00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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")
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
00266
00267
00268
00269 else
00270 {
00271 parse_section_body(token, lexer, "");
00272 }
00273 }
00274 }
00275
00276 void CL_ResourceManager_File::parse_include(CL_ResourceTokenizer &lexer)
00277 {
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
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
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
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
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 == "(")
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 }