1 //====-- UserSettingsController.cpp ------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include <string.h> 11 #include <algorithm> 12 13 #include "lldb/Core/UserSettingsController.h" 14 #include "lldb/Core/Error.h" 15 #include "lldb/Core/RegularExpression.h" 16 #include "lldb/Core/Stream.h" 17 #include "lldb/Core/StreamString.h" 18 #include "lldb/Interpreter/CommandInterpreter.h" 19 20 using namespace lldb; 21 using namespace lldb_private; 22 23 static void 24 DumpSettingEntry (CommandInterpreter &interpreter, 25 Stream &result_stream, 26 const uint32_t max_len, 27 const SettingEntry &entry) 28 { 29 StreamString description; 30 31 if (entry.description) 32 description.Printf ("%s", entry.description); 33 34 if (entry.default_value && entry.default_value[0]) 35 description.Printf (" (default: %s)", entry.default_value); 36 37 interpreter.OutputFormattedHelpText (result_stream, 38 entry.var_name, 39 "--", 40 description.GetData(), 41 max_len); 42 43 if (entry.enum_values && entry.enum_values[0].string_value) 44 { 45 interpreter.OutputFormattedHelpText (result_stream, 46 "", 47 " ", 48 "Enumeration values:", 49 max_len); 50 for (uint32_t enum_idx=0; entry.enum_values[enum_idx].string_value != NULL; ++enum_idx) 51 { 52 description.Clear(); 53 if (entry.enum_values[enum_idx].usage) 54 description.Printf ("%s = %s", 55 entry.enum_values[enum_idx].string_value, 56 entry.enum_values[enum_idx].usage); 57 else 58 description.Printf ("%s", entry.enum_values[enum_idx].string_value); 59 interpreter.OutputFormattedHelpText (result_stream, 60 "", 61 " ", 62 description.GetData(), 63 max_len); 64 } 65 } 66 } 67 68 UserSettingsController::UserSettingsController (const char *level_name, 69 const UserSettingsControllerSP &parent) : 70 m_default_settings (), 71 m_settings (), 72 m_children (), 73 m_pending_settings (), 74 m_live_settings (), 75 m_children_mutex (Mutex::eMutexTypeNormal), 76 m_pending_settings_mutex (Mutex::eMutexTypeRecursive), 77 m_live_settings_mutex (Mutex::eMutexTypeRecursive) 78 { 79 m_settings.parent = parent; 80 m_settings.level_name.SetCString (level_name); 81 } 82 83 UserSettingsController::~UserSettingsController () 84 { 85 m_live_settings.clear(); 86 } 87 88 bool 89 UserSettingsController::SetGlobalVariable 90 ( 91 const ConstString &var_name, 92 const char *index_value, 93 const char *value, 94 const SettingEntry &entry, 95 const VarSetOperationType op, 96 Error &err 97 ) 98 { 99 err.SetErrorString ("UserSettingsController has no global settings"); 100 return false; 101 } 102 103 bool 104 UserSettingsController::GetGlobalVariable 105 ( 106 const ConstString &var_name, 107 StringList &value, 108 Error &err 109 ) 110 { 111 return false; 112 } 113 114 bool 115 UserSettingsController::InitializeSettingsController (UserSettingsControllerSP &controller_sp, 116 SettingEntry *global_settings, 117 SettingEntry *instance_settings) 118 { 119 const UserSettingsControllerSP &parent = controller_sp->GetParent (); 120 if (parent) 121 parent->RegisterChild (controller_sp); 122 123 controller_sp->CreateSettingsVector (global_settings, true); 124 controller_sp->CreateSettingsVector (instance_settings, false); 125 126 controller_sp->InitializeGlobalVariables (); 127 controller_sp->CreateDefaultInstanceSettings (); 128 129 return true; 130 } 131 132 void 133 UserSettingsController::FinalizeSettingsController (UserSettingsControllerSP &controller_sp) 134 { 135 const UserSettingsControllerSP &parent = controller_sp->GetParent (); 136 if (parent) 137 parent->RemoveChild (controller_sp); 138 } 139 140 void 141 UserSettingsController::InitializeGlobalVariables () 142 { 143 int num_entries; 144 const char *prefix = GetLevelName().AsCString(); 145 146 num_entries = m_settings.global_settings.size(); 147 for (int i = 0; i < num_entries; ++i) 148 { 149 const SettingEntry &entry = m_settings.global_settings[i]; 150 if (entry.default_value != NULL) 151 { 152 StreamString full_name; 153 if (prefix[0] != '\0') 154 full_name.Printf ("%s.%s", prefix, entry.var_name); 155 else 156 full_name.Printf ("%s", entry.var_name); 157 SetVariable (full_name.GetData(), entry.default_value, eVarSetOperationAssign, false, ""); 158 } 159 } 160 } 161 162 const UserSettingsControllerSP & 163 UserSettingsController::GetParent () 164 { 165 return m_settings.parent; 166 } 167 168 void 169 UserSettingsController::RegisterChild (const UserSettingsControllerSP &child) 170 { 171 Mutex::Locker locker (m_children_mutex); 172 173 // Verify child is not already in m_children. 174 size_t num_children = m_children.size(); 175 bool found = false; 176 for (size_t i = 0; i < num_children; ++i) 177 { 178 if (m_children[i].get() == child.get()) 179 found = true; 180 } 181 182 // Add child to m_children. 183 if (! found) 184 m_children.push_back (child); 185 } 186 187 const ConstString & 188 UserSettingsController::GetLevelName () 189 { 190 return m_settings.level_name; 191 } 192 193 size_t 194 UserSettingsController::GetNumChildren () 195 { 196 return m_children.size(); 197 } 198 199 const UserSettingsControllerSP 200 UserSettingsController::GetChildAtIndex (size_t index) 201 { 202 if (index < m_children.size()) 203 return m_children[index]; 204 205 UserSettingsControllerSP dummy_value; 206 207 return dummy_value; 208 } 209 210 const SettingEntry * 211 UserSettingsController::GetGlobalEntry (const ConstString &var_name) 212 { 213 214 for (int i = 0; i < m_settings.global_settings.size(); ++i) 215 { 216 const SettingEntry &entry = m_settings.global_settings[i]; 217 ConstString entry_name (entry.var_name); 218 if (entry_name == var_name) 219 return &entry; 220 } 221 222 return NULL; 223 } 224 225 const SettingEntry * 226 UserSettingsController::GetInstanceEntry (const ConstString &const_var_name) 227 { 228 229 for (int i = 0; i < m_settings.instance_settings.size(); ++i) 230 { 231 SettingEntry &entry = m_settings.instance_settings[i]; 232 ConstString entry_name (entry.var_name); 233 if (entry_name == const_var_name) 234 return &entry; 235 } 236 237 return NULL; 238 } 239 240 void 241 UserSettingsController::BuildParentPrefix (std::string &parent_prefix) 242 { 243 UserSettingsControllerSP parent = GetParent(); 244 if (parent.get() != NULL) 245 { 246 parent->BuildParentPrefix (parent_prefix); 247 if (parent_prefix.length() > 0) 248 parent_prefix.append ("."); 249 } 250 parent_prefix.append (GetLevelName().AsCString()); 251 } 252 253 void 254 UserSettingsController::RemoveChild (const UserSettingsControllerSP &child) 255 { 256 Mutex::Locker locker (m_children_mutex); 257 std::vector<UserSettingsControllerSP>::iterator pos, end = m_children.end(); 258 259 for (pos = m_children.begin(); pos != end; ++pos) 260 { 261 UserSettingsControllerSP entry = *pos; 262 if (entry == child) 263 { 264 m_children.erase (pos); 265 break; 266 } 267 } 268 } 269 270 Error 271 UserSettingsController::SetVariable (const char *full_dot_name, 272 const char *value, 273 const VarSetOperationType op, 274 const bool override, 275 const char *debugger_instance_name, 276 const char *index_value) 277 { 278 Error err; 279 ConstString const_var_name; 280 const ConstString &default_name = InstanceSettings::GetDefaultName(); 281 282 Args names = UserSettingsController::BreakNameIntoPieces (full_dot_name); 283 int num_pieces = names.GetArgumentCount(); 284 285 if (num_pieces < 1) 286 { 287 err.SetErrorStringWithFormat ("'%s' is not a valid variable name; cannot assign value.\n", full_dot_name); 288 return err; 289 } 290 291 ConstString prefix (names.GetArgumentAtIndex (0)); 292 293 if ((prefix == m_settings.level_name) 294 || (m_settings.level_name.GetLength() == 0)) 295 { 296 297 if (prefix == m_settings.level_name) 298 { 299 names.Shift (); 300 num_pieces = names.GetArgumentCount(); 301 } 302 303 if (num_pieces == 0) 304 { 305 err.SetErrorString ("No variable name specified; cannot assign value.\n"); 306 return err; 307 } 308 else if (num_pieces == 1) 309 { 310 311 // Must be one of the class-wide settings. 312 313 const_var_name.SetCString (names.GetArgumentAtIndex (0)); 314 const SettingEntry *entry = GetGlobalEntry (const_var_name); 315 if (entry) 316 { 317 UserSettingsController::VerifyOperationForType (entry->var_type, op, const_var_name, err); 318 319 if (err.Fail()) 320 return err; 321 322 if ((value == NULL || value[0] == '\0') 323 && (op == eVarSetOperationAssign)) 324 { 325 if (entry->var_type != eSetVarTypeEnum) 326 value = entry->default_value; 327 else 328 value = entry->enum_values[0].string_value; 329 } 330 SetGlobalVariable (const_var_name, index_value, value, *entry, op, err); 331 } 332 else 333 { 334 // MIGHT be instance variable, to be for ALL instances. 335 336 entry = GetInstanceEntry (const_var_name); 337 if (entry == NULL) 338 { 339 err.SetErrorStringWithFormat ("Unable to find variable '%s.%s'; cannot assign value.\n", 340 prefix.AsCString(), const_var_name.AsCString()); 341 return err; 342 } 343 else 344 { 345 UserSettingsController::VerifyOperationForType (entry->var_type, op, const_var_name, err); 346 347 if (err.Fail()) 348 return err; 349 350 if ((value == NULL || value[0] == '\0') 351 && (op == eVarSetOperationAssign)) 352 { 353 if (entry->var_type != eSetVarTypeEnum) 354 value = entry->default_value; 355 else 356 value = entry->enum_values[0].string_value; 357 } 358 359 if ((m_settings.level_name.GetLength() > 0) 360 || strlen (debugger_instance_name) == 0) 361 { 362 // Set the default settings 363 m_default_settings->UpdateInstanceSettingsVariable (const_var_name, index_value, value, 364 default_name, *entry, op, err, true); 365 } 366 else 367 { 368 // We're at the Debugger level; find the correct debugger instance and set those settings 369 StreamString tmp_name; 370 if (debugger_instance_name[0] != '[') 371 tmp_name.Printf ("[%s]", debugger_instance_name); 372 else 373 tmp_name.Printf ("%s", debugger_instance_name); 374 ConstString dbg_name (tmp_name.GetData()); 375 InstanceSettings *dbg_settings = FindSettingsForInstance (dbg_name); 376 if (dbg_settings) 377 dbg_settings->UpdateInstanceSettingsVariable (const_var_name, index_value, value, dbg_name, 378 *entry, op, err, false); 379 } 380 381 if (override) 382 { 383 OverrideAllInstances (const_var_name, value, op, index_value, err); 384 385 // Update all pending records as well. 386 // std::map<std::string, InstanceSettingsSP>::iterator pos, end = m_pending_settings.end(); 387 // for (pos = m_pending_settings.begin(); pos != end; end++) 388 // { 389 // const ConstString instance_name (pos->first.c_str()); 390 // InstanceSettingsSP setting_sp = pos->second; 391 // setting_sp->UpdateInstanceSettingsVariable (const_var_name, index_value, value, 392 // instance_name, *entry, op, err, true); 393 // } 394 } 395 } 396 } 397 } 398 else 399 { 400 // Either a child's setting or an instance setting. 401 402 if (names.GetArgumentAtIndex(0)[0] == '[') 403 { 404 // An instance setting. Supposedly. 405 406 ConstString instance_name (names.GetArgumentAtIndex (0)); 407 408 // First verify that there is only one more name. 409 410 names.Shift(); 411 412 if (names.GetArgumentCount() != 1) 413 { 414 err.SetErrorStringWithFormat ("Invalid variable name format '%s'; cannot assign value.\n", 415 full_dot_name); 416 return err; 417 } 418 419 // Next verify that it is a valid instance setting name. 420 421 const_var_name.SetCString (names.GetArgumentAtIndex (0)); 422 const SettingEntry *entry = GetInstanceEntry (const_var_name); 423 424 if (entry == NULL) 425 { 426 err.SetErrorStringWithFormat ("Unknown instance variable '%s'; cannot assign value.\n", 427 const_var_name.AsCString()); 428 return err; 429 } 430 431 UserSettingsController::VerifyOperationForType (entry->var_type, op, const_var_name, err); 432 433 if (err.Fail()) 434 return err; 435 436 if ((value == NULL || value[0] == '\0') 437 && (op == eVarSetOperationAssign)) 438 { 439 if (entry->var_type != eSetVarTypeEnum) 440 value = entry->default_value; 441 else 442 value = entry->enum_values[0].string_value; 443 } 444 445 // Now look for existing instance with given instance name; if not found, find or create pending 446 // setting for instance with given name. 447 448 InstanceSettings *current_settings = FindSettingsForInstance (instance_name); 449 450 if (current_settings != NULL) 451 { 452 current_settings->UpdateInstanceSettingsVariable (const_var_name, index_value, value, 453 instance_name, *entry, op, err, false); 454 455 } 456 else 457 { 458 // Instance does not currently exist; make or update a pending setting for it. 459 InstanceSettingsSP current_settings_sp = PendingSettingsForInstance (instance_name); 460 461 // Now we have a settings record, update it appropriately. 462 463 current_settings_sp->UpdateInstanceSettingsVariable (const_var_name, index_value, value, 464 instance_name, *entry, op, err, true); 465 466 { // Scope for mutex. 467 Mutex::Locker locker (m_pending_settings_mutex); 468 m_pending_settings[instance_name.AsCString()] = current_settings_sp; 469 } 470 471 if (override) 472 { 473 OverrideAllInstances (const_var_name, value, op, index_value, err); 474 475 // Update all pending records as well. 476 std::map<std::string, InstanceSettingsSP>::iterator pos; 477 std::map<std::string, InstanceSettingsSP>::iterator end = m_pending_settings.end(); 478 for (pos = m_pending_settings.begin(); pos != end; end++) 479 { 480 const ConstString tmp_inst_name (pos->first.c_str()); 481 InstanceSettingsSP setting_sp = pos->second; 482 setting_sp->UpdateInstanceSettingsVariable (const_var_name, index_value, value, 483 tmp_inst_name, *entry, op, err, true); 484 } 485 } 486 } 487 } 488 else 489 { 490 // A child setting. 491 UserSettingsControllerSP child; 492 ConstString child_prefix (names.GetArgumentAtIndex (0)); 493 int num_children = GetNumChildren(); 494 bool found = false; 495 for (int i = 0; i < num_children && !found; ++i) 496 { 497 child = GetChildAtIndex (i); 498 ConstString current_prefix = child->GetLevelName(); 499 if (current_prefix == child_prefix) 500 { 501 found = true; 502 std::string new_name; 503 for (int j = 0; j < names.GetArgumentCount(); ++j) 504 { 505 if (j > 0) 506 new_name += '.'; 507 new_name += names.GetArgumentAtIndex (j); 508 } 509 return child->SetVariable (new_name.c_str(), value, op, override, debugger_instance_name, 510 index_value); 511 } 512 } 513 if (!found) 514 { 515 err.SetErrorStringWithFormat ("Unable to find variable '%s'; cannot assign value.\n", 516 full_dot_name); 517 return err; 518 } 519 } 520 } 521 } 522 else 523 { 524 err.SetErrorStringWithFormat ("'%s' is not a valid level name; was expecting '%s'. Cannot assign value.\n", 525 prefix.AsCString(), m_settings.level_name.AsCString()); 526 } 527 528 return err; 529 } 530 531 StringList 532 UserSettingsController::GetVariable 533 ( 534 const char *full_dot_name, 535 SettableVariableType &var_type, 536 const char *debugger_instance_name, 537 Error &err 538 ) 539 { 540 Args names = UserSettingsController::BreakNameIntoPieces (full_dot_name); 541 ConstString const_var_name; 542 StringList value; 543 544 int num_pieces = names.GetArgumentCount(); 545 546 ConstString prefix (names.GetArgumentAtIndex (0)); 547 const_var_name.SetCString (names.GetArgumentAtIndex (num_pieces - 1)); 548 549 const SettingEntry *global_entry = GetGlobalEntry (const_var_name); 550 const SettingEntry *instance_entry = GetInstanceEntry (const_var_name); 551 552 if ((prefix != m_settings.level_name) 553 && (m_settings.level_name.GetLength () > 0)) 554 { 555 err.SetErrorString ("Invalid variable name"); 556 return value; 557 } 558 559 // prefix name matched; remove it from names. 560 if (m_settings.level_name.GetLength() > 0) 561 names.Shift(); 562 563 // Should we pass this off to a child? If there is more than one name piece left, and the next name piece 564 // matches a child prefix, then yes. 565 566 UserSettingsControllerSP child; 567 if (names.GetArgumentCount() > 1) 568 { 569 ConstString child_prefix (names.GetArgumentAtIndex (0)); 570 bool found = false; 571 for (int i = 0; i < m_children.size() && !found; ++i) 572 { 573 if (child_prefix == m_children[i]->GetLevelName()) 574 { 575 found = true; 576 child = m_children[i]; 577 std::string new_name; 578 for (int j = 0; j < names.GetArgumentCount(); ++j) 579 { 580 if (j > 0) 581 new_name += '.'; 582 new_name += names.GetArgumentAtIndex (j); 583 } 584 return child->GetVariable (new_name.c_str(), var_type, debugger_instance_name, err); 585 } 586 } 587 588 if (!found) 589 { 590 // Cannot be handled by a child, because name did not match any child prefixes. 591 // Cannot be a class-wide variable because there are too many name pieces. 592 593 if (instance_entry != NULL) 594 { 595 var_type = instance_entry->var_type; 596 ConstString instance_name (names.GetArgumentAtIndex (0)); 597 InstanceSettings *current_settings = FindSettingsForInstance (instance_name); 598 599 if (current_settings != NULL) 600 { 601 current_settings->GetInstanceSettingsValue (*instance_entry, const_var_name, value, &err); 602 } 603 else 604 { 605 // Look for instance name setting in pending settings. 606 607 std::string inst_name_str = instance_name.AsCString(); 608 std::map<std::string, InstanceSettingsSP>::iterator pos; 609 610 pos = m_pending_settings.find (inst_name_str); 611 if (pos != m_pending_settings.end()) 612 { 613 InstanceSettingsSP settings_sp = pos->second; 614 settings_sp->GetInstanceSettingsValue (*instance_entry, const_var_name, value, &err); 615 } 616 else 617 { 618 if (m_settings.level_name.GetLength() > 0) 619 { 620 // No valid instance name; assume they want the default settings. 621 m_default_settings->GetInstanceSettingsValue (*instance_entry, const_var_name, value, &err); 622 } 623 else 624 { 625 // We're at the Debugger level; use the debugger's instance settings. 626 StreamString tmp_name; 627 if (debugger_instance_name[0] != '[') 628 tmp_name.Printf ("[%s]", debugger_instance_name); 629 else 630 tmp_name.Printf ("%s", debugger_instance_name); 631 ConstString dbg_name (debugger_instance_name); 632 InstanceSettings *dbg_settings = FindSettingsForInstance (dbg_name); 633 if (dbg_settings) 634 dbg_settings->GetInstanceSettingsValue (*instance_entry, const_var_name, value, &err); 635 } 636 } 637 } 638 } 639 else 640 err.SetErrorString ("Invalid variable name"); 641 } 642 } 643 else 644 { 645 // Only one name left. It must belong to the current level, or be an error. 646 if ((global_entry == NULL) 647 && (instance_entry == NULL)) 648 { 649 err.SetErrorString ("Invalid variable name"); 650 } 651 else if (global_entry) 652 { 653 var_type = global_entry->var_type; 654 GetGlobalVariable (const_var_name, value, err); 655 } 656 else if (instance_entry) 657 { 658 var_type = instance_entry->var_type; 659 if (m_settings.level_name.GetLength() > 0) 660 m_default_settings->GetInstanceSettingsValue (*instance_entry, const_var_name, value, &err); 661 else 662 { 663 // We're at the Debugger level; use the debugger's instance settings. 664 StreamString tmp_name; 665 if (debugger_instance_name[0] != '[') 666 tmp_name.Printf ("[%s]", debugger_instance_name); 667 else 668 tmp_name.Printf ("%s", debugger_instance_name); 669 ConstString dbg_name (tmp_name.GetData()); 670 InstanceSettings *dbg_settings = FindSettingsForInstance (dbg_name); 671 if (dbg_settings) 672 dbg_settings->GetInstanceSettingsValue (*instance_entry, const_var_name, value, &err); 673 } 674 } 675 } 676 677 return value; 678 } 679 680 void 681 UserSettingsController::RemovePendingSettings (const ConstString &instance_name) 682 { 683 StreamString tmp_name; 684 685 // Add surrounding brackets to instance name if not already present. 686 687 if (instance_name.AsCString()[0] != '[') 688 tmp_name.Printf ("[%s]", instance_name.AsCString()); 689 else 690 tmp_name.Printf ("%s", instance_name.AsCString()); 691 692 std::string instance_name_str (tmp_name.GetData()); 693 std::map<std::string, InstanceSettingsSP>::iterator pos; 694 Mutex::Locker locker (m_pending_settings_mutex); 695 696 m_pending_settings.erase (instance_name_str); 697 } 698 699 const InstanceSettingsSP & 700 UserSettingsController::FindPendingSettings (const ConstString &instance_name) 701 { 702 std::map<std::string, InstanceSettingsSP>::iterator pos; 703 StreamString tmp_name; 704 705 // Add surrounding brackets to instance name if not already present. 706 707 if (instance_name.AsCString()[0] != '[') 708 tmp_name.Printf ("[%s]", instance_name.AsCString()); 709 else 710 tmp_name.Printf ("%s", instance_name.AsCString()); 711 712 std::string instance_name_str (tmp_name.GetData()); // Need std::string for std::map look-up 713 714 { // Scope for mutex. 715 Mutex::Locker locker (m_pending_settings_mutex); 716 717 pos = m_pending_settings.find (instance_name_str); 718 if (pos != m_pending_settings.end()) 719 return pos->second; 720 } 721 722 return m_default_settings; 723 } 724 725 void 726 UserSettingsController::CreateDefaultInstanceSettings () 727 { 728 Error err; 729 const ConstString &default_name = InstanceSettings::GetDefaultName(); 730 for (int i = 0; i < m_settings.instance_settings.size(); ++i) 731 { 732 SettingEntry &entry = m_settings.instance_settings[i]; 733 ConstString var_name (entry.var_name); 734 const char *value = entry.default_value; 735 736 if (entry.var_type == eSetVarTypeEnum) 737 value = entry.enum_values[0].string_value; 738 739 m_default_settings->UpdateInstanceSettingsVariable (var_name, NULL, value, default_name, entry, 740 eVarSetOperationAssign, err, true); 741 } 742 } 743 744 void 745 UserSettingsController::CopyDefaultSettings (const InstanceSettingsSP &actual_settings, 746 const ConstString &instance_name, 747 bool pending) 748 { 749 Error err; 750 for (int i = 0; i < m_settings.instance_settings.size(); ++i) 751 { 752 SettingEntry &entry = m_settings.instance_settings[i]; 753 ConstString var_name (entry.var_name); 754 StringList value; 755 m_default_settings->GetInstanceSettingsValue (entry, var_name, value, NULL); 756 757 std::string value_str; 758 if (value.GetSize() == 1) 759 value_str.append (value.GetStringAtIndex (0)); 760 else if (value.GetSize() > 1) 761 { 762 for (int j = 0; j < value.GetSize(); ++j) 763 { 764 if (j > 0) 765 value_str.append (" "); 766 value_str.append (value.GetStringAtIndex (j)); 767 } 768 } 769 770 actual_settings->UpdateInstanceSettingsVariable (var_name, NULL, value_str.c_str(), instance_name, entry, 771 eVarSetOperationAssign, err, pending); 772 773 } 774 } 775 776 InstanceSettingsSP 777 UserSettingsController::PendingSettingsForInstance (const ConstString &instance_name) 778 { 779 std::string name_str (instance_name.AsCString()); 780 std::map<std::string, InstanceSettingsSP>::iterator pos; 781 Mutex::Locker locker (m_pending_settings_mutex); 782 783 pos = m_pending_settings.find (name_str); 784 if (pos != m_pending_settings.end()) 785 { 786 InstanceSettingsSP settings_sp = pos->second; 787 return settings_sp; 788 } 789 else 790 { 791 InstanceSettingsSP new_settings_sp = CreateInstanceSettings (instance_name.AsCString()); 792 CopyDefaultSettings (new_settings_sp, instance_name, true); 793 m_pending_settings[name_str] = new_settings_sp; 794 return new_settings_sp; 795 } 796 797 // Should never reach this line. 798 799 InstanceSettingsSP dummy; 800 801 return dummy; 802 } 803 804 void 805 UserSettingsController::GetAllDefaultSettingValues (Stream &result_stream) 806 { 807 std::string parent_prefix; 808 BuildParentPrefix (parent_prefix); 809 const char *prefix = parent_prefix.c_str(); 810 811 for (int i = 0; i < m_settings.instance_settings.size(); ++i) 812 { 813 SettingEntry &entry = m_settings.instance_settings[i]; 814 ConstString var_name (entry.var_name); 815 StringList tmp_value; 816 m_default_settings->GetInstanceSettingsValue (entry, var_name, tmp_value, NULL); 817 818 StreamString value_string; 819 bool multi_value = false; 820 821 if (tmp_value.GetSize() == 1) 822 value_string.Printf ("%s", tmp_value.GetStringAtIndex (0)); 823 else 824 { 825 for (int j = 0; j < tmp_value.GetSize(); ++j) 826 { 827 if (entry.var_type == eSetVarTypeArray) 828 value_string.Printf ("\n [%d]: '%s'", j, tmp_value.GetStringAtIndex (j)); 829 else if (entry.var_type == eSetVarTypeDictionary) 830 value_string.Printf ("\n '%s'", tmp_value.GetStringAtIndex (j)); 831 } 832 multi_value = true; 833 } 834 835 if (! parent_prefix.empty()) 836 { 837 if (multi_value) 838 result_stream.Printf ("%s.%s (%s):%s\n", prefix, var_name.AsCString(), 839 UserSettingsController::GetTypeString (entry.var_type), value_string.GetData()); 840 else 841 result_stream.Printf ("%s.%s (%s) = '%s'\n", prefix, var_name.AsCString(), 842 UserSettingsController::GetTypeString (entry.var_type), value_string.GetData()); 843 } 844 } 845 } 846 847 void 848 UserSettingsController::GetAllPendingSettingValues (Stream &result_stream) 849 { 850 std::map<std::string, InstanceSettingsSP>::iterator pos; 851 852 std::string parent_prefix; 853 BuildParentPrefix (parent_prefix); 854 const char *prefix = parent_prefix.c_str(); 855 856 for (pos = m_pending_settings.begin(); pos != m_pending_settings.end(); ++pos) 857 { 858 std::string tmp_name = pos->first; 859 InstanceSettingsSP settings_sp = pos->second; 860 861 const ConstString instance_name (tmp_name.c_str()); 862 863 for (int i = 0; i < m_settings.instance_settings.size(); ++i) 864 { 865 SettingEntry &entry = m_settings.instance_settings[i]; 866 ConstString var_name (entry.var_name); 867 StringList tmp_value; 868 settings_sp->GetInstanceSettingsValue (entry, var_name, tmp_value, NULL); 869 870 StreamString value_str; 871 872 if (tmp_value.GetSize() == 0) 873 value_str.Printf (""); 874 else if (tmp_value.GetSize() == 1) 875 value_str.Printf ("%s", tmp_value.GetStringAtIndex (0)); 876 else 877 { 878 for (int j = 0; j < tmp_value.GetSize(); ++j) 879 value_str.Printf ("%s ", tmp_value.GetStringAtIndex (j)); 880 } 881 882 if (parent_prefix.length() > 0) 883 { 884 result_stream.Printf ("%s.%s.%s (%s) = '%s' [pending]\n", prefix, instance_name.AsCString(), 885 var_name.AsCString(), UserSettingsController::GetTypeString (entry.var_type), 886 value_str.GetData()); 887 } 888 else 889 { 890 result_stream.Printf ("%s (%s) = '%s' [pending]\n", var_name.AsCString(), 891 UserSettingsController::GetTypeString (entry.var_type), 892 value_str.GetData()); 893 } 894 } 895 } 896 } 897 898 InstanceSettings * 899 UserSettingsController::FindSettingsForInstance (const ConstString &instance_name) 900 { 901 std::string instance_name_str (instance_name.AsCString()); 902 std::map<std::string, InstanceSettings *>::iterator pos; 903 904 pos = m_live_settings.find (instance_name_str); 905 if (pos != m_live_settings.end ()) 906 { 907 InstanceSettings *settings = pos->second; 908 return settings; 909 } 910 911 return NULL; 912 } 913 914 void 915 UserSettingsController::GetAllInstanceVariableValues (CommandInterpreter &interpreter, 916 Stream &result_stream) 917 { 918 std::map<std::string, InstanceSettings *>::iterator pos; 919 std::string parent_prefix; 920 BuildParentPrefix (parent_prefix); 921 const char *prefix = parent_prefix.c_str(); 922 StreamString description; 923 924 for (pos = m_live_settings.begin(); pos != m_live_settings.end(); ++pos) 925 { 926 std::string instance_name = pos->first; 927 InstanceSettings *settings = pos->second; 928 929 for (int i = 0; i < m_settings.instance_settings.size(); ++i) 930 { 931 SettingEntry &entry = m_settings.instance_settings[i]; 932 const ConstString var_name (entry.var_name); 933 StringList tmp_value; 934 settings->GetInstanceSettingsValue (entry, var_name, tmp_value, NULL); 935 StreamString tmp_value_str; 936 937 if (tmp_value.GetSize() == 0) 938 tmp_value_str.Printf (""); 939 else if (tmp_value.GetSize() == 1) 940 tmp_value_str.Printf ("%s", tmp_value.GetStringAtIndex (0)); 941 else 942 { 943 for (int j = 0; j < tmp_value.GetSize(); ++j) 944 tmp_value_str.Printf ("%s ",tmp_value.GetStringAtIndex (j)); 945 } 946 947 description.Clear(); 948 if (parent_prefix.length() > 0) 949 { 950 description.Printf ("%s.%s.%s (%s) = '%s'", prefix, instance_name.c_str(), var_name.AsCString(), 951 UserSettingsController::GetTypeString (entry.var_type), 952 tmp_value_str.GetData()); 953 } 954 else 955 { 956 description.Printf ("%s (%s) = '%s'", var_name.AsCString(), 957 UserSettingsController::GetTypeString (entry.var_type), tmp_value_str.GetData()); 958 } 959 result_stream.Printf ("%s\n", description.GetData()); 960 } 961 } 962 } 963 964 void 965 UserSettingsController::OverrideAllInstances (const ConstString &var_name, 966 const char *value, 967 VarSetOperationType op, 968 const char *index_value, 969 Error &err) 970 { 971 std::map<std::string, InstanceSettings *>::iterator pos; 972 StreamString description; 973 974 for (pos = m_live_settings.begin(); pos != m_live_settings.end(); ++pos) 975 { 976 InstanceSettings *settings = pos->second; 977 StreamString tmp_name; 978 tmp_name.Printf ("[%s]", settings->GetInstanceName().AsCString()); 979 const ConstString instance_name (tmp_name.GetData()); 980 const SettingEntry *entry = GetInstanceEntry (var_name); 981 settings->UpdateInstanceSettingsVariable (var_name, index_value, value, instance_name, *entry, op, err, false); 982 983 } 984 } 985 986 void 987 UserSettingsController::RegisterInstanceSettings (InstanceSettings *instance_settings) 988 { 989 Mutex::Locker locker (m_live_settings_mutex); 990 StreamString tmp_name; 991 tmp_name.Printf ("[%s]", instance_settings->GetInstanceName().AsCString()); 992 const ConstString instance_name (tmp_name.GetData()); 993 std::string instance_name_str (instance_name.AsCString()); 994 if (instance_name_str.compare (InstanceSettings::GetDefaultName().AsCString()) != 0) 995 m_live_settings[instance_name_str] = instance_settings; 996 } 997 998 void 999 UserSettingsController::UnregisterInstanceSettings (InstanceSettings *instance) 1000 { 1001 Mutex::Locker locker (m_live_settings_mutex); 1002 StreamString tmp_name; 1003 tmp_name.Printf ("[%s]", instance->GetInstanceName().AsCString()); 1004 std::string instance_name (tmp_name.GetData()); 1005 1006 std::map <std::string, InstanceSettings *>::iterator pos; 1007 1008 pos = m_live_settings.find (instance_name); 1009 if (pos != m_live_settings.end()) 1010 m_live_settings.erase (pos); 1011 } 1012 1013 void 1014 UserSettingsController::CreateSettingsVector (const SettingEntry *table, 1015 bool global) 1016 { 1017 int i = 0; 1018 while (table[i].var_name != NULL) 1019 { 1020 const SettingEntry &table_entry = table[i]; 1021 ConstString const_var_name (table_entry.var_name); 1022 SettingEntry new_entry; 1023 1024 new_entry = table_entry; 1025 new_entry.var_name = const_var_name.AsCString(); 1026 1027 if (global) 1028 m_settings.global_settings.push_back (new_entry); 1029 else 1030 m_settings.instance_settings.push_back (new_entry); 1031 1032 ++i; 1033 } 1034 } 1035 1036 //---------------------------------------------------------------------- 1037 // UserSettingsController static methods 1038 //---------------------------------------------------------------------- 1039 1040 int 1041 FindMaxNameLength (std::vector<SettingEntry> table) 1042 { 1043 int max_length = 1; 1044 1045 for (int i = 0; i < table.size(); ++i) 1046 { 1047 int len = strlen (table[i].var_name); 1048 if (len > max_length) 1049 max_length = len; 1050 } 1051 1052 return max_length; 1053 } 1054 1055 const char * 1056 UserSettingsController::GetTypeString (SettableVariableType var_type) 1057 { 1058 switch (var_type) 1059 { 1060 case eSetVarTypeInt: 1061 return "int"; 1062 case eSetVarTypeBoolean: 1063 return "boolean"; 1064 case eSetVarTypeString: 1065 return "string"; 1066 case eSetVarTypeArray: 1067 return "array"; 1068 case eSetVarTypeDictionary: 1069 return "dictionary"; 1070 case eSetVarTypeEnum: 1071 return "enum"; 1072 case eSetVarTypeNone: 1073 return "no type"; 1074 } 1075 1076 return ""; 1077 } 1078 1079 void 1080 UserSettingsController::PrintEnumValues (const OptionEnumValueElement *enum_values, Stream &str) 1081 { 1082 int i = 0; 1083 while (enum_values[i].string_value != NULL) 1084 { 1085 str.Printf ("%s ", enum_values[i].string_value); 1086 ++i; 1087 } 1088 1089 } 1090 1091 void 1092 UserSettingsController::FindAllSettingsDescriptions (CommandInterpreter &interpreter, 1093 UserSettingsControllerSP root, 1094 std::string ¤t_prefix, 1095 Stream &result_stream, 1096 Error &err) 1097 { 1098 // Write out current prefix line. 1099 StreamString prefix_line; 1100 StreamString description; 1101 uint32_t max_len = FindMaxNameLength (root->m_settings.global_settings); 1102 int num_entries = root->m_settings.global_settings.size(); 1103 1104 if (! current_prefix.empty()) 1105 result_stream.Printf ("\n'%s' variables:\n\n", current_prefix.c_str()); 1106 else 1107 result_stream.Printf ("\nTop level variables:\n\n"); 1108 1109 if (num_entries > 0) 1110 { 1111 // Write out all "global" variables. 1112 for (int i = 0; i < num_entries; ++i) 1113 { 1114 DumpSettingEntry (interpreter, result_stream, max_len, root->m_settings.global_settings[i]); 1115 } 1116 } 1117 1118 num_entries = root->m_settings.instance_settings.size(); 1119 max_len = FindMaxNameLength (root->m_settings.instance_settings); 1120 1121 if (num_entries > 0) 1122 { 1123 // Write out all instance variables. 1124 for (int i = 0; i < num_entries; ++i) 1125 { 1126 DumpSettingEntry (interpreter, result_stream, max_len, root->m_settings.instance_settings[i]); 1127 } 1128 } 1129 1130 // Now, recurse across all children. 1131 int num_children = root->GetNumChildren(); 1132 for (int i = 0; i < num_children; ++i) 1133 { 1134 UserSettingsControllerSP child = root->GetChildAtIndex (i); 1135 1136 if (child) 1137 { 1138 ConstString child_prefix = child->GetLevelName(); 1139 StreamString new_prefix; 1140 if (! current_prefix.empty()) 1141 new_prefix.Printf ("%s.%s", current_prefix.c_str(), child_prefix.AsCString()); 1142 else 1143 new_prefix.Printf ("%s", child_prefix.AsCString()); 1144 std::string new_prefix_str = new_prefix.GetData(); 1145 UserSettingsController::FindAllSettingsDescriptions (interpreter, 1146 child, 1147 new_prefix_str, 1148 result_stream, 1149 err); 1150 } 1151 } 1152 } 1153 1154 void 1155 UserSettingsController::FindSettingsDescriptions (CommandInterpreter &interpreter, 1156 UserSettingsControllerSP root, 1157 std::string ¤t_prefix, 1158 const char *search_name, 1159 Stream &result_stream, 1160 Error &err) 1161 { 1162 Args names = UserSettingsController::BreakNameIntoPieces (search_name); 1163 int num_pieces = names.GetArgumentCount (); 1164 1165 if (num_pieces == 0) 1166 return; 1167 1168 if (root->GetLevelName().GetLength() > 0) 1169 { 1170 ConstString prefix (names.GetArgumentAtIndex (0)); 1171 if (prefix != root->GetLevelName()) 1172 { 1173 std::string parent_prefix; 1174 root->BuildParentPrefix (parent_prefix); 1175 err.SetErrorStringWithFormat ("Cannot find match for '%s.%s'\n", parent_prefix.c_str(), 1176 prefix.AsCString()); 1177 return; 1178 } 1179 else 1180 { 1181 names.Shift(); 1182 --num_pieces; 1183 } 1184 } 1185 1186 // If there's nothing left then dump all global and instance descriptions for this root. 1187 if (num_pieces == 0) 1188 { 1189 StreamString prefix_line; 1190 StreamString description; 1191 uint32_t max_len; 1192 int num_entries = root->m_settings.global_settings.size(); 1193 1194 max_len = FindMaxNameLength (root->m_settings.global_settings); 1195 1196 result_stream.Printf ("\n'%s' variables:\n\n", search_name); 1197 1198 if (num_entries > 0) 1199 { 1200 // Write out all "global" variables. 1201 for (int i = 0; i < num_entries; ++i) 1202 { 1203 DumpSettingEntry (interpreter, result_stream, max_len, root->m_settings.global_settings[i]); 1204 } 1205 } 1206 1207 num_entries = root->m_settings.instance_settings.size(); 1208 max_len = FindMaxNameLength (root->m_settings.instance_settings); 1209 1210 if (num_entries > 0) 1211 { 1212 // Write out all instance variables. 1213 for (int i = 0; i < num_entries; ++i) 1214 { 1215 DumpSettingEntry (interpreter, result_stream, max_len, root->m_settings.instance_settings[i]); 1216 } 1217 } 1218 } 1219 else if (num_pieces == 1) 1220 { 1221 ConstString var_name (names.GetArgumentAtIndex (0)); 1222 bool is_global = false; 1223 1224 const SettingEntry *setting_entry = root->GetGlobalEntry (var_name); 1225 1226 if (setting_entry == NULL) 1227 setting_entry = root->GetInstanceEntry (var_name); 1228 else 1229 is_global = true; 1230 1231 // Check to see if it is a global or instance variable name. 1232 if (setting_entry != NULL) 1233 { 1234 DumpSettingEntry (interpreter, result_stream, var_name.GetLength(), *setting_entry); 1235 } 1236 else 1237 { 1238 // It must be a child name. 1239 int num_children = root->GetNumChildren(); 1240 bool found = false; 1241 for (int i = 0; i < num_children && !found; ++i) 1242 { 1243 UserSettingsControllerSP child = root->GetChildAtIndex (i); 1244 if (child) 1245 { 1246 ConstString child_prefix = child->GetLevelName(); 1247 if (child_prefix == var_name) 1248 { 1249 found = true; 1250 UserSettingsController::FindSettingsDescriptions (interpreter, 1251 child, 1252 current_prefix, 1253 var_name.AsCString(), 1254 result_stream, 1255 err); 1256 } 1257 } 1258 } 1259 if (!found) 1260 { 1261 std::string parent_prefix; 1262 root->BuildParentPrefix (parent_prefix); 1263 err.SetErrorStringWithFormat ("Cannot find match for '%s.%s'\n", parent_prefix.c_str(), search_name); 1264 return; 1265 } 1266 } 1267 } 1268 else 1269 { 1270 // It must be a child name; find the child and call this function recursively on child. 1271 ConstString child_name (names.GetArgumentAtIndex (0)); 1272 1273 StreamString rest_of_search_name; 1274 for (int i = 0; i < num_pieces; ++i) 1275 { 1276 rest_of_search_name.Printf ("%s", names.GetArgumentAtIndex (i)); 1277 if ((i + 1) < num_pieces) 1278 rest_of_search_name.Printf ("."); 1279 } 1280 1281 int num_children = root->GetNumChildren(); 1282 bool found = false; 1283 for (int i = 0; i < num_children && !found; ++i) 1284 { 1285 UserSettingsControllerSP child = root->GetChildAtIndex (i); 1286 if (child) 1287 { 1288 ConstString child_prefix = child->GetLevelName(); 1289 if (child_prefix == child_name) 1290 { 1291 found = true; 1292 UserSettingsController::FindSettingsDescriptions (interpreter, child, current_prefix, 1293 rest_of_search_name.GetData(), result_stream, 1294 err); 1295 } 1296 } 1297 } 1298 if (!found) 1299 { 1300 std::string parent_prefix; 1301 root->BuildParentPrefix (parent_prefix); 1302 err.SetErrorStringWithFormat ("Cannot find match for '%s.%s'\n", parent_prefix.c_str(), search_name); 1303 return; 1304 } 1305 } 1306 } 1307 1308 void 1309 UserSettingsController::SearchAllSettingsDescriptions (CommandInterpreter &interpreter, 1310 UserSettingsControllerSP root, 1311 std::string ¤t_prefix, 1312 const char *search_word, 1313 Stream &result_stream) 1314 { 1315 if ((search_word == NULL) || (strlen (search_word) == 0)) 1316 return; 1317 1318 int num_entries = root->m_settings.global_settings.size(); 1319 1320 if (num_entries > 0) 1321 { 1322 for (int i = 0; i < num_entries; ++i) 1323 { 1324 const SettingEntry &entry = root->m_settings.global_settings[i]; 1325 if (strcasestr (entry.description, search_word) != NULL) 1326 { 1327 StreamString var_name; 1328 if (current_prefix.size() > 0) 1329 var_name.Printf ("%s.%s", current_prefix.c_str(), entry.var_name); 1330 else 1331 var_name.Printf ("%s", entry.var_name); 1332 interpreter.OutputFormattedHelpText (result_stream, var_name.GetData(), "--", entry.description, 1333 var_name.GetSize()); 1334 } 1335 } 1336 } 1337 1338 num_entries = root->m_settings.instance_settings.size(); 1339 if (num_entries > 0) 1340 { 1341 for (int i = 0; i < num_entries; ++i) 1342 { 1343 SettingEntry &entry = root->m_settings.instance_settings[i]; 1344 if (strcasestr (entry.description, search_word) != NULL) 1345 { 1346 StreamString var_name; 1347 if (current_prefix.size() > 0) 1348 var_name.Printf ("%s.%s", current_prefix.c_str(), entry.var_name); 1349 else 1350 var_name.Printf ("%s", entry.var_name); 1351 interpreter.OutputFormattedHelpText (result_stream, var_name.GetData(), "--", entry.description, 1352 var_name.GetSize()); 1353 } 1354 } 1355 } 1356 1357 int num_children = root->GetNumChildren (); 1358 for (int i = 0; i < num_children; ++i) 1359 { 1360 UserSettingsControllerSP child = root->GetChildAtIndex (i); 1361 1362 if (child) 1363 { 1364 ConstString child_prefix = child->GetLevelName(); 1365 StreamString new_prefix; 1366 if (! current_prefix.empty()) 1367 new_prefix.Printf ("%s.%s", current_prefix.c_str(), child_prefix.AsCString()); 1368 else 1369 new_prefix.Printf ("%s", child_prefix.AsCString()); 1370 std::string new_prefix_str = new_prefix.GetData(); 1371 UserSettingsController::SearchAllSettingsDescriptions (interpreter, child, new_prefix_str, search_word, 1372 result_stream); 1373 } 1374 } 1375 } 1376 1377 void 1378 UserSettingsController::GetAllVariableValues (CommandInterpreter &interpreter, 1379 UserSettingsControllerSP root, 1380 std::string ¤t_prefix, 1381 Stream &result_stream, 1382 Error &err) 1383 { 1384 StreamString description; 1385 int num_entries = root->m_settings.global_settings.size(); 1386 SettableVariableType var_type; 1387 1388 1389 for (int i = 0; i < num_entries; ++i) 1390 { 1391 StreamString full_var_name; 1392 const SettingEntry &entry = root->m_settings.global_settings[i]; 1393 if (! current_prefix.empty()) 1394 full_var_name.Printf ("%s.%s", current_prefix.c_str(), entry.var_name); 1395 else 1396 full_var_name.Printf ("%s", entry.var_name); 1397 StringList value = root->GetVariable (full_var_name.GetData(), var_type, 1398 interpreter.GetDebugger().GetInstanceName().AsCString(), err); 1399 description.Clear(); 1400 if (value.GetSize() == 1) 1401 description.Printf ("%s (%s) = '%s'", full_var_name.GetData(), GetTypeString (entry.var_type), 1402 value.GetStringAtIndex (0)); 1403 else 1404 { 1405 description.Printf ("%s (%s):\n", full_var_name.GetData(), GetTypeString (entry.var_type)); 1406 for (int j = 0; j < value.GetSize(); ++j) 1407 if (entry.var_type == eSetVarTypeArray) 1408 description.Printf (" [%d]: '%s'\n", j, value.GetStringAtIndex (j)); 1409 else if (entry.var_type == eSetVarTypeDictionary) 1410 description.Printf (" '%s'\n", value.GetStringAtIndex (j)); 1411 } 1412 1413 result_stream.Printf ("%s\n", description.GetData()); 1414 } 1415 1416 root->GetAllInstanceVariableValues (interpreter, result_stream); 1417 root->GetAllPendingSettingValues (result_stream); 1418 if (root->GetLevelName().GetLength() > 0) // Don't bother with default values for Debugger level. 1419 root->GetAllDefaultSettingValues (result_stream); 1420 1421 1422 // Now, recurse across all children. 1423 int num_children = root->GetNumChildren(); 1424 for (int i = 0; i < num_children; ++i) 1425 { 1426 UserSettingsControllerSP child = root->GetChildAtIndex (i); 1427 1428 if (child) 1429 { 1430 ConstString child_prefix = child->GetLevelName(); 1431 StreamString new_prefix; 1432 if (! current_prefix.empty()) 1433 new_prefix.Printf ("%s.%s", current_prefix.c_str(), child_prefix.AsCString()); 1434 else 1435 new_prefix.Printf ("%s", child_prefix.AsCString()); 1436 std::string new_prefix_str = new_prefix.GetData(); 1437 UserSettingsController::GetAllVariableValues (interpreter, child, new_prefix_str, result_stream, 1438 err); 1439 } 1440 } 1441 1442 } 1443 1444 Args 1445 UserSettingsController::BreakNameIntoPieces (const char *full_dot_name) 1446 { 1447 Args return_value; 1448 std::string name_string (full_dot_name); 1449 bool done = false; 1450 1451 std::string piece; 1452 std::string remainder (full_dot_name); 1453 1454 while (!done) 1455 { 1456 size_t idx = remainder.find_first_of ('.'); 1457 piece = remainder.substr (0, idx); 1458 return_value.AppendArgument (piece.c_str()); 1459 if (idx != std::string::npos) 1460 remainder = remainder.substr (idx+1); 1461 else 1462 done = true; 1463 } 1464 1465 return return_value; 1466 } 1467 1468 bool 1469 UserSettingsController::IsLiveInstance (const std::string &instance_name) 1470 { 1471 std::map<std::string, InstanceSettings *>::iterator pos; 1472 1473 pos = m_live_settings.find (instance_name); 1474 if (pos != m_live_settings.end()) 1475 return true; 1476 1477 return false; 1478 } 1479 1480 int 1481 UserSettingsController::CompleteSettingsValue (UserSettingsControllerSP root_settings, 1482 const char *full_dot_name, 1483 const char *partial_value, 1484 bool &word_complete, 1485 StringList &matches) 1486 { 1487 Args names = UserSettingsController::BreakNameIntoPieces (full_dot_name); 1488 int num_pieces = names.GetArgumentCount(); 1489 word_complete = true; 1490 1491 ConstString root_level = root_settings->GetLevelName(); 1492 int num_extra_levels = num_pieces - 2; 1493 if ((num_extra_levels > 0) 1494 && root_level.GetLength() > 0) 1495 { 1496 ConstString current_level (names.GetArgumentAtIndex (0)); 1497 if (current_level == root_level) 1498 { 1499 names.Shift(); 1500 --num_extra_levels; 1501 } 1502 else 1503 return 0; 1504 } 1505 1506 for (int i = 0; i < num_extra_levels; ++i) 1507 { 1508 ConstString child_level (names.GetArgumentAtIndex (0)); 1509 bool found = false; 1510 int num_children = root_settings->GetNumChildren(); 1511 for (int j = 0; j < num_children && !found; ++j) 1512 { 1513 if (root_settings->GetChildAtIndex (j)->GetLevelName() == child_level) 1514 { 1515 found = true; 1516 root_settings = root_settings->GetChildAtIndex (j); 1517 names.Shift(); 1518 } 1519 } 1520 if (!found) 1521 return 0; 1522 } 1523 1524 if (names.GetArgumentCount() != 2) 1525 return 0; 1526 1527 std::string next_name (names.GetArgumentAtIndex (0)); 1528 int len = next_name.length(); 1529 names.Shift(); 1530 1531 if ((next_name[0] == '[') && (next_name[len-1] == ']')) 1532 { 1533 // 'next_name' is instance name. Instance names are irrelevent here. 1534 } 1535 else 1536 { 1537 // 'next_name' is child name. 1538 bool found = false; 1539 int num_children = root_settings->GetNumChildren(); 1540 ConstString child_level (next_name.c_str()); 1541 for (int j = 0; j < num_children && !found; ++j) 1542 { 1543 if (root_settings->GetChildAtIndex (j)->GetLevelName() == child_level) 1544 { 1545 found = true; 1546 root_settings = root_settings->GetChildAtIndex (j); 1547 } 1548 } 1549 if (!found) 1550 return 0; 1551 } 1552 1553 ConstString var_name (names.GetArgumentAtIndex(0)); 1554 const SettingEntry *entry = root_settings->GetGlobalEntry (var_name); 1555 if (entry == NULL) 1556 entry = root_settings->GetInstanceEntry (var_name); 1557 1558 if (entry == NULL) 1559 return 0; 1560 1561 if (entry->var_type == eSetVarTypeBoolean) 1562 return UserSettingsController::BooleanMatches (partial_value, word_complete, matches); 1563 else if (entry->var_type == eSetVarTypeEnum) 1564 return UserSettingsController::EnumMatches (partial_value, entry->enum_values, word_complete, matches); 1565 else 1566 return 0; 1567 } 1568 1569 int 1570 UserSettingsController::BooleanMatches (const char *partial_value, 1571 bool &word_complete, 1572 StringList &matches) 1573 { 1574 static const std::string true_string ("true"); 1575 static const std::string false_string ("false"); 1576 1577 if (partial_value == NULL) 1578 { 1579 matches.AppendString ("true"); 1580 matches.AppendString ("false"); 1581 } 1582 else 1583 { 1584 int partial_len = strlen (partial_value); 1585 1586 if ((partial_len <= true_string.length()) 1587 && (true_string.find (partial_value) == 0)) 1588 matches.AppendString ("true"); 1589 else if ((partial_len <= false_string.length()) 1590 && (false_string.find (partial_value) == 0)) 1591 matches.AppendString ("false"); 1592 } 1593 1594 word_complete = false; 1595 if (matches.GetSize() == 1) 1596 word_complete = true; 1597 1598 return matches.GetSize(); 1599 } 1600 1601 int 1602 UserSettingsController::EnumMatches (const char *partial_value, 1603 OptionEnumValueElement *enum_values, 1604 bool &word_complete, 1605 StringList &matches) 1606 { 1607 int len = (partial_value != NULL) ? strlen (partial_value) : 0; 1608 1609 int i = 0; 1610 while (enum_values[i].string_value != NULL) 1611 { 1612 if (len == 0) 1613 matches.AppendString (enum_values[i].string_value); 1614 else 1615 { 1616 std::string tmp_value (enum_values[i].string_value); 1617 if ((len <= tmp_value.length()) 1618 && tmp_value.find (partial_value) == 0) 1619 matches.AppendString (enum_values[i].string_value); 1620 } 1621 ++i; 1622 } 1623 1624 word_complete = false; 1625 if (matches.GetSize() == 1) 1626 word_complete = true; 1627 1628 return matches.GetSize(); 1629 } 1630 1631 int 1632 UserSettingsController::CompleteSettingsNames (UserSettingsControllerSP root_settings, 1633 Args &partial_setting_name_pieces, 1634 bool &word_complete, 1635 StringList &matches) 1636 { 1637 int num_matches = 0; 1638 int num_name_pieces = partial_setting_name_pieces.GetArgumentCount(); 1639 1640 if (num_name_pieces > 1) 1641 { 1642 // There are at least two pieces, perhaps with multiple level names preceding them. 1643 // First traverse all the extra levels, until we have exactly two pieces left. 1644 1645 int num_extra_levels = num_name_pieces - 2; 1646 1647 // Deal with current level first. 1648 1649 ConstString root_level = root_settings->GetLevelName(); 1650 if ((num_extra_levels > 0) 1651 && (root_level.GetLength() > 0)) 1652 { 1653 ConstString current_level (partial_setting_name_pieces.GetArgumentAtIndex (0)); 1654 if (current_level == root_level) 1655 { 1656 partial_setting_name_pieces.Shift(); 1657 --num_extra_levels; 1658 } 1659 else 1660 return 0; // The current level did not match the name pieces; something is wrong, so return immediately 1661 1662 } 1663 1664 for (int i = 0; i < num_extra_levels; ++i) 1665 { 1666 ConstString child_level (partial_setting_name_pieces.GetArgumentAtIndex (0)); 1667 bool found = false; 1668 int num_children = root_settings->GetNumChildren(); 1669 for (int j = 0; j < num_children && !found; ++j) 1670 { 1671 if (root_settings->GetChildAtIndex (j)->GetLevelName() == child_level) 1672 { 1673 found = true; 1674 root_settings = root_settings->GetChildAtIndex (j); 1675 partial_setting_name_pieces.Shift(); 1676 } 1677 } 1678 if (! found) 1679 { 1680 return 0; // Unable to find a matching child level name; something is wrong, so return immediately. 1681 } 1682 } 1683 1684 // Now there should be exactly two name pieces left. If not there is an error, so return immediately 1685 1686 if (partial_setting_name_pieces.GetArgumentCount() != 2) 1687 return 0; 1688 1689 std::string next_name (partial_setting_name_pieces.GetArgumentAtIndex (0)); 1690 int len = next_name.length(); 1691 partial_setting_name_pieces.Shift(); 1692 1693 if ((next_name[0] == '[') && (next_name[len-1] == ']')) 1694 { 1695 // 'next_name' is an instance name. The last name piece must be a non-empty partial match against an 1696 // instance_name, assuming 'next_name' is valid. 1697 1698 if (root_settings->IsLiveInstance (next_name)) 1699 { 1700 std::string complete_prefix; 1701 root_settings->BuildParentPrefix (complete_prefix); 1702 1703 num_matches = root_settings->InstanceVariableMatches(partial_setting_name_pieces.GetArgumentAtIndex(0), 1704 complete_prefix, 1705 next_name.c_str(), 1706 matches); 1707 word_complete = true; 1708 if (num_matches > 1) 1709 word_complete = false; 1710 1711 return num_matches; 1712 } 1713 else 1714 return 0; // Invalid instance_name 1715 } 1716 else 1717 { 1718 // 'next_name' must be a child name. Find the correct child and pass the remaining piece to be resolved. 1719 bool found = false; 1720 int num_children = root_settings->GetNumChildren(); 1721 ConstString child_level (next_name.c_str()); 1722 for (int i = 0; i < num_children; ++i) 1723 { 1724 if (root_settings->GetChildAtIndex (i)->GetLevelName() == child_level) 1725 { 1726 found = true; 1727 return UserSettingsController::CompleteSettingsNames (root_settings->GetChildAtIndex (i), 1728 partial_setting_name_pieces, 1729 word_complete, matches); 1730 } 1731 } 1732 if (!found) 1733 return 0; 1734 } 1735 } 1736 else if (num_name_pieces == 1) 1737 { 1738 std::string complete_prefix; 1739 root_settings->BuildParentPrefix (complete_prefix); 1740 1741 word_complete = true; 1742 std::string name (partial_setting_name_pieces.GetArgumentAtIndex (0)); 1743 1744 if (name[0] == '[') 1745 { 1746 // It's a partial instance name. 1747 1748 num_matches = root_settings->LiveInstanceMatches (name.c_str(), complete_prefix, word_complete, matches); 1749 } 1750 else 1751 { 1752 // It could be anything *except* an instance name... 1753 1754 num_matches = root_settings->GlobalVariableMatches (name.c_str(), complete_prefix, matches); 1755 num_matches += root_settings->InstanceVariableMatches (name.c_str(), complete_prefix, NULL, matches); 1756 num_matches += root_settings->ChildMatches (name.c_str(), complete_prefix, word_complete, matches); 1757 } 1758 1759 if (num_matches > 1) 1760 word_complete = false; 1761 1762 return num_matches; 1763 } 1764 else 1765 { 1766 // We have a user settings controller with a blank partial string. Return everything possible at this level. 1767 1768 std::string complete_prefix; 1769 root_settings->BuildParentPrefix (complete_prefix); 1770 num_matches = root_settings->GlobalVariableMatches (NULL, complete_prefix, matches); 1771 num_matches += root_settings->InstanceVariableMatches (NULL, complete_prefix, NULL, matches); 1772 num_matches += root_settings->LiveInstanceMatches (NULL, complete_prefix, word_complete, matches); 1773 num_matches += root_settings->ChildMatches (NULL, complete_prefix, word_complete, matches); 1774 word_complete = false; 1775 return num_matches; 1776 } 1777 1778 return num_matches; 1779 } 1780 1781 int 1782 UserSettingsController::GlobalVariableMatches (const char *partial_name, 1783 const std::string &complete_prefix, 1784 StringList &matches) 1785 { 1786 int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0; 1787 int num_matches = 0; 1788 1789 for (size_t i = 0; i < m_settings.global_settings.size(); ++i) 1790 { 1791 const SettingEntry &entry = m_settings.global_settings[i]; 1792 std::string var_name (entry.var_name); 1793 if ((partial_len == 0) 1794 || ((partial_len <= var_name.length()) 1795 && (var_name.find (partial_name) == 0))) 1796 { 1797 StreamString match_name; 1798 if (complete_prefix.length() > 0) 1799 { 1800 match_name.Printf ("%s.%s", complete_prefix.c_str(), var_name.c_str()); 1801 matches.AppendString (match_name.GetData()); 1802 } 1803 else 1804 matches.AppendString (var_name.c_str()); 1805 ++num_matches; 1806 } 1807 } 1808 return num_matches; 1809 } 1810 1811 int 1812 UserSettingsController::InstanceVariableMatches (const char *partial_name, 1813 const std::string &complete_prefix, 1814 const char *instance_name, 1815 StringList &matches) 1816 { 1817 int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0; 1818 int num_matches = 0; 1819 1820 for (size_t i = 0; i < m_settings.instance_settings.size(); ++i) 1821 { 1822 SettingEntry &entry = m_settings.instance_settings[i]; 1823 std::string var_name (entry.var_name); 1824 if ((partial_len == 0) 1825 || ((partial_len <= var_name.length()) 1826 && (var_name.find (partial_name) == 0))) 1827 { 1828 StreamString match_name; 1829 if (complete_prefix.length() > 0) 1830 { 1831 if (instance_name != NULL) 1832 match_name.Printf ("%s.%s.%s", complete_prefix.c_str(), instance_name, var_name.c_str()); 1833 else 1834 match_name.Printf ("%s.%s", complete_prefix.c_str(), var_name.c_str()); 1835 1836 matches.AppendString (match_name.GetData()); 1837 } 1838 else 1839 { 1840 if (instance_name != NULL) 1841 { 1842 match_name.Printf ("%s.%s", instance_name, var_name.c_str()); 1843 matches.AppendString (match_name.GetData()); 1844 } 1845 else 1846 matches.AppendString (var_name.c_str()); 1847 } 1848 ++num_matches; 1849 } 1850 } 1851 return num_matches; 1852 } 1853 1854 int 1855 UserSettingsController::LiveInstanceMatches (const char *partial_name, 1856 const std::string &complete_prefix, 1857 bool &word_complete, 1858 StringList &matches) 1859 { 1860 int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0; 1861 int num_matches = 0; 1862 1863 std::map<std::string, InstanceSettings*>::iterator pos; 1864 for (pos = m_live_settings.begin(); pos != m_live_settings.end(); ++pos) 1865 { 1866 std::string instance_name = pos->first; 1867 if ((partial_len == 0) 1868 || ((partial_len <= instance_name.length()) 1869 && (instance_name.find (partial_name) == 0))) 1870 { 1871 StreamString match_name; 1872 if (complete_prefix.length() > 0) 1873 match_name.Printf ("%s.%s.", complete_prefix.c_str(), instance_name.c_str()); 1874 else 1875 match_name.Printf ("%s.", instance_name.c_str()); 1876 matches.AppendString (match_name.GetData()); 1877 ++num_matches; 1878 } 1879 } 1880 1881 if (num_matches > 0) 1882 word_complete = false; 1883 1884 return num_matches; 1885 } 1886 1887 int 1888 UserSettingsController::ChildMatches (const char *partial_name, 1889 const std::string &complete_prefix, 1890 bool &word_complete, 1891 StringList &matches) 1892 { 1893 int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0; 1894 int num_children = GetNumChildren(); 1895 int num_matches = 0; 1896 for (int i = 0; i < num_children; ++i) 1897 { 1898 std::string child_name (GetChildAtIndex(i)->GetLevelName().AsCString()); 1899 StreamString match_name; 1900 if ((partial_len == 0) 1901 || ((partial_len <= child_name.length()) 1902 && (child_name.find (partial_name) == 0))) 1903 { 1904 if (complete_prefix.length() > 0) 1905 match_name.Printf ("%s.%s.", complete_prefix.c_str(), child_name.c_str()); 1906 else 1907 match_name.Printf ("%s.", child_name.c_str()); 1908 matches.AppendString (match_name.GetData()); 1909 ++num_matches; 1910 } 1911 } 1912 1913 if (num_matches > 0) 1914 word_complete = false; 1915 1916 return num_matches; 1917 } 1918 1919 void 1920 UserSettingsController::VerifyOperationForType (SettableVariableType var_type, 1921 VarSetOperationType op, 1922 const ConstString &var_name, 1923 Error &err) 1924 { 1925 if (op == eVarSetOperationAssign) 1926 return; 1927 1928 1929 if (op == eVarSetOperationInvalid) 1930 { 1931 err.SetErrorString ("Invalid 'settings ' subcommand operation.\n"); 1932 return; 1933 } 1934 1935 switch (op) 1936 { 1937 case eVarSetOperationInsertBefore: 1938 case eVarSetOperationInsertAfter: 1939 if (var_type != eSetVarTypeArray) 1940 err.SetErrorString ("Invalid operation: This operation can only be performed on array variables.\n"); 1941 break; 1942 case eVarSetOperationReplace: 1943 case eVarSetOperationRemove: 1944 if ((var_type != eSetVarTypeArray) 1945 && (var_type != eSetVarTypeDictionary)) 1946 err.SetErrorString ("Invalid operation: This operation can only be performed on array or dictionary" 1947 " variables.\n"); 1948 break; 1949 case eVarSetOperationAppend: 1950 case eVarSetOperationClear: 1951 if ((var_type != eSetVarTypeArray) 1952 && (var_type != eSetVarTypeDictionary) 1953 && (var_type != eSetVarTypeString)) 1954 err.SetErrorString ("Invalid operation: This operation can only be performed on array, dictionary " 1955 "or string variables.\n"); 1956 break; 1957 default: 1958 break; 1959 } 1960 1961 return; 1962 } 1963 1964 void 1965 UserSettingsController::UpdateStringVariable (VarSetOperationType op, 1966 std::string &string_var, 1967 const char *new_value, 1968 Error &err) 1969 { 1970 if (op == eVarSetOperationAssign) 1971 { 1972 if (new_value && new_value[0]) 1973 string_var.assign (new_value); 1974 else 1975 string_var.clear(); 1976 } 1977 else if (op == eVarSetOperationAppend) 1978 { 1979 if (new_value && new_value[0]) 1980 string_var.append (new_value); 1981 } 1982 else if (op == eVarSetOperationClear) 1983 string_var.clear(); 1984 else 1985 err.SetErrorString ("Unrecognized operation. Cannot update value.\n"); 1986 } 1987 1988 void 1989 UserSettingsController::UpdateBooleanVariable (VarSetOperationType op, 1990 bool &bool_var, 1991 const char *new_value, 1992 Error &err) 1993 { 1994 if (op != eVarSetOperationAssign) 1995 err.SetErrorString ("Invalid operation for Boolean variable. Cannot update value.\n"); 1996 1997 if (new_value && new_value[0]) 1998 { 1999 if ((::strcasecmp(new_value, "true") == 0) || 2000 (::strcasecmp(new_value, "yes") == 0) || 2001 (::strcasecmp(new_value, "on") == 0) || 2002 (::strcasecmp(new_value, "1") == 0)) 2003 bool_var = true; 2004 else 2005 if ((::strcasecmp(new_value, "false") == 0) || 2006 (::strcasecmp(new_value, "no") == 0) || 2007 (::strcasecmp(new_value, "off") == 0) || 2008 (::strcasecmp(new_value, "0") == 0)) 2009 bool_var = false; 2010 else 2011 err.SetErrorStringWithFormat ("Invalid boolean value '%s'\n", new_value); 2012 } 2013 else 2014 err.SetErrorString ("Invalid value. Cannot perform update.\n"); 2015 2016 } 2017 2018 void 2019 UserSettingsController::UpdateStringArrayVariable (VarSetOperationType op, 2020 const char *index_value, 2021 Args &array_var, 2022 const char *new_value, 2023 Error &err) 2024 { 2025 int index = -1; 2026 bool valid_index = true; 2027 2028 if (index_value != NULL) 2029 { 2030 for (int i = 0; i < strlen(index_value); ++i) 2031 if (!isdigit (index_value[i])) 2032 { 2033 valid_index = false; 2034 err.SetErrorStringWithFormat ("'%s' is not a valid integer index. Cannot update array value.\n", 2035 index_value); 2036 } 2037 2038 if (valid_index) 2039 index = atoi (index_value); 2040 2041 if (index < 0 2042 || index >= array_var.GetArgumentCount()) 2043 { 2044 valid_index = false; 2045 err.SetErrorStringWithFormat ("%d is outside the bounds of the specified array variable. " 2046 "Cannot update array value.\n", index); 2047 } 2048 } 2049 2050 switch (op) 2051 { 2052 case eVarSetOperationAssign: 2053 array_var.SetCommandString (new_value); 2054 break; 2055 case eVarSetOperationReplace: 2056 { 2057 if (valid_index) 2058 array_var.ReplaceArgumentAtIndex (index, new_value); 2059 break; 2060 } 2061 case eVarSetOperationInsertBefore: 2062 case eVarSetOperationInsertAfter: 2063 { 2064 if (valid_index) 2065 { 2066 Args new_array (new_value); 2067 if (op == eVarSetOperationInsertAfter) 2068 ++index; 2069 for (int i = 0; i < new_array.GetArgumentCount(); ++i) 2070 array_var.InsertArgumentAtIndex (index, new_array.GetArgumentAtIndex (i)); 2071 } 2072 break; 2073 } 2074 case eVarSetOperationRemove: 2075 { 2076 if (valid_index) 2077 array_var.DeleteArgumentAtIndex (index); 2078 break; 2079 } 2080 case eVarSetOperationAppend: 2081 { 2082 Args new_array (new_value); 2083 array_var.AppendArguments (new_array); 2084 break; 2085 } 2086 case eVarSetOperationClear: 2087 array_var.Clear(); 2088 break; 2089 default: 2090 err.SetErrorString ("Unrecognized operation. Cannot update value.\n"); 2091 break; 2092 } 2093 } 2094 2095 void 2096 UserSettingsController::UpdateDictionaryVariable (VarSetOperationType op, 2097 const char *index_value, 2098 std::map<std::string, std::string> &dictionary, 2099 const char *new_value, 2100 Error &err) 2101 { 2102 switch (op) 2103 { 2104 case eVarSetOperationReplace: 2105 if (index_value != NULL) 2106 { 2107 std::string key (index_value); 2108 std::map<std::string, std::string>::iterator pos; 2109 2110 pos = dictionary.find (key); 2111 if (pos != dictionary.end()) 2112 dictionary[key] = new_value; 2113 else 2114 err.SetErrorStringWithFormat ("'%s' is not an existing key; cannot replace value.\n", index_value); 2115 } 2116 else 2117 err.SetErrorString ("'settings replace' requires a key for dictionary variables. No key supplied.\n"); 2118 break; 2119 case eVarSetOperationRemove: 2120 if (index_value != NULL) 2121 { 2122 std::string key (index_value); 2123 dictionary.erase (key); 2124 } 2125 else 2126 err.SetErrorString ("'settings remove' requires a key for dictionary variables. No key supplied.\n"); 2127 break; 2128 case eVarSetOperationClear: 2129 dictionary.clear (); 2130 break; 2131 case eVarSetOperationAppend: 2132 case eVarSetOperationAssign: 2133 { 2134 // Clear the dictionary if it's an assign with new_value as NULL. 2135 if (new_value == NULL && op == eVarSetOperationAssign) 2136 { 2137 dictionary.clear (); 2138 break; 2139 } 2140 Args args (new_value); 2141 size_t num_args = args.GetArgumentCount(); 2142 RegularExpression regex("(\\[\"?)?" // Regex match 1 (optional key prefix of '["' pr '[') 2143 "([A-Za-z_][A-Za-z_0-9]*)" // Regex match 2 (key string) 2144 "(\"?\\])?" // Regex match 3 (optional key suffix of '"]' pr ']') 2145 "=" // The equal sign that is required 2146 "(.*)"); // Regex match 4 (value string) 2147 std::string key, value; 2148 2149 for (size_t i = 0; i < num_args; ++i) 2150 { 2151 const char *key_equal_value_arg = args.GetArgumentAtIndex (i); 2152 // Execute the regular expression on each arg. 2153 if (regex.Execute(key_equal_value_arg, 5)) 2154 { 2155 // The regular expression succeeded. The match at index 2156 // zero will be the entire string that matched the entire 2157 // regular expression. The match at index 1 - 4 will be 2158 // as mentioned above by the creation of the regex pattern. 2159 // Match index 2 is the key, match index 4 is the value. 2160 regex.GetMatchAtIndex (key_equal_value_arg, 2, key); 2161 regex.GetMatchAtIndex (key_equal_value_arg, 4, value); 2162 dictionary[key] = value; 2163 } 2164 else 2165 { 2166 err.SetErrorString ("Invalid format for dictionary value. Expected one of '[\"<key>\"]=<value>', '[<key>]=<value>', or '<key>=<value>'\n"); 2167 } 2168 } 2169 } 2170 break; 2171 case eVarSetOperationInsertBefore: 2172 case eVarSetOperationInsertAfter: 2173 err.SetErrorString ("Specified operation cannot be performed on dictionary variables.\n"); 2174 break; 2175 default: 2176 err.SetErrorString ("Unrecognized operation.\n"); 2177 break; 2178 } 2179 } 2180 2181 const char * 2182 UserSettingsController::EnumToString (const OptionEnumValueElement *enum_values, 2183 int value) 2184 { 2185 int i = 0; 2186 while (enum_values[i].string_value != NULL) 2187 { 2188 if (enum_values[i].value == value) 2189 return enum_values[i].string_value; 2190 ++i; 2191 } 2192 2193 return ""; 2194 } 2195 2196 2197 void 2198 UserSettingsController::UpdateEnumVariable (OptionEnumValueElement *enum_values, 2199 int *enum_var, 2200 const char *new_value, 2201 Error &err) 2202 { 2203 bool found_one; 2204 2205 *enum_var = Args::StringToOptionEnum (new_value, enum_values, enum_values[0].value, &found_one); 2206 2207 if (!found_one) 2208 err.SetErrorString ("Invalid enumeration value; cannot update variable.\n"); 2209 } 2210 2211 void 2212 UserSettingsController::RenameInstanceSettings (const char *old_name, const char *new_name) 2213 { 2214 Mutex::Locker live_mutex (m_live_settings_mutex); 2215 Mutex::Locker pending_mutex (m_pending_settings_mutex); 2216 std::string old_name_key (old_name); 2217 std::string new_name_key (new_name); 2218 2219 // First, find the live instance settings for the old_name. If they don't exist in the live settings 2220 // list, then this is not a setting that can be renamed. 2221 2222 if ((old_name_key[0] != '[') || (old_name_key[old_name_key.size() -1] != ']')) 2223 { 2224 StreamString tmp_str; 2225 tmp_str.Printf ("[%s]", old_name); 2226 old_name_key = tmp_str.GetData(); 2227 } 2228 2229 if ((new_name_key[0] != '[') || (new_name_key[new_name_key.size() -1] != ']')) 2230 { 2231 StreamString tmp_str; 2232 tmp_str.Printf ("[%s]", new_name); 2233 new_name_key = tmp_str.GetData(); 2234 } 2235 2236 if (old_name_key.compare (new_name_key) == 0) 2237 return; 2238 2239 size_t len = new_name_key.length(); 2240 std::string stripped_new_name = new_name_key.substr (1, len-2); // new name without the '[ ]' 2241 2242 std::map<std::string, InstanceSettings *>::iterator pos; 2243 2244 pos = m_live_settings.find (old_name_key); 2245 if (pos != m_live_settings.end()) 2246 { 2247 InstanceSettings *live_settings = pos->second; 2248 2249 // Rename the settings. 2250 live_settings->ChangeInstanceName (stripped_new_name); 2251 2252 // Now see if there are any pending settings for the new name; if so, copy them into live_settings. 2253 std::map<std::string, InstanceSettingsSP>::iterator pending_pos; 2254 pending_pos = m_pending_settings.find (new_name_key); 2255 if (pending_pos != m_pending_settings.end()) 2256 { 2257 InstanceSettingsSP pending_settings_sp = pending_pos->second; 2258 live_settings->CopyInstanceSettings (pending_settings_sp, false); 2259 } 2260 2261 // Erase the old entry (under the old name) from live settings. 2262 m_live_settings.erase (pos); 2263 2264 // Add the new entry, with the new name, into live settings. 2265 m_live_settings[new_name_key] = live_settings; 2266 } 2267 } 2268 2269 //---------------------------------------------------------------------- 2270 // class InstanceSettings 2271 //---------------------------------------------------------------------- 2272 2273 InstanceSettings::InstanceSettings (UserSettingsController &owner, const char *instance_name, bool live_instance) : 2274 m_owner (owner), 2275 m_instance_name (instance_name) 2276 { 2277 if ((m_instance_name != InstanceSettings::GetDefaultName()) 2278 && (m_instance_name != InstanceSettings::InvalidName()) 2279 && live_instance) 2280 m_owner.RegisterInstanceSettings (this); 2281 } 2282 2283 InstanceSettings::~InstanceSettings () 2284 { 2285 if (m_instance_name != InstanceSettings::GetDefaultName()) 2286 m_owner.UnregisterInstanceSettings (this); 2287 } 2288 2289 const ConstString & 2290 InstanceSettings::GetDefaultName () 2291 { 2292 static const ConstString g_default_settings_name ("[DEFAULT]"); 2293 2294 return g_default_settings_name; 2295 } 2296 2297 const ConstString & 2298 InstanceSettings::InvalidName () 2299 { 2300 static const ConstString g_invalid_name ("Invalid instance name"); 2301 2302 return g_invalid_name; 2303 } 2304 2305 void 2306 InstanceSettings::ChangeInstanceName (const std::string &new_instance_name) 2307 { 2308 m_instance_name.SetCString (new_instance_name.c_str()); 2309 } 2310 2311 2312