open_toontown_panda3d/direct/src/dcparser/dcFile.cxx

260 lines
8.1 KiB
C++

// Filename: dcFile.cxx
// Created by: drose (05Oct00)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "dcFile.h"
#include "dcParserDefs.h"
#include "dcLexerDefs.h"
#include "hashGenerator.h"
#ifdef WITHIN_PANDA
#include "filename.h"
#include "config_express.h"
#include "virtualFileSystem.h"
#endif
////////////////////////////////////////////////////////////////////
// Function: DCFile::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
DCFile::
DCFile() {
}
////////////////////////////////////////////////////////////////////
// Function: DCFile::Destructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
DCFile::
~DCFile() {
Classes::iterator ci;
for (ci = _classes.begin(); ci != _classes.end(); ++ci) {
delete (*ci);
}
}
////////////////////////////////////////////////////////////////////
// Function: DCFile::read
// Access: Published
// Description: Opens and reads the indicated .dc file by name. The
// distributed classes defined in the file will be
// appended to the set of distributed classes already
// recorded, if any.
//
// Returns true if the file is successfully read, false
// if there was an error (in which case the file might
// have been partially read).
////////////////////////////////////////////////////////////////////
bool DCFile::
read(Filename filename) {
ifstream in;
#ifdef WITHIN_PANDA
filename.set_text();
if (use_vfs) {
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
istream *in = vfs->open_read_file(filename);
if (in == (istream *)NULL) {
cerr << "Cannot open " << filename << " for reading.\n";
return false;
}
bool okflag = read(*in, filename);
delete in;
return okflag;
}
filename.open_read(in);
#else
in.open(filename.c_str());
#endif
if (!in) {
cerr << "Cannot open " << filename << " for reading.\n";
return false;
}
return read(in, filename);
}
////////////////////////////////////////////////////////////////////
// Function: DCFile::read
// Access: Published
// Description: Parses the already-opened input stream for
// distributed class descriptions. The filename
// parameter is optional and is only used when reporting
// errors.
//
// The distributed classes defined in the file will be
// appended to the set of distributed classes already
// recorded, if any.
//
// Returns true if the file is successfully read, false
// if there was an error (in which case the file might
// have been partially read).
////////////////////////////////////////////////////////////////////
bool DCFile::
read(istream &in, const string &filename) {
dc_init_parser(in, filename, *this);
dcyyparse();
dc_cleanup_parser();
return (dc_error_count() == 0);
}
////////////////////////////////////////////////////////////////////
// Function: DCFile::write
// Access: Published
// Description: Opens the indicated filename for output and writes a
// parseable description of all the known distributed
// classes to the file.
//
// Returns true if the description is successfully
// written, false otherwise.
////////////////////////////////////////////////////////////////////
bool DCFile::
write(Filename filename, bool brief) const {
ofstream out;
#ifdef WITHIN_PANDA
filename.set_text();
filename.open_write(out);
#else
out.open(filename.c_str());
#endif
if (!out) {
cerr << "Can't open " << filename << " for output.\n";
return false;
}
return write(out, brief);
}
////////////////////////////////////////////////////////////////////
// Function: DCFile::write
// Access: Published
// Description: Writes a parseable description of all the known
// distributed classes to the stream.
//
// Returns true if the description is successfully
// written, false otherwise.
////////////////////////////////////////////////////////////////////
bool DCFile::
write(ostream &out, bool brief) const {
Classes::const_iterator ci;
for (ci = _classes.begin(); ci != _classes.end(); ++ci) {
(*ci)->write(out, brief, 0);
out << "\n";
}
return !out.fail();
}
////////////////////////////////////////////////////////////////////
// Function: DCFile::get_num_classes
// Access: Published
// Description: Returns the number of classes read from the .dc
// file(s).
////////////////////////////////////////////////////////////////////
int DCFile::
get_num_classes() {
return _classes.size();
}
////////////////////////////////////////////////////////////////////
// Function: DCFile::get_class
// Access: Published
// Description: Returns the nth class read from the .dc file(s).
////////////////////////////////////////////////////////////////////
DCClass *DCFile::
get_class(int n) {
nassertr(n >= 0 && n < (int)_classes.size(), NULL);
return _classes[n];
}
////////////////////////////////////////////////////////////////////
// Function: DCFile::get_class_by_name
// Access: Published
// Description: Returns the class that has the indicated name, or
// NULL if there is no such class.
////////////////////////////////////////////////////////////////////
DCClass *DCFile::
get_class_by_name(const string &name) {
ClassesByName::const_iterator ni;
ni = _classes_by_name.find(name);
if (ni != _classes_by_name.end()) {
return (*ni).second;
}
return (DCClass *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: DCFile::get_hash
// Access: Published
// Description: Returns a 32-bit hash index associated with this
// file. This number is guaranteed to be consistent if
// the contents of the file have not changed, and it is
// very likely to be different if the contents of the
// file do change.
////////////////////////////////////////////////////////////////////
unsigned long DCFile::
get_hash() const {
HashGenerator hashgen;
generate_hash(hashgen);
return hashgen.get_hash();
}
////////////////////////////////////////////////////////////////////
// Function: DCFile::generate_hash
// Access: Public, Virtual
// Description: Accumulates the properties of this file into the
// hash.
////////////////////////////////////////////////////////////////////
void DCFile::
generate_hash(HashGenerator &hashgen) const {
hashgen.add_int(_classes.size());
Classes::const_iterator ci;
for (ci = _classes.begin(); ci != _classes.end(); ++ci) {
(*ci)->generate_hash(hashgen);
}
}
////////////////////////////////////////////////////////////////////
// Function: DCFile::add_class
// Access: Public
// Description: Adds the newly-allocated distributed class definition
// to the file. The DCFile becomes the owner of the
// pointer and will delete it when it destructs.
// Returns true if the class is successfully added, or
// false if there was a name conflict.
////////////////////////////////////////////////////////////////////
bool DCFile::
add_class(DCClass *dclass) {
bool inserted = _classes_by_name.insert
(ClassesByName::value_type(dclass->_name, dclass)).second;
if (!inserted) {
return false;
}
dclass->_number = get_num_classes();
_classes.push_back(dclass);
return true;
}