Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

resource_manager_file.cpp

Go to the documentation of this file.
00001 /*
00002         $Id: resource_manager_file.cpp,v 1.2 2000/06/04 19:02:55 sphair Exp $
00003 
00004         ------------------------------------------------------------------------
00005         ClanLib, the platform independent game SDK.
00006 
00007         This library is distributed under the GNU LIBRARY GENERAL PUBLIC LICENSE
00008         version 2. See COPYING for details.
00009 
00010         For a total list of contributers see CREDITS.
00011 
00012         ------------------------------------------------------------------------
00013 */
00014 
00015 #include "Core/precomp.h"
00016 #include "resource_manager_file.h"
00017 #include "resource_tokenizer.h"
00018 #include <API/Core/System/clanstring.h>
00019 #include <API/Core/System/error.h>
00020 #include <API/Core/System/cl_assert.h>
00021 
00022 CL_ResourceManager* CL_ResourceManager::create(
00023         const char *config_file,
00024         CL_InputSourceProvider *provider,
00025         bool read_directly_from_source,
00026         bool delete_inputsource_provider)
00027 {
00028         return new CL_ResourceManager_File(
00029                 config_file,
00030                 provider,
00031                 read_directly_from_source,
00032                 delete_inputsource_provider);
00033 }
00034 
00035 CL_ResourceManager *CL_ResourceManager::create(
00036         const char *file_name,
00037         const bool is_datafile)
00038 {
00039         return new CL_ResourceManager_File(
00040                 file_name,
00041                 is_datafile);
00042 }
00043 
00044 CL_ResourceManager_File::CL_ResourceManager_File(
00045         const char *config_file,
00046         CL_InputSourceProvider *provider,
00047         bool read_directly_from_source,
00048         bool delete_inputsource_provider)
00049 {
00050         filename = config_file;
00051         resource_provider = provider;
00052         delete_resource_provider = delete_inputsource_provider;
00053         from_source = read_directly_from_source;
00054         
00055         if (provider == NULL)
00056         {
00057                 if (read_directly_from_source)
00058                         resource_provider = CL_InputSourceProvider::create_file_provider("");
00059                 else
00060                         resource_provider = CL_InputSourceProvider::create_datafile_provider(filename.c_str());
00061                 
00062                 delete_resource_provider = true;
00063         }
00064         
00065         parse();
00066 }
00067 
00068 CL_ResourceManager_File::CL_ResourceManager_File(
00069         const char *file_name,
00070         const bool is_datafile)
00071 {
00072         filename = file_name;
00073         delete_resource_provider = true;
00074 
00075         if (is_datafile)
00076         {
00077                 resource_provider = CL_InputSourceProvider::create_datafile_provider(filename.c_str());
00078                 from_source = false;
00079         }
00080         else
00081         {
00082                 resource_provider = CL_InputSourceProvider::create_file_provider("");
00083                 from_source = true;
00084         }
00085         
00086         parse();
00087 }
00088 
00089 CL_ResourceManager_File::~CL_ResourceManager_File()
00090 {
00091         for (
00092                 std::list<CL_Resource*>::iterator it = resources.begin();
00093                 it != resources.end();
00094                 it++)
00095         {
00096                 if ((*it)->get_load_count() != 0)
00097                 {
00098                         CL_String warning;
00099                         warning << "Warning, resource load balance is not zero: ";
00100                         warning << (*it)->get_name() << ", " << (*it)->get_load_count();
00101 
00102                         cl_info(0, warning.get_string());
00103                 }
00104                 delete *it;
00105         }
00106 }
00107 
00108 void CL_ResourceManager_File::load_all_resources()
00109 {
00110         for (
00111                 std::list<CL_Resource*>::iterator it = resources.begin();
00112                 it != resources.end();
00113                 it++)
00114         {
00115                 (*it)->load();
00116         }
00117 }
00118 
00119 void CL_ResourceManager_File::unload_all_resources()
00120 {
00121         for (
00122                 std::list<CL_Resource*>::iterator it = resources.begin();
00123                 it != resources.end();
00124                 it++)
00125         {
00126                 while ((*it)->get_load_count() > 0)
00127                         (*it)->unload();
00128         }
00129 }
00130 
00131 void CL_ResourceManager_File::load_section(const char *section_name)
00132 {
00133         CL_String prefix = section_name;
00134         prefix << "/";
00135         
00136         int prefix_len = prefix.get_length();
00137 
00138         for (
00139                 std::list<CL_Resource*>::iterator it = resources.begin();
00140                 it != resources.end();
00141                 it++)
00142         {
00143                 CL_String name = (*it)->get_name();
00144                 if (name.mid(0, prefix_len) == prefix)
00145                 {
00146                         (*it)->load();
00147                 }
00148         }
00149 }
00150 
00151 void CL_ResourceManager_File::unload_section(const char *section_name)
00152 {
00153         CL_String prefix = section_name;
00154         prefix << "/";
00155         
00156         int prefix_len = prefix.get_length();
00157 
00158         for (
00159                 std::list<CL_Resource*>::iterator it = resources.begin();
00160                 it != resources.end();
00161                 it++)
00162         {
00163                 CL_String name = (*it)->get_name();
00164                 if (name.mid(0, prefix_len) == prefix)
00165                 {
00166                         while ((*it)->get_load_count() > 0)
00167                                 (*it)->unload();
00168                 }
00169         }
00170 }
00171 
00172 CL_Resource *CL_ResourceManager_File::get_resource(std::string res_id)
00173 {
00174         for (
00175                 std::list<CL_Resource*>::iterator it = resources.begin();
00176                 it != resources.end();
00177                 it++)
00178         {
00179                 if ((*it)->get_name() == res_id) return *it;
00180         }
00181         
00182         CL_String err;
00183         err << "Resource " << res_id << " not found.";
00184         throw CL_Error(err.get_string());
00185         
00186         return NULL;
00187 }
00188 
00189 std::list<std::string> *CL_ResourceManager_File::get_all_resources()
00190 {
00191         std::list<std::string> *retval = new std::list<std::string>;
00192 
00193         for (
00194                 std::list<CL_Resource*>::iterator it = resources.begin();
00195                 it != resources.end();
00196                 it++)
00197         {
00198                 retval->push_back((*it)->get_name());
00199         }
00200         
00201         return retval;
00202 }
00203 
00204 std::list<std::string> *CL_ResourceManager_File::get_resources_of_type(std::string type_id)
00205 {
00206         std::list<std::string> *retval = new std::list<std::string>;
00207 
00208         for (
00209                 std::list<CL_Resource*>::iterator it = resources.begin();
00210                 it != resources.end();
00211                 it++)
00212         {
00213                 if ((*it)->get_type() == type_id)
00214                         retval->push_back((*it)->get_name());
00215         }
00216 
00217         return retval;
00218 }
00219 
00220 CL_InputSourceProvider *CL_ResourceManager_File::get_resource_provider()
00221 {
00222         return resource_provider;
00223 }
00224 
00225 void CL_ResourceManager_File::parse()
00226 {
00227         CL_InputSource *input;
00228 
00229         if (from_source) input = resource_provider->open_source(filename.c_str());
00230         else input = resource_provider->open_source(default_scriptfile_id);
00231         
00232         CL_ResourceTokenizer lexer(filename, input);
00233 
00234         while (true)
00235         {
00236                 std::string token = lexer.get_next_token();
00237                 if (token == "") break;
00238                 
00239                 if (token == "location") // obsolete. Will read it but issues a warning.
00240                 {
00241                         token = lexer.get_next_token();
00242                         if (token != "=")
00243                                 throw CL_Error(lexer.write_error("Missing '=' following global 'location'-declaration"));
00244                         
00245                         token = lexer.get_next_token();
00246                         if (token != "datafile")
00247                                 throw CL_Error(lexer.write_error("Syntax error following global 'location'-declaration"));
00248                         
00249                         token = lexer.get_next_token();
00250                         if (token != "(")
00251                                 throw CL_Error(lexer.write_error("Missing '(' following 'datafile' keyword"));
00252 
00253                         token = lexer.get_next_token();
00254 
00255                         token = lexer.get_next_token();
00256                         if (token != ")")
00257                                 throw CL_Error(lexer.write_error("Missing ')' following datafile filename"));
00258 
00259                         token = lexer.get_next_token();
00260                         if (token != ";")
00261                                 throw CL_Error(lexer.write_error("Missing ';' following datafile filename"));
00262 
00263                         cl_info(0, "The location keyword is obsolete in resource files. Please don't use it anymore.");
00264                 }
00265 /*              else if (token == "include")
00266                 {
00267                         parse_include(lexer);
00268                 }
00269 */              else // assume it is a section body (resource or section)
00270                 {
00271                         parse_section_body(token, lexer, "");
00272                 }
00273         }
00274 }
00275 
00276 void CL_ResourceManager_File::parse_include(CL_ResourceTokenizer &lexer)
00277 {
00278 /*      std::string input_file = lexer.get_next_token();
00279         
00280         std::string token = lexer.get_next_token();
00281         if (token != ";")
00282                 throw CL_Error(lexer.write_error("Missing ';' following include"));
00283 
00284         CL_ResourceManager *manager = CL_ResourceManager::create(input_file.c_str(), NULL, true);
00285 */      
00286 /*    std::list<std::string> *resource_list = manager->get_all_resources();
00287 
00288         for (
00289                 std::list<std::string>::iterator it = resource_list->begin();
00290                 it != resource_list->end();
00291                 it++)
00292         {
00293                 CL_Resource *res = manager->get_resource(*it);
00294 
00295                 if (res != NULL)
00296                 {
00297                         resources.push_back(res);
00298                 }
00299         }
00300 
00301         delete resource_list;
00302         delete manager;
00303 */
00304 }
00305 
00306 void CL_ResourceManager_File::parse_section_body(
00307         std::string token,
00308         CL_ResourceTokenizer &lexer,
00309         std::string prefix)
00310 {
00311         if (token == "section")
00312         {
00313                 CL_String section_prefix = prefix;
00314                 section_prefix << lexer.get_next_token();
00315                 section_prefix << "/";
00316 
00317                 token = lexer.get_next_token();
00318                 if (token != "{")
00319                         throw CL_Error(lexer.write_error("Missing '{'"));
00320                         
00321                 while (true)
00322                 {
00323                         token = lexer.get_next_token();
00324                         if (token == "}") break;
00325                         parse_section_body(token, lexer, section_prefix);
00326                 }
00327         }
00328         else // must be a resource then
00329         {
00330                 CL_String name = prefix;
00331                 name << token;
00332 
00333                 token = lexer.get_next_token();
00334                 if (token != "=")
00335                 {
00336                         CL_String err;
00337                         err << "Missing '=' following declaration of resource '" << name << "'";
00338                         throw CL_Error(lexer.write_error(err));
00339                 }
00340 
00341                 // read the location (if available):
00342                 std::string location;
00343                 token = lexer.get_next_token();
00344                 if(token == "(")
00345                         location = "";
00346                 else {
00347                         location = token;
00348                         token = lexer.get_next_token();
00349                 }
00350 
00351                 // read resource options:
00352                 if (token != "(")
00353                 {
00354                         CL_String err;
00355                         err << "Missing '(' following declaration of resource '" << name << "'";
00356                         throw CL_Error(lexer.write_error(err));
00357                 }
00358 
00359                 CL_ResourceOptions *options = new CL_ResourceOptions(this);
00360                 while (true)
00361                 {
00362                         token = lexer.get_next_token();
00363                         if (token == ")") break;
00364                         
00365                         std::string option_name = token;
00366                         
00367                         token = lexer.get_next_token();
00368                         if (token != "=")
00369                         {
00370                                 CL_String err;
00371                                 err << "Syntax error in options following declaration of resource '" << name << "'";
00372                                 throw CL_Error(lexer.write_error(err));
00373                         }
00374                         
00375                         token = lexer.get_next_token();
00376                         if (token == "(") // it is a value list
00377                         {
00378                                 std::list<std::string> *value_list = new std::list<std::string>;
00379 
00380                                 while (true)
00381                                 {
00382                                         token = lexer.get_next_token();
00383                                         if (token == ")") break;
00384 
00385                                         value_list->push_back(token);
00386                                         
00387                                         token = lexer.get_next_token();
00388                                         if (token == ")") break;
00389                                         if (token != ",")
00390                                         {
00391                                                 delete value_list;
00392 
00393                                                 CL_String err;
00394                                                 err << "Missing ',' or ')' following declaration of multiple option values in option '" <<
00395                                                            option_name << "' in resource '" << name << "' (found '" << token << "')";
00396                                                 throw CL_Error(lexer.write_error(err));
00397                                         }
00398                                 }
00399                                 
00400                                 options->add(new CL_ResourceOption(option_name, value_list));
00401                         }
00402                         else
00403                         {
00404                                 std::string option_value = token;
00405                                 
00406                                 options->add(new CL_ResourceOption(option_name, option_value));
00407                         }
00408 
00409                         token = lexer.get_next_token();
00410                         if (token == ")") break;
00411                         if (token != ",")
00412                         {
00413                                 CL_String err;
00414                                 err << "Syntax error in options following declaration of resource '" << name << "'";
00415                                 throw CL_Error(lexer.write_error(err));
00416                         }
00417                 }
00418                 
00419                 token = lexer.get_next_token();
00420                 if (token != ";")
00421                 {
00422                         CL_String err;
00423                         err << "Missing ';' following declaration of resource '" << name << "'";
00424                         throw CL_Error(lexer.write_error(err));
00425                 }
00426                 
00427                 if (options->exists("type") == false)
00428                 {
00429                         CL_String err;
00430                         err << "No type declared for resource '" << name << "'";
00431                         throw CL_Error(lexer.write_error(err));
00432                 }
00433                 
00434                 CL_Resource *res = create_resource(name, location, *options);
00435                 if (res != NULL) resources.push_back(res);
00436                 else
00437                 {
00438                         CL_String err;
00439                         err << "Unknown type '" << options->get_value("type") << "' declared for resource '" << name << "'";
00440                         throw CL_Error(lexer.write_error(err));
00441                 }
00442         }
00443 }
00444 
00445 CL_Resource *CL_ResourceManager_File::create_resource(
00446         std::string name,
00447         std::string location,
00448         CL_ResourceOptions &options)
00449 {
00450         std::string type = options.get_value("type");
00451 
00452         for (
00453                 std::list<CL_ResourceType*>::iterator it = CL_ResourceType::resource_types.begin();
00454                 it != CL_ResourceType::resource_types.end();
00455                 it++)
00456         {
00457                 if ((*it)->get_type() == type)
00458                 {
00459                         if (from_source)
00460                         {
00461                                 return (*it)->create_from_location(
00462                                         name,
00463                                         location,
00464                                         &options,
00465                                         this);
00466                         }
00467                         else
00468                         {
00469                                 return (*it)->create_from_serialization(
00470                                         name,
00471                                         this);
00472                         }
00473                 }
00474         }
00475 
00476         return NULL;
00477 }

Generated at Wed Apr 4 19:54:03 2001 for ClanLib by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001