00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "precomp.h"
00010 #include "API/Core/System/clanstring.h"
00011 #include "API/Core/Resources/resource_manager.h"
00012 #include "API/Core/IOData/inputsource.h"
00013 #include "API/GUI/component_style.h"
00014 #include "component_manager_generic.h"
00015 #include "component_tokenizer.h"
00016 #include "componentfile_preprocess.h"
00017
00018 std::map<std::string, CL_ComponentType *> CL_ComponentManager::component_types;
00019
00020 CL_ComponentManager *CL_ComponentManager::create(const char *resource_id, CL_ResourceManager *res_manager, CL_StyleManager *style)
00021 {
00022 return new CL_ComponentManager_Generic(resource_id, res_manager, style);
00023 }
00024
00025 CL_ComponentManager *CL_ComponentManager::create(const char *filename, bool is_datafile, CL_StyleManager *style)
00026 {
00027 return new CL_ComponentManager_Generic(filename, is_datafile, style);
00028 }
00029
00030 CL_ComponentManager_Generic::CL_ComponentManager_Generic(const char *filename, CL_ResourceManager *resources, CL_StyleManager *style)
00031 {
00032 this->filename = filename;
00033 this->resources = resources;
00034 style_manager = style;
00035
00036
00037 input = resources->get_resource_provider()->open_source(filename);
00038 parse();
00039 }
00040
00041 CL_ComponentManager_Generic::CL_ComponentManager_Generic(const char *filename, bool is_datafile, CL_StyleManager *style)
00042 {
00043 this->filename = filename;
00044 style_manager = style;
00045
00046
00047 if (is_datafile)
00048 {
00049 input = CL_InputSourceProvider::create_datafile_provider(filename)->open_source(filename);
00050 }
00051 else
00052 {
00053 input = CL_InputSourceProvider::create_file_provider(".")->open_source(filename);
00054 }
00055
00056 parse();
00057 }
00058
00059 CL_ComponentManager_Generic::~CL_ComponentManager_Generic()
00060 {
00061 std::vector<CL_Component *> components;
00062 get_root_component_list(components);
00063
00064 std::vector<CL_Component *>::iterator it;
00065 for (it = components.begin(); it != components.end(); it++)
00066 delete *it;
00067 }
00068
00069 void CL_ComponentManager_Generic::init_style_manager(const char *style_id)
00070 {
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 }
00084
00085 void CL_ComponentManager_Generic::create_components(std::multimap<int, CL_ComponentInfo *> &creation_sort_map)
00086 {
00087 std::multimap<int, CL_ComponentInfo *>::iterator it;
00088 for (it=creation_sort_map.begin();it!=creation_sort_map.end();it++)
00089 {
00090 CL_ComponentInfo *info = (*it).second;
00091
00092 if (info->component == NULL)
00093 {
00094 info->component = style_manager->create_component(
00095 info->type,
00096 info->options,
00097 NULL);
00098 }
00099
00100 if (!info->children.empty())
00101 {
00102 if (!info->component_type->is_container())
00103 {
00104 throw CL_Error("Internal component manager error");
00105 }
00106
00107 std::list<CL_ComponentInfo *>::iterator c_it;
00108 for (c_it=info->children.begin();c_it!=info->children.end();c_it++)
00109 {
00110 CL_ComponentInfo *child_info = *c_it;
00111 if (child_info->component == NULL)
00112 {
00113 child_info->component = style_manager->create_component(
00114 child_info->type,
00115 child_info->options,
00116 info->component);
00117 }
00118
00119 info->component->add_child(child_info->component, true);
00120 }
00121 info->children.clear();
00122 }
00123 }
00124 }
00125
00126 CL_Component *CL_ComponentManager_Generic::get_component(const char *component_id)
00127 {
00128 std::map<std::string, CL_ComponentManager_Generic::CL_ComponentInfo>::iterator it = component_map.find(component_id);
00129 if (it != component_map.end())
00130 {
00131 return (*it).second.component;
00132 }
00133 throw CL_Error("Unable to locate component");
00134 }
00135
00136 void CL_ComponentManager_Generic::get_root_component_list(std::vector<CL_Component *> &components)
00137 {
00138 std::map<std::string, CL_ComponentInfo>::iterator it;
00139 for (it = component_map.begin(); it != component_map.end();it++)
00140 {
00141 if ((*it).second.component->get_parent() == NULL)
00142 {
00143 components.push_back((*it).second.component);
00144 }
00145 }
00146 }
00147
00148 std::string CL_ComponentManager_Generic::preprocess_templates()
00149 {
00150 char *temp_data = new char[input->size()+1];
00151 input->read(temp_data, input->size());
00152 temp_data[input->size()] = 0;
00153 std::string file_data(temp_data);
00154 delete[] temp_data;
00155
00156 CL_Componentfile_Preprocess preprocessor(file_data, filename);
00157 return preprocessor;
00158 }
00159
00160 void CL_ComponentManager_Generic::parse()
00161 {
00162 CL_ComponentTokenizer lexer(preprocess_templates(), filename);
00163
00164 typedef std::pair<std::string, CL_ComponentInfo> named_component_t;
00165 std::stack<named_component_t> component_stack;
00166 std::multimap<int, CL_ComponentInfo *> creation_sort_map;
00167 std::map<std::string, int> component_id_enumerator;
00168
00169 enum EParseState
00170 {
00171 PARSE_GLOBAL,
00172 PARSE_COMPONENT_TYPE,
00173 PARSE_COMPONENT_NAME,
00174 PARSE_COMPONENT,
00175 PARSE_VARIABLE_NAME,
00176 PARSE_VARIABLE_VALUE
00177 };
00178 EParseState state = PARSE_GLOBAL;
00179 EParseState prev_state = PARSE_GLOBAL;
00180 std::string component_type;
00181 std::string component_name;
00182 std::string variable_name;
00183 std::list<std::string> variable_value;
00184 std::string toplevel_style = "";
00185
00186 while (true)
00187 {
00188 const std::string &token = lexer.peek_next_token();
00189 if (token == "") break;
00190
00191 CL_ComponentType *comp_type = NULL;
00192 switch (state)
00193 {
00194 case PARSE_GLOBAL:
00195 if (token == "style")
00196 {
00197 if (lexer.peek_next_token() != "=")
00198 {
00199 throw CL_Error(lexer.write_error("Missing '=' following global style-declaration"));
00200 }
00201 prev_state = PARSE_GLOBAL;
00202 state = PARSE_VARIABLE_VALUE;
00203 variable_name = token;
00204 }
00205 else if ((comp_type = is_component_type(token)))
00206 {
00207 state = PARSE_COMPONENT_TYPE;
00208 component_type = token;
00209 component_name = "";
00210
00211 CL_ComponentManager_Generic::CL_ComponentInfo info;
00212 info.type = token;
00213 info.component = NULL;
00214 info.component_type = comp_type;
00215 component_stack.push(named_component_t("", info));
00216 }
00217 else
00218 {
00219 throw CL_Error(lexer.write_error("Syntax error"));
00220 }
00221 break;
00222 case PARSE_COMPONENT_TYPE:
00223 if (token == "{")
00224 {
00225 int next_id = component_id_enumerator[token]++;
00226 char buf[20];
00227 sprintf(buf, "%d", next_id);
00228 if (strlen(buf) == 1) component_name = token+"0"+buf;
00229 else component_name = token+buf;
00230 component_stack.top().first = component_name;
00231
00232 state = PARSE_COMPONENT;
00233 }
00234 else
00235 {
00236 component_name = token;
00237 component_stack.top().first = component_name;
00238 state = PARSE_COMPONENT_NAME;
00239 }
00240 break;
00241 case PARSE_COMPONENT_NAME:
00242 if (token != "{")
00243 {
00244 char buf[1000];
00245 sprintf(buf, "Missing '{' following declaration of component '%s'", component_name.c_str());
00246 throw CL_Error(lexer.write_error(buf));
00247 }
00248 state = PARSE_COMPONENT;
00249 break;
00250 case PARSE_COMPONENT:
00251 {
00252 comp_type = is_component_type(token);
00253 if (comp_type != NULL)
00254 {
00255 if (component_stack.empty())
00256 {
00257 throw CL_Error("Internal component manager parser error");
00258 }
00259 if (!component_stack.top().second.component_type->is_container()) throw CL_Error("Tried to add child to non-container component");
00260
00261 CL_ComponentManager_Generic::CL_ComponentInfo info;
00262 info.type = token;
00263 info.component = NULL;
00264 info.component_type = comp_type;
00265
00266 component_stack.push(named_component_t("", info));
00267 component_type = token;
00268 component_name = "";
00269 state = PARSE_COMPONENT_TYPE;
00270 }
00271 else if (token == "}")
00272 {
00273 if (component_stack.empty())
00274 {
00275 throw CL_Error(lexer.write_error("Found '}' outside component"));
00276 }
00277 named_component_t comp = component_stack.top();
00278 component_stack.pop();
00279
00280 std::pair<std::map<std::string, CL_ComponentManager_Generic::CL_ComponentInfo>::iterator, bool> it =
00281 component_map.insert(
00282 std::make_pair(comp.first, comp.second));
00283
00284 if (!it.second)
00285 {
00286 throw CL_Error("All component names must be unique");
00287 }
00288
00289
00290
00291
00292
00293 creation_sort_map.insert(std::make_pair(
00294 component_stack.size(),
00295 &(*it.first).second));
00296
00297 if (!component_stack.empty())
00298 {
00299 named_component_t &parent_comp = component_stack.top();
00300 if (!parent_comp.second.component_type->is_container())
00301 {
00302 throw CL_Error(lexer.write_error("Found component inside other component (must be container)"));
00303 }
00304 else
00305 {
00306 parent_comp.second.children.push_back(&(*it.first).second);
00307 }
00308 }
00309 else
00310 {
00311 state = PARSE_GLOBAL;
00312 }
00313 }
00314 else if (token.length() == 1 && lexer.is_operator(token[0]))
00315 {
00316 throw CL_Error(lexer.write_error("Expected variable-name or component-type"));
00317 }
00318 else
00319 {
00320 prev_state = PARSE_COMPONENT;
00321 state = PARSE_VARIABLE_NAME;
00322 variable_name = token;
00323 variable_value.clear();
00324 }
00325 }
00326 break;
00327 case PARSE_VARIABLE_NAME:
00328 if (token == "=")
00329 {
00330 state = PARSE_VARIABLE_VALUE;
00331 }
00332 else if (token == ";")
00333 {
00334 if (!component_stack.top().second.component_type->has_option(variable_name))
00335 {
00336 char buf[1000];
00337 sprintf(buf, "Failed to add '%s' to component of type '%s'",
00338 variable_name.c_str(),
00339 component_stack.top().second.type.c_str());
00340 throw CL_Error(lexer.write_error(buf));
00341 }
00342 #ifdef BORLAND
00343 component_stack.top().second.options.options.insert(std::make_pair(std::string(variable_name), std::string("")));
00344 #else
00345 component_stack.top().second.options.options.insert(std::make_pair<std::string, std::string>(variable_name, ""));
00346 #endif
00347 variable_name = "";
00348 variable_value.clear();
00349 state = prev_state;
00350 }
00351 else
00352 {
00353 throw CL_Error(lexer.write_error("Expected ';' following variable declaration"));
00354 }
00355 break;
00356 case PARSE_VARIABLE_VALUE:
00357 if (token != ";")
00358 {
00359 variable_value.push_back(token);
00360 }
00361 else
00362 {
00363 if (component_stack.empty())
00364 {
00365 globals.push_back(variable_pair_t(variable_name, evaluate_expression(variable_value)));
00366 }
00367 else if (!component_stack.top().second.component_type->has_option(variable_name))
00368 {
00369 std::string variable_value_str;
00370 int size_list = variable_value.size();
00371 std::list<std::string>::iterator it;
00372 for (it=variable_value.begin();it!=variable_value.end();it++)
00373 {
00374 variable_value_str.append(*it);
00375 size_list--;
00376 if (size_list > 0) variable_value_str.append(1, ' ');
00377 }
00378 char buf[1000];
00379 sprintf(buf, "Failed to add '%s = %s' to component of type '%s'",
00380 variable_name.c_str(),
00381 variable_value_str.c_str(),
00382 component_stack.top().second.type.c_str());
00383 throw CL_Error(lexer.write_error(buf));
00384 }
00385 else
00386 {
00387 component_stack.top().second.options.options.insert(std::make_pair(variable_name, evaluate_expression(variable_value)));
00388 }
00389 variable_name = "";
00390 variable_value.clear();
00391 state = prev_state;
00392 }
00393 break;
00394 }
00395 lexer.pop_to_peek();
00396 }
00397 create_components(creation_sort_map);
00398 }
00399
00400 CL_ComponentType *CL_ComponentManager_Generic::is_component_type(const std::string &token)
00401 {
00402 std::map<std::string, CL_ComponentType *>::iterator it = CL_ComponentManager::component_types.find(token);
00403 if (it == CL_ComponentManager::component_types.end()) return NULL;
00404
00405 return (*it).second;
00406 }
00407
00408 std::string CL_ComponentManager_Generic::concatenate_stringlist(std::list<std::string> &expression)
00409 {
00410 std::string result;
00411 int size_list = expression.size();
00412 std::list<std::string>::iterator it;
00413 for (it=expression.begin();it!=expression.end();it++)
00414 {
00415 result.append(*it);
00416 size_list--;
00417 if (size_list > 0) result.append(1, ' ');
00418 }
00419 return result;
00420 }
00421
00422 std::string CL_ComponentManager_Generic::evaluate_expression(std::list<std::string> &expression)
00423 {
00424 bool is_expression = true;
00425 std::string result;
00426 std::list<std::string>::iterator it = expression.begin();
00427 for (;it!=expression.end();it++)
00428 {
00429 std::string &s = *it;
00430 if (s == "+" || s == "-" || s == "*" || s == "/" || s == "(" || s == ")")
00431 {
00432 continue;
00433 }
00434 const char *str = s.c_str();
00435 for (;*str;str++)
00436 {
00437 if ((*str < '0' || *str > '9') && *str != '.')
00438 {
00439 break;
00440 }
00441 }
00442 if (*str)
00443 {
00444 is_expression = false;
00445 break;
00446 }
00447 }
00448
00449 if (!is_expression)
00450 {
00451 return concatenate_stringlist(expression);
00452 }
00453
00454 std::string test = concatenate_stringlist(expression);
00455
00456
00457
00458
00459
00460
00461
00462 int op = 0;
00463 float result_val = 0.0f;
00464 for (it=expression.begin();it!=expression.end();it++)
00465 {
00466 std::string &s = *it;
00467 if (s == "+") op = 0;
00468 else if (s == "-") op = 1;
00469 else if (s == "*") op = 2;
00470 else if (s == "/") op = 3;
00471 else if (s == "(" || s == ")")
00472 {
00473 continue;
00474 }
00475 else
00476 {
00477 if (op == -1) throw CL_Error("Could not evaluate expression");
00478 float val = atof(s.c_str());
00479 switch (op)
00480 {
00481 case 0:
00482 result_val += val;
00483 break;
00484 case 1:
00485 result_val -= val;
00486 break;
00487 case 2:
00488 result_val *= val;
00489 break;
00490 case 3:
00491 result_val /= val;
00492 break;
00493 default:
00494 result_val = val;
00495 break;
00496 }
00497 op = -1;
00498 }
00499 }
00500
00501 int rval = int(result_val+0.5);
00502 return CL_String(rval);
00503 }