00001 // Filename: dcFile.cxx 00002 // Created by: drose (05Oct00) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved 00008 // 00009 // All use of this software is subject to the terms of the Panda 3d 00010 // Software license. You should have received a copy of this license 00011 // along with this source code; you will also find a current copy of 00012 // the license at http://www.panda3d.org/license.txt . 00013 // 00014 // To contact the maintainers of this program write to 00015 // panda3d@yahoogroups.com . 00016 // 00017 //////////////////////////////////////////////////////////////////// 00018 00019 #include "dcFile.h" 00020 #include "dcParserDefs.h" 00021 #include "dcLexerDefs.h" 00022 #include "hashGenerator.h" 00023 00024 #ifdef WITHIN_PANDA 00025 #include "filename.h" 00026 #include "config_express.h" 00027 #include "virtualFileSystem.h" 00028 #endif 00029 00030 00031 //////////////////////////////////////////////////////////////////// 00032 // Function: DCFile::Constructor 00033 // Access: Published 00034 // Description: 00035 //////////////////////////////////////////////////////////////////// 00036 DCFile:: 00037 DCFile() { 00038 } 00039 00040 //////////////////////////////////////////////////////////////////// 00041 // Function: DCFile::Destructor 00042 // Access: Published 00043 // Description: 00044 //////////////////////////////////////////////////////////////////// 00045 DCFile:: 00046 ~DCFile() { 00047 Classes::iterator ci; 00048 for (ci = _classes.begin(); ci != _classes.end(); ++ci) { 00049 delete (*ci); 00050 } 00051 } 00052 00053 //////////////////////////////////////////////////////////////////// 00054 // Function: DCFile::read 00055 // Access: Published 00056 // Description: Opens and reads the indicated .dc file by name. The 00057 // distributed classes defined in the file will be 00058 // appended to the set of distributed classes already 00059 // recorded, if any. 00060 // 00061 // Returns true if the file is successfully read, false 00062 // if there was an error (in which case the file might 00063 // have been partially read). 00064 //////////////////////////////////////////////////////////////////// 00065 bool DCFile:: 00066 read(Filename filename) { 00067 ifstream in; 00068 00069 #ifdef WITHIN_PANDA 00070 filename.set_text(); 00071 if (use_vfs) { 00072 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); 00073 istream *in = vfs->open_read_file(filename); 00074 if (in == (istream *)NULL) { 00075 cerr << "Cannot open " << filename << " for reading.\n"; 00076 return false; 00077 } 00078 bool okflag = read(*in, filename); 00079 delete in; 00080 return okflag; 00081 } 00082 filename.open_read(in); 00083 #else 00084 in.open(filename.c_str()); 00085 #endif 00086 00087 if (!in) { 00088 cerr << "Cannot open " << filename << " for reading.\n"; 00089 return false; 00090 } 00091 00092 return read(in, filename); 00093 } 00094 00095 //////////////////////////////////////////////////////////////////// 00096 // Function: DCFile::read 00097 // Access: Published 00098 // Description: Parses the already-opened input stream for 00099 // distributed class descriptions. The filename 00100 // parameter is optional and is only used when reporting 00101 // errors. 00102 // 00103 // The distributed classes defined in the file will be 00104 // appended to the set of distributed classes already 00105 // recorded, if any. 00106 // 00107 // Returns true if the file is successfully read, false 00108 // if there was an error (in which case the file might 00109 // have been partially read). 00110 //////////////////////////////////////////////////////////////////// 00111 bool DCFile:: 00112 read(istream &in, const string &filename) { 00113 dc_init_parser(in, filename, *this); 00114 dcyyparse(); 00115 dc_cleanup_parser(); 00116 00117 return (dc_error_count() == 0); 00118 } 00119 00120 //////////////////////////////////////////////////////////////////// 00121 // Function: DCFile::write 00122 // Access: Published 00123 // Description: Opens the indicated filename for output and writes a 00124 // parseable description of all the known distributed 00125 // classes to the file. 00126 // 00127 // Returns true if the description is successfully 00128 // written, false otherwise. 00129 //////////////////////////////////////////////////////////////////// 00130 bool DCFile:: 00131 write(Filename filename) const { 00132 ofstream out; 00133 00134 #ifdef WITHIN_PANDA 00135 filename.set_text(); 00136 filename.open_write(out); 00137 #else 00138 out.open(filename.c_str()); 00139 #endif 00140 00141 if (!out) { 00142 cerr << "Can't open " << filename << " for output.\n"; 00143 return false; 00144 } 00145 return write(out, filename); 00146 } 00147 00148 //////////////////////////////////////////////////////////////////// 00149 // Function: DCFile::write 00150 // Access: Published 00151 // Description: Writes a parseable description of all the known 00152 // distributed classes to the file. The filename 00153 // parameter is optional and is only used when reporting 00154 // errors. 00155 // 00156 // Returns true if the description is successfully 00157 // written, false otherwise. 00158 //////////////////////////////////////////////////////////////////// 00159 bool DCFile:: 00160 write(ostream &out, const string &filename) const { 00161 Classes::const_iterator ci; 00162 for (ci = _classes.begin(); ci != _classes.end(); ++ci) { 00163 (*ci)->write(out); 00164 out << "\n"; 00165 } 00166 00167 if (out.fail()) { 00168 cerr << "I/O error writing " << filename << ".\n"; 00169 return false; 00170 } 00171 00172 return true; 00173 } 00174 00175 //////////////////////////////////////////////////////////////////// 00176 // Function: DCFile::get_num_classes 00177 // Access: Published 00178 // Description: Returns the number of classes read from the .dc 00179 // file(s). 00180 //////////////////////////////////////////////////////////////////// 00181 int DCFile:: 00182 get_num_classes() { 00183 return _classes.size(); 00184 } 00185 00186 //////////////////////////////////////////////////////////////////// 00187 // Function: DCFile::get_class 00188 // Access: Published 00189 // Description: Returns the nth class read from the .dc file(s). 00190 //////////////////////////////////////////////////////////////////// 00191 DCClass *DCFile:: 00192 get_class(int n) { 00193 nassertr(n >= 0 && n < (int)_classes.size(), NULL); 00194 return _classes[n]; 00195 } 00196 00197 //////////////////////////////////////////////////////////////////// 00198 // Function: DCFile::get_class_by_name 00199 // Access: Published 00200 // Description: Returns the class that has the indicated name, or 00201 // NULL if there is no such class. 00202 //////////////////////////////////////////////////////////////////// 00203 DCClass *DCFile:: 00204 get_class_by_name(const string &name) { 00205 ClassesByName::const_iterator ni; 00206 ni = _classes_by_name.find(name); 00207 if (ni != _classes_by_name.end()) { 00208 return (*ni).second; 00209 } 00210 00211 return (DCClass *)NULL; 00212 } 00213 00214 //////////////////////////////////////////////////////////////////// 00215 // Function: DCFile::get_hash 00216 // Access: Published 00217 // Description: Returns a 32-bit hash index associated with this 00218 // file. This number is guaranteed to be consistent if 00219 // the contents of the file have not changed, and it is 00220 // very likely to be different if the contents of the 00221 // file do change. 00222 //////////////////////////////////////////////////////////////////// 00223 unsigned long DCFile:: 00224 get_hash() const { 00225 HashGenerator hashgen; 00226 generate_hash(hashgen); 00227 return hashgen.get_hash(); 00228 } 00229 00230 //////////////////////////////////////////////////////////////////// 00231 // Function: DCFile::generate_hash 00232 // Access: Public, Virtual 00233 // Description: Accumulates the properties of this file into the 00234 // hash. 00235 //////////////////////////////////////////////////////////////////// 00236 void DCFile:: 00237 generate_hash(HashGenerator &hashgen) const { 00238 hashgen.add_int(_classes.size()); 00239 Classes::const_iterator ci; 00240 for (ci = _classes.begin(); ci != _classes.end(); ++ci) { 00241 (*ci)->generate_hash(hashgen); 00242 } 00243 } 00244 00245 //////////////////////////////////////////////////////////////////// 00246 // Function: DCFile::add_class 00247 // Access: Public 00248 // Description: Adds the newly-allocated distributed class definition 00249 // to the file. The DCFile becomes the owner of the 00250 // pointer and will delete it when it destructs. 00251 // Returns true if the class is successfully added, or 00252 // false if there was a name conflict. 00253 //////////////////////////////////////////////////////////////////// 00254 bool DCFile:: 00255 add_class(DCClass *dclass) { 00256 bool inserted = _classes_by_name.insert 00257 (ClassesByName::value_type(dclass->_name, dclass)).second; 00258 00259 if (!inserted) { 00260 return false; 00261 } 00262 00263 dclass->_number = get_num_classes(); 00264 _classes.push_back(dclass); 00265 return true; 00266 }