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