Panda3D

loaderFileTypeRegistry.cxx

00001 // Filename: loaderFileTypeRegistry.cxx
00002 // Created by:  drose (20Jun00)
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 "loaderFileTypeRegistry.h"
00016 #include "loaderFileType.h"
00017 #include "config_pgraph.h"
00018 
00019 #include "load_dso.h"
00020 #include "string_utils.h"
00021 #include "indent.h"
00022 
00023 #include <algorithm>
00024 
00025 LoaderFileTypeRegistry *LoaderFileTypeRegistry::_global_ptr;
00026 
00027 ////////////////////////////////////////////////////////////////////
00028 //     Function: LoaderFileTypeRegistry::Constructor
00029 //       Access: Public
00030 //  Description:
00031 ////////////////////////////////////////////////////////////////////
00032 LoaderFileTypeRegistry::
00033 LoaderFileTypeRegistry() {
00034 }
00035 
00036 ////////////////////////////////////////////////////////////////////
00037 //     Function: LoaderFileTypeRegistry::Destructor
00038 //       Access: Public
00039 //  Description:
00040 ////////////////////////////////////////////////////////////////////
00041 LoaderFileTypeRegistry::
00042 ~LoaderFileTypeRegistry() {
00043 }
00044 
00045 ////////////////////////////////////////////////////////////////////
00046 //     Function: LoaderFileTypeRegistry::register_type
00047 //       Access: Public
00048 //  Description: Defines a new LoaderFileType in the universe.
00049 ////////////////////////////////////////////////////////////////////
00050 void LoaderFileTypeRegistry::
00051 register_type(LoaderFileType *type) {
00052   // Make sure we haven't already registered this type.
00053   if (find(_types.begin(), _types.end(), type) != _types.end()) {
00054     if (loader_cat->is_debug()) {
00055       loader_cat->debug()
00056         << "Attempt to register LoaderFileType " << type->get_name()
00057         << " (" << type->get_type() << ") more than once.\n";
00058     }
00059     return;
00060   }
00061 
00062   _types.push_back(type);
00063 
00064   record_extension(type->get_extension(), type);
00065 
00066   vector_string words;
00067   extract_words(type->get_additional_extensions(), words);
00068   vector_string::const_iterator wi;
00069   for (wi = words.begin(); wi != words.end(); ++wi) {
00070     record_extension(*wi, type);
00071   }
00072 }
00073 
00074 ////////////////////////////////////////////////////////////////////
00075 //     Function: LoaderFileTypeRegistry::register_deferred_type
00076 //       Access: Public
00077 //  Description: Records a type associated with a particular extension
00078 //               to be loaded in the future.  The named library will
00079 //               be dynamically loaded the first time files of this
00080 //               extension are loaded; presumably this library will
00081 //               call register_type() when it initializes, thus making
00082 //               the extension loadable.
00083 ////////////////////////////////////////////////////////////////////
00084 void LoaderFileTypeRegistry::
00085 register_deferred_type(const string &extension, const string &library) {
00086   string dcextension = downcase(extension);
00087 
00088   Extensions::const_iterator ei;
00089   ei = _extensions.find(dcextension);
00090   if (ei != _extensions.end()) {
00091     // We already have a loader for this type; no need to register
00092     // another one.
00093     if (loader_cat->is_debug()) {
00094       loader_cat->debug()
00095         << "Attempt to register loader library " << library
00096         << " (" << dcextension << ") when extension is already known.\n";
00097     }
00098     return;
00099   }
00100 
00101   DeferredTypes::const_iterator di;
00102   di = _deferred_types.find(dcextension);
00103   if (di != _deferred_types.end()) {
00104     if ((*di).second == library) {
00105       if (loader_cat->is_debug()) {
00106         loader_cat->debug()
00107           << "Attempt to register loader library " << library
00108           << " (" << dcextension << ") more than once.\n";
00109       }
00110       return;
00111     } else {
00112       if (loader_cat->is_debug()) {
00113         loader_cat->debug()
00114           << "Multiple libraries registered that use the extension "
00115           << dcextension << "\n";
00116       }
00117     }
00118   }
00119 
00120   _deferred_types[dcextension] = library;
00121 }
00122 
00123 ////////////////////////////////////////////////////////////////////
00124 //     Function: LoaderFileTypeRegistry::get_num_types
00125 //       Access: Published
00126 //  Description: Returns the total number of types registered.
00127 ////////////////////////////////////////////////////////////////////
00128 int LoaderFileTypeRegistry::
00129 get_num_types() const {
00130   return _types.size();
00131 }
00132 
00133 ////////////////////////////////////////////////////////////////////
00134 //     Function: LoaderFileTypeRegistry::get_type
00135 //       Access: Published
00136 //  Description: Returns the nth type registered.
00137 ////////////////////////////////////////////////////////////////////
00138 LoaderFileType *LoaderFileTypeRegistry::
00139 get_type(int n) const {
00140   nassertr(n >= 0 && n < (int)_types.size(), NULL);
00141   return _types[n];
00142 }
00143 
00144 ////////////////////////////////////////////////////////////////////
00145 //     Function: LoaderFileTypeRegistry::get_type_from_extension
00146 //       Access: Published
00147 //  Description: Determines the type of the file based on the indicated
00148 //               extension (without a leading dot).  Returns NULL if
00149 //               the extension matches no known file types.
00150 ////////////////////////////////////////////////////////////////////
00151 LoaderFileType *LoaderFileTypeRegistry::
00152 get_type_from_extension(const string &extension) {
00153   string dcextension = downcase(extension);
00154 
00155   Extensions::const_iterator ei;
00156   ei = _extensions.find(dcextension);
00157   if (ei == _extensions.end()) {
00158     // Nothing matches that extension.  Do we have a deferred type?
00159 
00160     DeferredTypes::iterator di;
00161     di = _deferred_types.find(dcextension);
00162     if (di != _deferred_types.end()) {
00163       // We do!  Try to load the deferred library on-the-fly.  Note
00164       // that this is a race condition if we support threaded loading;
00165       // this whole function needs to be protected from multiple
00166       // entry.
00167       string name = (*di).second;
00168       Filename dlname = Filename::dso_filename("lib" + name + ".so");
00169       _deferred_types.erase(di);
00170 
00171       loader_cat->info()
00172         << "loading file type module: " << name << endl;
00173       void *tmp = load_dso(get_plugin_path().get_value(), dlname);
00174       if (tmp == (void *)NULL) {
00175         loader_cat->warning()
00176           << "Unable to load " << dlname.to_os_specific() << ": " 
00177           << load_dso_error() << endl;
00178         return NULL;
00179       }
00180 
00181       // Now try again to find the LoaderFileType.
00182       ei = _extensions.find(dcextension);
00183     }
00184   }
00185 
00186   if (ei == _extensions.end()) {
00187     // Nothing matches that extension, even after we've checked for a
00188     // deferred type description.
00189     return NULL;
00190   }
00191 
00192   return (*ei).second;
00193 }
00194 
00195 ////////////////////////////////////////////////////////////////////
00196 //     Function: LoaderFileTypeRegistry::write
00197 //       Access: Published
00198 //  Description: Writes a list of supported file types to the
00199 //               indicated output stream, one per line.
00200 ////////////////////////////////////////////////////////////////////
00201 void LoaderFileTypeRegistry::
00202 write(ostream &out, int indent_level) const {
00203   if (_types.empty()) {
00204     indent(out, indent_level) << "(No file types are known).\n";
00205   } else {
00206     Types::const_iterator ti;
00207     for (ti = _types.begin(); ti != _types.end(); ++ti) {
00208       LoaderFileType *type = (*ti);
00209       string name = type->get_name();
00210       indent(out, indent_level) << name;
00211       indent(out, max(30 - (int)name.length(), 0))
00212         << "  ." << type->get_extension() << "\n";
00213     }
00214   }
00215 
00216   if (!_deferred_types.empty()) {
00217     indent(out, indent_level) << "Also available:";
00218     DeferredTypes::const_iterator di;
00219     for (di = _deferred_types.begin(); di != _deferred_types.end(); ++di) {
00220       const string &extension = (*di).first;
00221       out << " ." << extension;
00222     }
00223     out << "\n";
00224   }
00225 }
00226 
00227 ////////////////////////////////////////////////////////////////////
00228 //     Function: LoaderFileTypeRegistry::get_global_ptr
00229 //       Access: Published, Static
00230 //  Description: Returns a pointer to the global LoaderFileTypeRegistry
00231 //               object.
00232 ////////////////////////////////////////////////////////////////////
00233 LoaderFileTypeRegistry *LoaderFileTypeRegistry::
00234 get_global_ptr() {
00235   if (_global_ptr == (LoaderFileTypeRegistry *)NULL) {
00236     _global_ptr = new LoaderFileTypeRegistry;
00237   }
00238   return _global_ptr;
00239 }
00240 
00241 ////////////////////////////////////////////////////////////////////
00242 //     Function: LoaderFileTypeRegistry::record_extension
00243 //       Access: Private
00244 //  Description: Records a filename extension recognized by a loader
00245 //               file type.
00246 ////////////////////////////////////////////////////////////////////
00247 void LoaderFileTypeRegistry::
00248 record_extension(const string &extension, LoaderFileType *type) {
00249   string dcextension = downcase(extension);
00250   Extensions::const_iterator ei;
00251   ei = _extensions.find(dcextension);
00252   if (ei != _extensions.end()) {
00253     if (loader_cat->is_debug()) {
00254       loader_cat->debug()
00255         << "Multiple LoaderFileTypes registered that use the extension "
00256         << dcextension << "\n";
00257     }
00258   } else {
00259     _extensions.insert(Extensions::value_type(dcextension, type));
00260   }
00261 
00262   _deferred_types.erase(dcextension);
00263 }
 All Classes Functions Variables Enumerations