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