00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "pnmFileTypeRegistry.h"
00016 #include "pnmFileType.h"
00017 #include "config_pnmimage.h"
00018
00019 #include "string_utils.h"
00020 #include "indent.h"
00021 #include "pset.h"
00022
00023 #include <algorithm>
00024
00025 PNMFileTypeRegistry *PNMFileTypeRegistry::_global_ptr;
00026
00027
00028
00029
00030
00031
00032 PNMFileTypeRegistry::
00033 PNMFileTypeRegistry() {
00034 _requires_sort = false;
00035 }
00036
00037
00038
00039
00040
00041
00042 PNMFileTypeRegistry::
00043 ~PNMFileTypeRegistry() {
00044 }
00045
00046
00047
00048
00049
00050
00051 void PNMFileTypeRegistry::
00052 register_type(PNMFileType *type) {
00053 if (pnmimage_cat->is_debug()) {
00054 pnmimage_cat->debug()
00055 << "Registering image type " << type->get_name() << "\n";
00056 }
00057
00058
00059 Handles::iterator hi = _handles.find(type->get_type());
00060 if (hi != _handles.end()) {
00061 pnmimage_cat->warning()
00062 << "Attempt to register PNMFileType " << type->get_name()
00063 << " (" << type->get_type() << ") more than once.\n";
00064 return;
00065 }
00066
00067 _types.push_back(type);
00068 _handles.insert(Handles::value_type(type->get_type(), type));
00069
00070
00071 pset<string> unique_extensions;
00072 int num_extensions = type->get_num_extensions();
00073 for (int i = 0; i < num_extensions; i++) {
00074 string extension = downcase(type->get_extension(i));
00075
00076 if (!unique_extensions.insert(extension).second) {
00077 pnmimage_cat->warning()
00078 << "PNMFileType " << type->get_name()
00079 << " (" << type->get_type() << ") defined extension "
00080 << extension << " more than once.\n";
00081 }
00082 }
00083
00084 pset<string>::iterator ui;
00085 for (ui = unique_extensions.begin(); ui != unique_extensions.end(); ++ui) {
00086 _extensions[*ui].push_back(type);
00087 }
00088
00089 _requires_sort = true;
00090 }
00091
00092
00093
00094
00095
00096
00097 int PNMFileTypeRegistry::
00098 get_num_types() const {
00099 if (_requires_sort) {
00100 ((PNMFileTypeRegistry *)this)->sort_preferences();
00101 }
00102 return _types.size();
00103 }
00104
00105
00106
00107
00108
00109
00110 PNMFileType *PNMFileTypeRegistry::
00111 get_type(int n) const {
00112 nassertr(n >= 0 && n < (int)_types.size(), NULL);
00113 return _types[n];
00114 }
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124 PNMFileType *PNMFileTypeRegistry::
00125 get_type_from_extension(const string &filename) const {
00126 if (_requires_sort) {
00127 ((PNMFileTypeRegistry *)this)->sort_preferences();
00128 }
00129
00130
00131
00132
00133
00134 string extension;
00135 size_t dot = filename.rfind('.');
00136
00137 if (dot == string::npos) {
00138 extension = filename;
00139 } else {
00140 extension = filename.substr(dot + 1);
00141 }
00142
00143 #ifdef HAVE_ZLIB
00144 if (extension == "pz") {
00145
00146
00147
00148 size_t prev_dot = filename.rfind('.', dot - 1);
00149 if (prev_dot == string::npos) {
00150 extension = filename.substr(0, dot);
00151 } else {
00152 extension = filename.substr(prev_dot + 1, dot - prev_dot - 1);
00153 }
00154 }
00155 #endif // HAVE_ZLIB
00156
00157 if (extension.find('/') != string::npos) {
00158
00159
00160
00161 extension = "";
00162 }
00163
00164 Extensions::const_iterator ei;
00165 ei = _extensions.find(extension);
00166 if (ei == _extensions.end() || (*ei).second.empty()) {
00167
00168
00169
00170 ei = _extensions.find(downcase(extension));
00171
00172 if (ei == _extensions.end() || (*ei).second.empty()) {
00173
00174 return NULL;
00175 }
00176 }
00177
00178
00179 return (*ei).second.front();
00180 }
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191 PNMFileType *PNMFileTypeRegistry::
00192 get_type_from_magic_number(const string &magic_number) const {
00193 if (_requires_sort) {
00194 ((PNMFileTypeRegistry *)this)->sort_preferences();
00195 }
00196
00197 Types::const_iterator ti;
00198 for (ti = _types.begin(); ti != _types.end(); ++ti) {
00199 PNMFileType *type = (*ti);
00200 if (type->has_magic_number() &&
00201 type->matches_magic_number(magic_number)) {
00202 return type;
00203 }
00204 }
00205
00206 return NULL;
00207 }
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217 PNMFileType *PNMFileTypeRegistry::
00218 get_type_by_handle(TypeHandle handle) const {
00219 Handles::const_iterator hi;
00220 hi = _handles.find(handle);
00221 if (hi != _handles.end()) {
00222 return (*hi).second;
00223 }
00224
00225 return (PNMFileType *)NULL;
00226 }
00227
00228
00229
00230
00231
00232
00233
00234 void PNMFileTypeRegistry::
00235 write(ostream &out, int indent_level) const {
00236 if (_types.empty()) {
00237 indent(out, indent_level) << "(No image types are known).\n";
00238 } else {
00239 Types::const_iterator ti;
00240 for (ti = _types.begin(); ti != _types.end(); ++ti) {
00241 PNMFileType *type = (*ti);
00242 string name = type->get_name();
00243 indent(out, indent_level) << name;
00244 indent(out, max(30 - (int)name.length(), 0)) << " ";
00245
00246 int num_extensions = type->get_num_extensions();
00247 if (num_extensions == 1) {
00248 out << "." << type->get_extension(0);
00249 } else if (num_extensions > 1) {
00250 out << "." << type->get_extension(0);
00251 for (int i = 1; i < num_extensions; i++) {
00252 out << ", ." << type->get_extension(i);
00253 }
00254 }
00255 out << "\n";
00256 }
00257 }
00258 }
00259
00260
00261
00262
00263
00264
00265
00266 PNMFileTypeRegistry *PNMFileTypeRegistry::
00267 get_global_ptr() {
00268 if (_global_ptr == (PNMFileTypeRegistry *)NULL) {
00269 _global_ptr = new PNMFileTypeRegistry;
00270 }
00271 return _global_ptr;
00272 }
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284 void PNMFileTypeRegistry::
00285 sort_preferences() {
00286
00287
00288 _requires_sort = false;
00289 }