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", 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"); 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", 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", 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", 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", 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", 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() == 1) 863 value_str.Printf ("%s", tmp_value.GetStringAtIndex (0)); 864 else 865 { 866 for (int j = 0; j < tmp_value.GetSize(); ++j) 867 value_str.Printf ("%s ", tmp_value.GetStringAtIndex (j)); 868 } 869 870 if (parent_prefix.length() > 0) 871 { 872 strm.Printf ("%s.%s.%s (%s) = '%s' [pending]\n", prefix, instance_name.GetCString(), 873 var_name.GetCString(), UserSettingsController::GetTypeString (entry.var_type), 874 value_str.GetData()); 875 } 876 else 877 { 878 strm.Printf ("%s (%s) = '%s' [pending]\n", var_name.GetCString(), 879 UserSettingsController::GetTypeString (entry.var_type), 880 value_str.GetData()); 881 } 882 } 883 } 884 } 885 886 InstanceSettings * 887 UserSettingsController::FindSettingsForInstance (const ConstString &instance_name) 888 { 889 std::string instance_name_str (instance_name.GetCString()); 890 Mutex::Locker locker (m_live_settings_mutex); 891 InstanceSettingsMap::iterator pos = m_live_settings.find (instance_name_str); 892 if (pos != m_live_settings.end ()) 893 return pos->second; 894 return NULL; 895 } 896 897 void 898 UserSettingsController::GetAllInstanceVariableValues (CommandInterpreter &interpreter, 899 Stream &strm) 900 { 901 std::string parent_prefix; 902 BuildParentPrefix (parent_prefix); 903 StreamString description; 904 905 Mutex::Locker locker (m_live_settings_mutex); 906 for (InstanceSettingsMap::iterator pos = m_live_settings.begin(); pos != m_live_settings.end(); ++pos) 907 { 908 std::string instance_name = pos->first; 909 InstanceSettings *settings = pos->second; 910 911 for (int i = 0; i < m_settings.instance_settings.size(); ++i) 912 { 913 SettingEntry &entry = m_settings.instance_settings[i]; 914 const ConstString var_name (entry.var_name); 915 StringList tmp_value; 916 settings->GetInstanceSettingsValue (entry, var_name, tmp_value, NULL); 917 918 if (!parent_prefix.empty()) 919 strm.Printf ("%s.", parent_prefix.c_str()); 920 921 DumpValue(var_name.GetCString(), entry.var_type, tmp_value, strm); 922 } 923 } 924 } 925 926 void 927 UserSettingsController::OverrideAllInstances (const ConstString &var_name, 928 const char *value, 929 VarSetOperationType op, 930 const char *index_value, 931 Error &err) 932 { 933 StreamString description; 934 935 Mutex::Locker locker (m_live_settings_mutex); 936 for (InstanceSettingsMap::iterator pos = m_live_settings.begin(); pos != m_live_settings.end(); ++pos) 937 { 938 InstanceSettings *settings = pos->second; 939 StreamString tmp_name; 940 tmp_name.Printf ("[%s]", settings->GetInstanceName().GetCString()); 941 const ConstString instance_name (tmp_name.GetData()); 942 const SettingEntry *entry = GetInstanceEntry (var_name); 943 settings->UpdateInstanceSettingsVariable (var_name, index_value, value, instance_name, *entry, op, err, false); 944 945 } 946 } 947 948 void 949 UserSettingsController::RegisterInstanceSettings (InstanceSettings *instance_settings) 950 { 951 Mutex::Locker locker (m_live_settings_mutex); 952 StreamString tmp_name; 953 tmp_name.Printf ("[%s]", instance_settings->GetInstanceName().GetCString()); 954 const ConstString instance_name (tmp_name.GetData()); 955 std::string instance_name_str (instance_name.GetCString()); 956 if (instance_name_str.compare (InstanceSettings::GetDefaultName().GetCString()) != 0) 957 m_live_settings[instance_name_str] = instance_settings; 958 } 959 960 void 961 UserSettingsController::UnregisterInstanceSettings (InstanceSettings *instance) 962 { 963 Mutex::Locker locker (m_live_settings_mutex); 964 StreamString tmp_name; 965 tmp_name.Printf ("[%s]", instance->GetInstanceName().GetCString()); 966 std::string instance_name (tmp_name.GetData()); 967 968 InstanceSettingsMap::iterator pos = m_live_settings.find (instance_name); 969 if (pos != m_live_settings.end()) 970 m_live_settings.erase (pos); 971 } 972 973 void 974 UserSettingsController::CreateSettingsVector (const SettingEntry *table, 975 bool global) 976 { 977 int i = 0; 978 while (table[i].var_name != NULL) 979 { 980 const SettingEntry &table_entry = table[i]; 981 ConstString const_var_name (table_entry.var_name); 982 SettingEntry new_entry; 983 984 new_entry = table_entry; 985 new_entry.var_name = const_var_name.GetCString(); 986 987 if (global) 988 m_settings.global_settings.push_back (new_entry); 989 else 990 m_settings.instance_settings.push_back (new_entry); 991 992 ++i; 993 } 994 } 995 996 //---------------------------------------------------------------------- 997 // UserSettingsController static methods 998 //---------------------------------------------------------------------- 999 1000 int 1001 FindMaxNameLength (std::vector<SettingEntry> table) 1002 { 1003 int max_length = 1; 1004 1005 for (int i = 0; i < table.size(); ++i) 1006 { 1007 int len = strlen (table[i].var_name); 1008 if (len > max_length) 1009 max_length = len; 1010 } 1011 1012 return max_length; 1013 } 1014 1015 const char * 1016 UserSettingsController::GetTypeString (SettableVariableType var_type) 1017 { 1018 switch (var_type) 1019 { 1020 case eSetVarTypeInt: 1021 return "int"; 1022 case eSetVarTypeBoolean: 1023 return "boolean"; 1024 case eSetVarTypeString: 1025 return "string"; 1026 case eSetVarTypeArray: 1027 return "array"; 1028 case eSetVarTypeDictionary: 1029 return "dictionary"; 1030 case eSetVarTypeEnum: 1031 return "enum"; 1032 case eSetVarTypeNone: 1033 return "no type"; 1034 } 1035 1036 return ""; 1037 } 1038 1039 void 1040 UserSettingsController::PrintEnumValues (const OptionEnumValueElement *enum_values, Stream &str) 1041 { 1042 int i = 0; 1043 while (enum_values[i].string_value != NULL) 1044 { 1045 str.Printf ("%s ", enum_values[i].string_value); 1046 ++i; 1047 } 1048 1049 } 1050 1051 void 1052 UserSettingsController::FindAllSettingsDescriptions (CommandInterpreter &interpreter, 1053 const UserSettingsControllerSP& usc_sp, 1054 const char *current_prefix, 1055 Stream &strm, 1056 Error &err) 1057 { 1058 // Write out current prefix line. 1059 StreamString prefix_line; 1060 StreamString description; 1061 uint32_t max_len = FindMaxNameLength (usc_sp->m_settings.global_settings); 1062 int num_entries = usc_sp->m_settings.global_settings.size(); 1063 1064 if (current_prefix && current_prefix[0]) 1065 strm.Printf ("\n'%s' variables:\n\n", current_prefix); 1066 else 1067 strm.Printf ("\nTop level variables:\n\n"); 1068 1069 if (num_entries > 0) 1070 { 1071 // Write out all "global" variables. 1072 for (int i = 0; i < num_entries; ++i) 1073 { 1074 DumpSettingEntry (interpreter, strm, max_len, usc_sp->m_settings.global_settings[i]); 1075 } 1076 } 1077 1078 num_entries = usc_sp->m_settings.instance_settings.size(); 1079 max_len = FindMaxNameLength (usc_sp->m_settings.instance_settings); 1080 1081 if (num_entries > 0) 1082 { 1083 // Write out all instance variables. 1084 for (int i = 0; i < num_entries; ++i) 1085 { 1086 DumpSettingEntry (interpreter, strm, max_len, usc_sp->m_settings.instance_settings[i]); 1087 } 1088 } 1089 1090 // Now, recurse across all children. 1091 int num_children = usc_sp->GetNumChildren(); 1092 for (int i = 0; i < num_children; ++i) 1093 { 1094 UserSettingsControllerSP child = usc_sp->GetChildAtIndex (i); 1095 1096 if (child) 1097 { 1098 ConstString child_prefix = child->GetLevelName(); 1099 if (current_prefix && current_prefix[0]) 1100 { 1101 StreamString new_prefix; 1102 new_prefix.Printf ("%s.%s", current_prefix, child_prefix.GetCString()); 1103 UserSettingsController::FindAllSettingsDescriptions (interpreter, 1104 child, 1105 new_prefix.GetData(), 1106 strm, 1107 err); 1108 } 1109 else 1110 { 1111 UserSettingsController::FindAllSettingsDescriptions (interpreter, 1112 child, 1113 child_prefix.GetCString(), 1114 strm, 1115 err); 1116 } 1117 } 1118 } 1119 } 1120 1121 void 1122 UserSettingsController::FindSettingsDescriptions (CommandInterpreter &interpreter, 1123 const UserSettingsControllerSP& usc_sp, 1124 const char *current_prefix, 1125 const char *search_name, 1126 Stream &strm, 1127 Error &err) 1128 { 1129 Args names = UserSettingsController::BreakNameIntoPieces (search_name); 1130 int num_pieces = names.GetArgumentCount (); 1131 1132 if (num_pieces == 0) 1133 return; 1134 1135 if (usc_sp->GetLevelName().GetLength() > 0) 1136 { 1137 ConstString prefix (names.GetArgumentAtIndex (0)); 1138 if (prefix != usc_sp->GetLevelName()) 1139 { 1140 std::string parent_prefix; 1141 usc_sp->BuildParentPrefix (parent_prefix); 1142 err.SetErrorStringWithFormat ("cannot find match for '%s.%s'", parent_prefix.c_str(), 1143 prefix.GetCString()); 1144 return; 1145 } 1146 else 1147 { 1148 names.Shift(); 1149 --num_pieces; 1150 } 1151 } 1152 1153 // If there's nothing left then dump all global and instance descriptions for this root. 1154 if (num_pieces == 0) 1155 { 1156 StreamString prefix_line; 1157 StreamString description; 1158 uint32_t max_len; 1159 int num_entries = usc_sp->m_settings.global_settings.size(); 1160 1161 max_len = FindMaxNameLength (usc_sp->m_settings.global_settings); 1162 1163 strm.Printf ("\n'%s' variables:\n\n", search_name); 1164 1165 if (num_entries > 0) 1166 { 1167 // Write out all "global" variables. 1168 for (int i = 0; i < num_entries; ++i) 1169 { 1170 DumpSettingEntry (interpreter, strm, max_len, usc_sp->m_settings.global_settings[i]); 1171 } 1172 } 1173 1174 num_entries = usc_sp->m_settings.instance_settings.size(); 1175 max_len = FindMaxNameLength (usc_sp->m_settings.instance_settings); 1176 1177 if (num_entries > 0) 1178 { 1179 // Write out all instance variables. 1180 for (int i = 0; i < num_entries; ++i) 1181 { 1182 DumpSettingEntry (interpreter, strm, max_len, usc_sp->m_settings.instance_settings[i]); 1183 } 1184 } 1185 } 1186 else if (num_pieces == 1) 1187 { 1188 ConstString var_name (names.GetArgumentAtIndex (0)); 1189 bool is_global = false; 1190 1191 const SettingEntry *setting_entry = usc_sp->GetGlobalEntry (var_name); 1192 1193 if (setting_entry == NULL) 1194 setting_entry = usc_sp->GetInstanceEntry (var_name); 1195 else 1196 is_global = true; 1197 1198 // Check to see if it is a global or instance variable name. 1199 if (setting_entry != NULL) 1200 { 1201 DumpSettingEntry (interpreter, strm, var_name.GetLength(), *setting_entry); 1202 } 1203 else 1204 { 1205 // It must be a child name. 1206 int num_children = usc_sp->GetNumChildren(); 1207 bool found = false; 1208 for (int i = 0; i < num_children && !found; ++i) 1209 { 1210 UserSettingsControllerSP child = usc_sp->GetChildAtIndex (i); 1211 if (child) 1212 { 1213 ConstString child_prefix = child->GetLevelName(); 1214 if (child_prefix == var_name) 1215 { 1216 found = true; 1217 UserSettingsController::FindSettingsDescriptions (interpreter, 1218 child, 1219 current_prefix, 1220 var_name.GetCString(), 1221 strm, 1222 err); 1223 } 1224 } 1225 } 1226 if (!found) 1227 { 1228 std::string parent_prefix; 1229 usc_sp->BuildParentPrefix (parent_prefix); 1230 err.SetErrorStringWithFormat ("cannot find match for '%s.%s'", parent_prefix.c_str(), search_name); 1231 return; 1232 } 1233 } 1234 } 1235 else 1236 { 1237 // It must be a child name; find the child and call this function recursively on child. 1238 ConstString child_name (names.GetArgumentAtIndex (0)); 1239 1240 StreamString rest_of_search_name; 1241 for (int i = 0; i < num_pieces; ++i) 1242 { 1243 rest_of_search_name.Printf ("%s", names.GetArgumentAtIndex (i)); 1244 if ((i + 1) < num_pieces) 1245 rest_of_search_name.Printf ("."); 1246 } 1247 1248 int num_children = usc_sp->GetNumChildren(); 1249 bool found = false; 1250 for (int i = 0; i < num_children && !found; ++i) 1251 { 1252 UserSettingsControllerSP child = usc_sp->GetChildAtIndex (i); 1253 if (child) 1254 { 1255 ConstString child_prefix = child->GetLevelName(); 1256 if (child_prefix == child_name) 1257 { 1258 found = true; 1259 UserSettingsController::FindSettingsDescriptions (interpreter, child, current_prefix, 1260 rest_of_search_name.GetData(), strm, 1261 err); 1262 } 1263 } 1264 } 1265 if (!found) 1266 { 1267 std::string parent_prefix; 1268 usc_sp->BuildParentPrefix (parent_prefix); 1269 err.SetErrorStringWithFormat ("cannot find match for '%s.%s'", parent_prefix.c_str(), search_name); 1270 return; 1271 } 1272 } 1273 } 1274 1275 void 1276 UserSettingsController::SearchAllSettingsDescriptions (CommandInterpreter &interpreter, 1277 const UserSettingsControllerSP& usc_sp, 1278 const char *current_prefix, 1279 const char *search_word, 1280 Stream &strm) 1281 { 1282 if ((search_word == NULL) || (strlen (search_word) == 0)) 1283 return; 1284 1285 int num_entries = usc_sp->m_settings.global_settings.size(); 1286 1287 if (num_entries > 0) 1288 { 1289 for (int i = 0; i < num_entries; ++i) 1290 { 1291 const SettingEntry &entry = usc_sp->m_settings.global_settings[i]; 1292 if (strcasestr (entry.description, search_word) != NULL) 1293 { 1294 StreamString var_name; 1295 if (current_prefix && current_prefix[0]) 1296 var_name.Printf ("%s.%s", current_prefix, entry.var_name); 1297 else 1298 var_name.Printf ("%s", entry.var_name); 1299 interpreter.OutputFormattedHelpText (strm, var_name.GetData(), "--", entry.description, 1300 var_name.GetSize()); 1301 } 1302 } 1303 } 1304 1305 num_entries = usc_sp->m_settings.instance_settings.size(); 1306 if (num_entries > 0) 1307 { 1308 for (int i = 0; i < num_entries; ++i) 1309 { 1310 SettingEntry &entry = usc_sp->m_settings.instance_settings[i]; 1311 if (strcasestr (entry.description, search_word) != NULL) 1312 { 1313 StreamString var_name; 1314 if (current_prefix && current_prefix[0]) 1315 var_name.Printf ("%s.%s", current_prefix, entry.var_name); 1316 else 1317 var_name.Printf ("%s", entry.var_name); 1318 interpreter.OutputFormattedHelpText (strm, 1319 var_name.GetData(), 1320 "--", 1321 entry.description, 1322 var_name.GetSize()); 1323 } 1324 } 1325 } 1326 1327 int num_children = usc_sp->GetNumChildren (); 1328 for (int i = 0; i < num_children; ++i) 1329 { 1330 UserSettingsControllerSP child = usc_sp->GetChildAtIndex (i); 1331 1332 if (child) 1333 { 1334 ConstString child_prefix = child->GetLevelName(); 1335 if (current_prefix && current_prefix[0]) 1336 { 1337 StreamString new_prefix; 1338 new_prefix.Printf ("%s.%s", current_prefix, child_prefix.GetCString()); 1339 UserSettingsController::SearchAllSettingsDescriptions (interpreter, 1340 child, 1341 new_prefix.GetData(), 1342 search_word, 1343 strm); 1344 } 1345 else 1346 { 1347 UserSettingsController::SearchAllSettingsDescriptions (interpreter, 1348 child, 1349 child_prefix.GetCString(), 1350 search_word, 1351 strm); 1352 } 1353 } 1354 } 1355 } 1356 1357 bool 1358 UserSettingsController::DumpValue (CommandInterpreter &interpreter, 1359 const UserSettingsControllerSP& usc_sp, 1360 const char *variable_dot_name, 1361 Stream &strm) 1362 { 1363 SettableVariableType var_type; 1364 Error err; 1365 StringList value = usc_sp->GetVariable (variable_dot_name, 1366 var_type, 1367 interpreter.GetDebugger().GetInstanceName().GetCString(), 1368 err); 1369 1370 if (err.Success()) 1371 return DumpValue (variable_dot_name, var_type, value, strm); 1372 return false; 1373 } 1374 1375 1376 bool 1377 UserSettingsController::DumpValue (const char *variable_dot_name, 1378 SettableVariableType var_type, 1379 const StringList &value, 1380 Stream &strm) 1381 { 1382 const char *type_name = UserSettingsController::GetTypeString (var_type); 1383 1384 strm.Printf ("%s (%s) = ", variable_dot_name, type_name); 1385 if (value.GetSize() == 0) 1386 { 1387 strm.EOL(); 1388 } 1389 else 1390 { 1391 switch (var_type) 1392 { 1393 case eSetVarTypeNone: 1394 case eSetVarTypeEnum: 1395 case eSetVarTypeInt: 1396 case eSetVarTypeBoolean: 1397 strm.Printf ("%s\n", value.GetStringAtIndex (0)); 1398 break; 1399 1400 case eSetVarTypeString: 1401 strm.Printf ("\"%s\"\n", value.GetStringAtIndex (0)); 1402 break; 1403 1404 case eSetVarTypeArray: 1405 { 1406 strm.EOL(); 1407 for (unsigned i = 0, e = value.GetSize(); i != e; ++i) 1408 strm.Printf (" [%u]: \"%s\"\n", i, value.GetStringAtIndex (i)); 1409 } 1410 break; 1411 1412 case eSetVarTypeDictionary: 1413 { 1414 strm.EOL(); 1415 for (unsigned i = 0, e = value.GetSize(); i != e; ++i) 1416 strm.Printf (" %s\n", value.GetStringAtIndex (i)); 1417 } 1418 break; 1419 1420 default: 1421 return false; 1422 } 1423 } 1424 return true; 1425 } 1426 1427 void 1428 UserSettingsController::GetAllVariableValues (CommandInterpreter &interpreter, 1429 const UserSettingsControllerSP& usc_sp, 1430 const char *current_prefix, 1431 Stream &strm, 1432 Error &err) 1433 { 1434 StreamString description; 1435 int num_entries = usc_sp->m_settings.global_settings.size(); 1436 1437 for (int i = 0; i < num_entries; ++i) 1438 { 1439 StreamString full_var_name; 1440 const SettingEntry &entry = usc_sp->m_settings.global_settings[i]; 1441 1442 if (current_prefix && current_prefix[0]) 1443 full_var_name.Printf ("%s.%s", current_prefix, entry.var_name); 1444 else 1445 full_var_name.Printf ("%s", entry.var_name); 1446 1447 DumpValue (interpreter, usc_sp, full_var_name.GetData(), strm); 1448 } 1449 1450 usc_sp->GetAllInstanceVariableValues (interpreter, strm); 1451 usc_sp->GetAllPendingSettingValues (strm); 1452 if (usc_sp->GetLevelName().GetLength() > 0) // Don't bother with default values for Debugger level. 1453 usc_sp->GetAllDefaultSettingValues (strm); 1454 1455 1456 // Now, recurse across all children. 1457 int num_children = usc_sp->GetNumChildren(); 1458 for (int i = 0; i < num_children; ++i) 1459 { 1460 UserSettingsControllerSP child = usc_sp->GetChildAtIndex (i); 1461 1462 if (child) 1463 { 1464 ConstString child_prefix = child->GetLevelName(); 1465 if (current_prefix && current_prefix[0]) 1466 { 1467 StreamString new_prefix; 1468 new_prefix.Printf ("%s.%s", current_prefix, child_prefix.GetCString()); 1469 UserSettingsController::GetAllVariableValues (interpreter, 1470 child, 1471 new_prefix.GetData(), 1472 strm, 1473 err); 1474 } 1475 else 1476 { 1477 UserSettingsController::GetAllVariableValues (interpreter, 1478 child, 1479 child_prefix.GetCString(), 1480 strm, 1481 err); 1482 } 1483 } 1484 } 1485 1486 } 1487 1488 Args 1489 UserSettingsController::BreakNameIntoPieces (const char *full_dot_name) 1490 { 1491 Args return_value; 1492 std::string name_string (full_dot_name); 1493 bool done = false; 1494 1495 std::string piece; 1496 std::string remainder (full_dot_name); 1497 1498 while (!done) 1499 { 1500 size_t idx = remainder.find_first_of ('.'); 1501 piece = remainder.substr (0, idx); 1502 return_value.AppendArgument (piece.c_str()); 1503 if (idx != std::string::npos) 1504 remainder = remainder.substr (idx+1); 1505 else 1506 done = true; 1507 } 1508 1509 return return_value; 1510 } 1511 1512 bool 1513 UserSettingsController::IsLiveInstance (const std::string &instance_name) 1514 { 1515 Mutex::Locker locker (m_live_settings_mutex); 1516 InstanceSettingsMap::iterator pos = m_live_settings.find (instance_name); 1517 if (pos != m_live_settings.end()) 1518 return true; 1519 1520 return false; 1521 } 1522 1523 int 1524 UserSettingsController::CompleteSettingsValue (const UserSettingsControllerSP& usc_sp, 1525 const char *full_dot_name, 1526 const char *partial_value, 1527 bool &word_complete, 1528 StringList &matches) 1529 { 1530 Args names = UserSettingsController::BreakNameIntoPieces (full_dot_name); 1531 int num_pieces = names.GetArgumentCount(); 1532 word_complete = true; 1533 1534 ConstString root_level = usc_sp->GetLevelName(); 1535 int num_extra_levels = num_pieces - 2; 1536 if ((num_extra_levels > 0) 1537 && root_level.GetLength() > 0) 1538 { 1539 ConstString current_level (names.GetArgumentAtIndex (0)); 1540 if (current_level == root_level) 1541 { 1542 names.Shift(); 1543 --num_extra_levels; 1544 } 1545 else 1546 return 0; 1547 } 1548 1549 for (int i = 0; i < num_extra_levels; ++i) 1550 { 1551 ConstString child_level (names.GetArgumentAtIndex (0)); 1552 bool found = false; 1553 int num_children = usc_sp->GetNumChildren(); 1554 UserSettingsControllerSP child_usc_sp = usc_sp; 1555 for (int j = 0; j < num_children && !found; ++j) 1556 { 1557 if (child_usc_sp->GetChildAtIndex (j)->GetLevelName() == child_level) 1558 { 1559 found = true; 1560 child_usc_sp = child_usc_sp->GetChildAtIndex (j); 1561 names.Shift(); 1562 } 1563 } 1564 if (!found) 1565 return 0; 1566 } 1567 1568 if (names.GetArgumentCount() != 2) 1569 return 0; 1570 1571 std::string next_name (names.GetArgumentAtIndex (0)); 1572 int len = next_name.length(); 1573 names.Shift(); 1574 1575 if ((next_name[0] == '[') && (next_name[len-1] == ']')) 1576 { 1577 // 'next_name' is instance name. Instance names are irrelevent here. 1578 } 1579 else 1580 { 1581 // 'next_name' is child name. 1582 bool found = false; 1583 int num_children = usc_sp->GetNumChildren(); 1584 ConstString child_level (next_name.c_str()); 1585 UserSettingsControllerSP child_usc_sp = usc_sp; 1586 for (int j = 0; j < num_children && !found; ++j) 1587 { 1588 if (child_usc_sp->GetChildAtIndex (j)->GetLevelName() == child_level) 1589 { 1590 found = true; 1591 child_usc_sp = child_usc_sp->GetChildAtIndex (j); 1592 } 1593 } 1594 if (!found) 1595 return 0; 1596 } 1597 1598 ConstString var_name (names.GetArgumentAtIndex(0)); 1599 const SettingEntry *entry = usc_sp->GetGlobalEntry (var_name); 1600 if (entry == NULL) 1601 entry = usc_sp->GetInstanceEntry (var_name); 1602 1603 if (entry == NULL) 1604 return 0; 1605 1606 if (entry->var_type == eSetVarTypeBoolean) 1607 return UserSettingsController::BooleanMatches (partial_value, word_complete, matches); 1608 else if (entry->var_type == eSetVarTypeEnum) 1609 return UserSettingsController::EnumMatches (partial_value, entry->enum_values, word_complete, matches); 1610 else 1611 return 0; 1612 } 1613 1614 int 1615 UserSettingsController::BooleanMatches (const char *partial_value, 1616 bool &word_complete, 1617 StringList &matches) 1618 { 1619 static const std::string true_string ("true"); 1620 static const std::string false_string ("false"); 1621 1622 if (partial_value == NULL) 1623 { 1624 matches.AppendString ("true"); 1625 matches.AppendString ("false"); 1626 } 1627 else 1628 { 1629 int partial_len = strlen (partial_value); 1630 1631 if ((partial_len <= true_string.length()) 1632 && (true_string.find (partial_value) == 0)) 1633 matches.AppendString ("true"); 1634 else if ((partial_len <= false_string.length()) 1635 && (false_string.find (partial_value) == 0)) 1636 matches.AppendString ("false"); 1637 } 1638 1639 word_complete = false; 1640 if (matches.GetSize() == 1) 1641 word_complete = true; 1642 1643 return matches.GetSize(); 1644 } 1645 1646 int 1647 UserSettingsController::EnumMatches (const char *partial_value, 1648 OptionEnumValueElement *enum_values, 1649 bool &word_complete, 1650 StringList &matches) 1651 { 1652 int len = (partial_value != NULL) ? strlen (partial_value) : 0; 1653 1654 int i = 0; 1655 while (enum_values[i].string_value != NULL) 1656 { 1657 if (len == 0) 1658 matches.AppendString (enum_values[i].string_value); 1659 else 1660 { 1661 std::string tmp_value (enum_values[i].string_value); 1662 if ((len <= tmp_value.length()) 1663 && tmp_value.find (partial_value) == 0) 1664 matches.AppendString (enum_values[i].string_value); 1665 } 1666 ++i; 1667 } 1668 1669 word_complete = false; 1670 if (matches.GetSize() == 1) 1671 word_complete = true; 1672 1673 return matches.GetSize(); 1674 } 1675 1676 int 1677 UserSettingsController::CompleteSettingsNames (const UserSettingsControllerSP& usc_sp, 1678 Args &partial_setting_name_pieces, 1679 bool &word_complete, 1680 StringList &matches) 1681 { 1682 int num_matches = 0; 1683 int num_name_pieces = partial_setting_name_pieces.GetArgumentCount(); 1684 1685 if (num_name_pieces > 1) 1686 { 1687 // There are at least two pieces, perhaps with multiple level names preceding them. 1688 // First traverse all the extra levels, until we have exactly two pieces left. 1689 1690 int num_extra_levels = num_name_pieces - 2; 1691 1692 // Deal with current level first. 1693 1694 ConstString root_level = usc_sp->GetLevelName(); 1695 if ((num_extra_levels > 0) 1696 && (root_level.GetLength() > 0)) 1697 { 1698 ConstString current_level (partial_setting_name_pieces.GetArgumentAtIndex (0)); 1699 if (current_level == root_level) 1700 { 1701 partial_setting_name_pieces.Shift(); 1702 --num_extra_levels; 1703 } 1704 else 1705 return 0; // The current level did not match the name pieces; something is wrong, so return immediately 1706 1707 } 1708 1709 for (int i = 0; i < num_extra_levels; ++i) 1710 { 1711 ConstString child_level (partial_setting_name_pieces.GetArgumentAtIndex (0)); 1712 bool found = false; 1713 int num_children = usc_sp->GetNumChildren(); 1714 UserSettingsControllerSP child_usc_sp = usc_sp; 1715 1716 for (int j = 0; j < num_children && !found; ++j) 1717 { 1718 if (child_usc_sp->GetChildAtIndex (j)->GetLevelName() == child_level) 1719 { 1720 found = true; 1721 child_usc_sp = child_usc_sp->GetChildAtIndex (j); 1722 partial_setting_name_pieces.Shift(); 1723 } 1724 } 1725 if (! found) 1726 { 1727 return 0; // Unable to find a matching child level name; something is wrong, so return immediately. 1728 } 1729 } 1730 1731 // Now there should be exactly two name pieces left. If not there is an error, so return immediately 1732 1733 if (partial_setting_name_pieces.GetArgumentCount() != 2) 1734 return 0; 1735 1736 std::string next_name (partial_setting_name_pieces.GetArgumentAtIndex (0)); 1737 int len = next_name.length(); 1738 partial_setting_name_pieces.Shift(); 1739 1740 if ((next_name[0] == '[') && (next_name[len-1] == ']')) 1741 { 1742 // 'next_name' is an instance name. The last name piece must be a non-empty partial match against an 1743 // instance_name, assuming 'next_name' is valid. 1744 1745 if (usc_sp->IsLiveInstance (next_name)) 1746 { 1747 std::string complete_prefix; 1748 usc_sp->BuildParentPrefix (complete_prefix); 1749 1750 num_matches = usc_sp->InstanceVariableMatches(partial_setting_name_pieces.GetArgumentAtIndex(0), 1751 complete_prefix, 1752 next_name.c_str(), 1753 matches); 1754 word_complete = true; 1755 if (num_matches > 1) 1756 word_complete = false; 1757 1758 return num_matches; 1759 } 1760 else 1761 return 0; // Invalid instance_name 1762 } 1763 else 1764 { 1765 // 'next_name' must be a child name. Find the correct child and pass the remaining piece to be resolved. 1766 bool found = false; 1767 int num_children = usc_sp->GetNumChildren(); 1768 ConstString child_level (next_name.c_str()); 1769 for (int i = 0; i < num_children; ++i) 1770 { 1771 if (usc_sp->GetChildAtIndex (i)->GetLevelName() == child_level) 1772 { 1773 found = true; 1774 return UserSettingsController::CompleteSettingsNames (usc_sp->GetChildAtIndex (i), 1775 partial_setting_name_pieces, 1776 word_complete, matches); 1777 } 1778 } 1779 if (!found) 1780 return 0; 1781 } 1782 } 1783 else if (num_name_pieces == 1) 1784 { 1785 std::string complete_prefix; 1786 usc_sp->BuildParentPrefix (complete_prefix); 1787 1788 word_complete = true; 1789 std::string name (partial_setting_name_pieces.GetArgumentAtIndex (0)); 1790 1791 if (name[0] == '[') 1792 { 1793 // It's a partial instance name. 1794 1795 num_matches = usc_sp->LiveInstanceMatches (name.c_str(), complete_prefix, word_complete, matches); 1796 } 1797 else 1798 { 1799 // It could be anything *except* an instance name... 1800 1801 num_matches = usc_sp->GlobalVariableMatches (name.c_str(), complete_prefix, matches); 1802 num_matches += usc_sp->InstanceVariableMatches (name.c_str(), complete_prefix, NULL, matches); 1803 num_matches += usc_sp->ChildMatches (name.c_str(), complete_prefix, word_complete, matches); 1804 } 1805 1806 if (num_matches > 1) 1807 word_complete = false; 1808 1809 return num_matches; 1810 } 1811 else 1812 { 1813 // We have a user settings controller with a blank partial string. Return everything possible at this level. 1814 1815 std::string complete_prefix; 1816 usc_sp->BuildParentPrefix (complete_prefix); 1817 num_matches = usc_sp->GlobalVariableMatches (NULL, complete_prefix, matches); 1818 num_matches += usc_sp->InstanceVariableMatches (NULL, complete_prefix, NULL, matches); 1819 num_matches += usc_sp->LiveInstanceMatches (NULL, complete_prefix, word_complete, matches); 1820 num_matches += usc_sp->ChildMatches (NULL, complete_prefix, word_complete, matches); 1821 word_complete = false; 1822 return num_matches; 1823 } 1824 1825 return num_matches; 1826 } 1827 1828 int 1829 UserSettingsController::GlobalVariableMatches (const char *partial_name, 1830 const std::string &complete_prefix, 1831 StringList &matches) 1832 { 1833 int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0; 1834 int num_matches = 0; 1835 1836 for (size_t i = 0; i < m_settings.global_settings.size(); ++i) 1837 { 1838 const SettingEntry &entry = m_settings.global_settings[i]; 1839 std::string var_name (entry.var_name); 1840 if ((partial_len == 0) 1841 || ((partial_len <= var_name.length()) 1842 && (var_name.find (partial_name) == 0))) 1843 { 1844 StreamString match_name; 1845 if (complete_prefix.length() > 0) 1846 { 1847 match_name.Printf ("%s.%s", complete_prefix.c_str(), var_name.c_str()); 1848 matches.AppendString (match_name.GetData()); 1849 } 1850 else 1851 matches.AppendString (var_name.c_str()); 1852 ++num_matches; 1853 } 1854 } 1855 return num_matches; 1856 } 1857 1858 int 1859 UserSettingsController::InstanceVariableMatches (const char *partial_name, 1860 const std::string &complete_prefix, 1861 const char *instance_name, 1862 StringList &matches) 1863 { 1864 int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0; 1865 int num_matches = 0; 1866 1867 for (size_t i = 0; i < m_settings.instance_settings.size(); ++i) 1868 { 1869 SettingEntry &entry = m_settings.instance_settings[i]; 1870 std::string var_name (entry.var_name); 1871 if ((partial_len == 0) 1872 || ((partial_len <= var_name.length()) 1873 && (var_name.find (partial_name) == 0))) 1874 { 1875 StreamString match_name; 1876 if (complete_prefix.length() > 0) 1877 { 1878 if (instance_name != NULL) 1879 match_name.Printf ("%s.%s.%s", complete_prefix.c_str(), instance_name, var_name.c_str()); 1880 else 1881 match_name.Printf ("%s.%s", complete_prefix.c_str(), var_name.c_str()); 1882 1883 matches.AppendString (match_name.GetData()); 1884 } 1885 else 1886 { 1887 if (instance_name != NULL) 1888 { 1889 match_name.Printf ("%s.%s", instance_name, var_name.c_str()); 1890 matches.AppendString (match_name.GetData()); 1891 } 1892 else 1893 matches.AppendString (var_name.c_str()); 1894 } 1895 ++num_matches; 1896 } 1897 } 1898 return num_matches; 1899 } 1900 1901 int 1902 UserSettingsController::LiveInstanceMatches (const char *partial_name, 1903 const std::string &complete_prefix, 1904 bool &word_complete, 1905 StringList &matches) 1906 { 1907 int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0; 1908 int num_matches = 0; 1909 1910 InstanceSettingsMap::iterator pos; 1911 Mutex::Locker locker (m_live_settings_mutex); 1912 for (pos = m_live_settings.begin(); pos != m_live_settings.end(); ++pos) 1913 { 1914 std::string instance_name = pos->first; 1915 if ((partial_len == 0) 1916 || ((partial_len <= instance_name.length()) 1917 && (instance_name.find (partial_name) == 0))) 1918 { 1919 StreamString match_name; 1920 if (complete_prefix.length() > 0) 1921 match_name.Printf ("%s.%s.", complete_prefix.c_str(), instance_name.c_str()); 1922 else 1923 match_name.Printf ("%s.", instance_name.c_str()); 1924 matches.AppendString (match_name.GetData()); 1925 ++num_matches; 1926 } 1927 } 1928 1929 if (num_matches > 0) 1930 word_complete = false; 1931 1932 return num_matches; 1933 } 1934 1935 int 1936 UserSettingsController::ChildMatches (const char *partial_name, 1937 const std::string &complete_prefix, 1938 bool &word_complete, 1939 StringList &matches) 1940 { 1941 int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0; 1942 int num_children = GetNumChildren(); 1943 int num_matches = 0; 1944 for (int i = 0; i < num_children; ++i) 1945 { 1946 std::string child_name (GetChildAtIndex(i)->GetLevelName().GetCString()); 1947 StreamString match_name; 1948 if ((partial_len == 0) 1949 || ((partial_len <= child_name.length()) 1950 && (child_name.find (partial_name) == 0))) 1951 { 1952 if (complete_prefix.length() > 0) 1953 match_name.Printf ("%s.%s.", complete_prefix.c_str(), child_name.c_str()); 1954 else 1955 match_name.Printf ("%s.", child_name.c_str()); 1956 matches.AppendString (match_name.GetData()); 1957 ++num_matches; 1958 } 1959 } 1960 1961 if (num_matches > 0) 1962 word_complete = false; 1963 1964 return num_matches; 1965 } 1966 1967 void 1968 UserSettingsController::VerifyOperationForType (SettableVariableType var_type, 1969 VarSetOperationType op, 1970 const ConstString &var_name, 1971 Error &err) 1972 { 1973 if (op == eVarSetOperationAssign) 1974 return; 1975 1976 1977 if (op == eVarSetOperationInvalid) 1978 { 1979 err.SetErrorString ("invalid 'settings' subcommand operation"); 1980 return; 1981 } 1982 1983 switch (op) 1984 { 1985 case eVarSetOperationInsertBefore: 1986 case eVarSetOperationInsertAfter: 1987 if (var_type != eSetVarTypeArray) 1988 err.SetErrorString ("invalid operation: this operation can only be performed on array variables"); 1989 break; 1990 case eVarSetOperationReplace: 1991 case eVarSetOperationRemove: 1992 if ((var_type != eSetVarTypeArray) 1993 && (var_type != eSetVarTypeDictionary)) 1994 err.SetErrorString ("invalid operation: this operation can only be performed on array or dictionary variables"); 1995 break; 1996 case eVarSetOperationAppend: 1997 case eVarSetOperationClear: 1998 if ((var_type != eSetVarTypeArray) 1999 && (var_type != eSetVarTypeDictionary) 2000 && (var_type != eSetVarTypeString)) 2001 err.SetErrorString ("invalid operation: this operation can only be performed on array, dictionary or string variables"); 2002 break; 2003 default: 2004 break; 2005 } 2006 2007 return; 2008 } 2009 2010 void 2011 UserSettingsController::UpdateStringVariable (VarSetOperationType op, 2012 std::string &string_var, 2013 const char *new_value, 2014 Error &err) 2015 { 2016 if (op == eVarSetOperationAssign) 2017 { 2018 if (new_value && new_value[0]) 2019 string_var.assign (new_value); 2020 else 2021 string_var.clear(); 2022 } 2023 else if (op == eVarSetOperationAppend) 2024 { 2025 if (new_value && new_value[0]) 2026 string_var.append (new_value); 2027 } 2028 else if (op == eVarSetOperationClear) 2029 string_var.clear(); 2030 else 2031 err.SetErrorString ("unrecognized operation. Cannot update value"); 2032 } 2033 2034 Error 2035 UserSettingsController::UpdateStringOptionValue (const char *value, 2036 VarSetOperationType op, 2037 OptionValueString &option_value) 2038 { 2039 Error error; 2040 if (op == eVarSetOperationAssign) 2041 { 2042 option_value.SetCurrentValue (value); 2043 } 2044 else if (op == eVarSetOperationAppend) 2045 { 2046 option_value.AppendToCurrentValue (value); 2047 } 2048 else if (op == eVarSetOperationClear) 2049 { 2050 option_value.Clear(); 2051 } 2052 else 2053 { 2054 error.SetErrorString ("unrecognized operation, cannot update value"); 2055 } 2056 return error; 2057 } 2058 2059 Error 2060 UserSettingsController::UpdateFileSpecOptionValue (const char *value, 2061 VarSetOperationType op, 2062 OptionValueFileSpec &option_value) 2063 { 2064 Error error; 2065 if (op == eVarSetOperationAssign) 2066 { 2067 option_value.GetCurrentValue().SetFile (value, false); 2068 } 2069 else if (op == eVarSetOperationAppend) 2070 { 2071 char path[PATH_MAX]; 2072 if (option_value.GetCurrentValue().GetPath (path, sizeof(path))) 2073 { 2074 int path_len = ::strlen (path); 2075 int value_len = ::strlen (value); 2076 if (value_len + 1 > sizeof(path) - path_len) 2077 { 2078 error.SetErrorString("path too long."); 2079 } 2080 else 2081 { 2082 ::strncat (path, value, sizeof(path) - path_len - 1); 2083 option_value.GetCurrentValue().SetFile (path, false); 2084 } 2085 } 2086 else 2087 { 2088 error.SetErrorString("path too long."); 2089 } 2090 } 2091 else if (op == eVarSetOperationClear) 2092 { 2093 option_value.Clear(); 2094 } 2095 else 2096 { 2097 error.SetErrorString ("operation not supported for FileSpec option value type."); 2098 } 2099 return error; 2100 } 2101 2102 2103 void 2104 UserSettingsController::UpdateBooleanVariable (VarSetOperationType op, 2105 bool &bool_value, 2106 const char *value_cstr, 2107 bool clear_value, 2108 Error &err) 2109 { 2110 switch (op) 2111 { 2112 case eVarSetOperationReplace: 2113 case eVarSetOperationInsertBefore: 2114 case eVarSetOperationInsertAfter: 2115 case eVarSetOperationRemove: 2116 case eVarSetOperationAppend: 2117 case eVarSetOperationInvalid: 2118 default: 2119 err.SetErrorString ("invalid operation for Boolean variable, cannot update value"); 2120 break; 2121 2122 case eVarSetOperationClear: 2123 err.Clear(); 2124 bool_value = clear_value; 2125 break; 2126 2127 case eVarSetOperationAssign: 2128 { 2129 bool success = false; 2130 2131 2132 if (value_cstr == NULL) 2133 err.SetErrorStringWithFormat ("invalid boolean string value (NULL)"); 2134 else if (value_cstr[0] == '\0') 2135 err.SetErrorStringWithFormat ("invalid boolean string value (empty)"); 2136 else 2137 { 2138 bool new_value = Args::StringToBoolean (value_cstr, false, &success); 2139 if (success) 2140 { 2141 err.Clear(); 2142 bool_value = new_value; 2143 } 2144 else 2145 err.SetErrorStringWithFormat ("invalid boolean string value: '%s'", value_cstr); 2146 } 2147 } 2148 break; 2149 } 2150 } 2151 Error 2152 UserSettingsController::UpdateBooleanOptionValue (const char *value, 2153 VarSetOperationType op, 2154 OptionValueBoolean &option_value) 2155 { 2156 Error error; 2157 switch (op) 2158 { 2159 case eVarSetOperationReplace: 2160 case eVarSetOperationInsertBefore: 2161 case eVarSetOperationInsertAfter: 2162 case eVarSetOperationRemove: 2163 case eVarSetOperationAppend: 2164 case eVarSetOperationInvalid: 2165 default: 2166 error.SetErrorString ("Invalid operation for Boolean variable. Cannot update value.\n"); 2167 break; 2168 2169 case eVarSetOperationClear: 2170 option_value.Clear(); 2171 break; 2172 2173 case eVarSetOperationAssign: 2174 { 2175 bool success = false; 2176 error = option_value.SetValueFromCString(value); 2177 2178 if (value == NULL) 2179 error.SetErrorStringWithFormat ("invalid boolean string value (NULL)\n"); 2180 else if (value[0] == '\0') 2181 error.SetErrorStringWithFormat ("invalid boolean string value (empty)\n"); 2182 else 2183 { 2184 bool new_value = Args::StringToBoolean (value, false, &success); 2185 if (success) 2186 { 2187 error.Clear(); 2188 option_value = new_value; 2189 } 2190 else 2191 error.SetErrorStringWithFormat ("invalid boolean string value: '%s'\n", value); 2192 } 2193 } 2194 break; 2195 } 2196 return error; 2197 } 2198 2199 void 2200 UserSettingsController::UpdateStringArrayVariable (VarSetOperationType op, 2201 const char *index_value, 2202 Args &array_var, 2203 const char *new_value, 2204 Error &err) 2205 { 2206 int index = -1; 2207 bool valid_index = true; 2208 2209 if (index_value != NULL) 2210 { 2211 for (int i = 0; i < strlen(index_value); ++i) 2212 if (!isdigit (index_value[i])) 2213 { 2214 valid_index = false; 2215 err.SetErrorStringWithFormat ("'%s' is not a valid integer index, cannot update array value", 2216 index_value); 2217 } 2218 2219 if (valid_index) 2220 index = atoi (index_value); 2221 2222 if (index < 0 2223 || index >= array_var.GetArgumentCount()) 2224 { 2225 valid_index = false; 2226 err.SetErrorStringWithFormat ("%d is outside the bounds of the specified array variable, " 2227 "cannot update array value", index); 2228 } 2229 } 2230 2231 switch (op) 2232 { 2233 case eVarSetOperationAssign: 2234 array_var.SetCommandString (new_value); 2235 break; 2236 case eVarSetOperationReplace: 2237 { 2238 if (valid_index) 2239 array_var.ReplaceArgumentAtIndex (index, new_value); 2240 break; 2241 } 2242 case eVarSetOperationInsertBefore: 2243 case eVarSetOperationInsertAfter: 2244 { 2245 if (valid_index) 2246 { 2247 Args new_array (new_value); 2248 if (op == eVarSetOperationInsertAfter) 2249 ++index; 2250 for (int i = 0; i < new_array.GetArgumentCount(); ++i) 2251 array_var.InsertArgumentAtIndex (index, new_array.GetArgumentAtIndex (i)); 2252 } 2253 break; 2254 } 2255 case eVarSetOperationRemove: 2256 { 2257 if (valid_index) 2258 array_var.DeleteArgumentAtIndex (index); 2259 break; 2260 } 2261 case eVarSetOperationAppend: 2262 { 2263 Args new_array (new_value); 2264 array_var.AppendArguments (new_array); 2265 break; 2266 } 2267 case eVarSetOperationClear: 2268 array_var.Clear(); 2269 break; 2270 default: 2271 err.SetErrorString ("unrecognized operation, cannot update value"); 2272 break; 2273 } 2274 } 2275 2276 void 2277 UserSettingsController::UpdateDictionaryVariable (VarSetOperationType op, 2278 const char *index_value, 2279 std::map<std::string, std::string> &dictionary, 2280 const char *new_value, 2281 Error &err) 2282 { 2283 switch (op) 2284 { 2285 case eVarSetOperationReplace: 2286 if (index_value != NULL) 2287 { 2288 std::string key (index_value); 2289 std::map<std::string, std::string>::iterator pos; 2290 2291 pos = dictionary.find (key); 2292 if (pos != dictionary.end()) 2293 dictionary[key] = new_value; 2294 else 2295 err.SetErrorStringWithFormat ("'%s' is not an existing key; cannot replace value", index_value); 2296 } 2297 else 2298 err.SetErrorString ("'settings replace' requires a key for dictionary variables, no key supplied"); 2299 break; 2300 case eVarSetOperationRemove: 2301 if (index_value != NULL) 2302 { 2303 std::string key (index_value); 2304 dictionary.erase (key); 2305 } 2306 else 2307 err.SetErrorString ("'settings remove' requires a key for dictionary variables, no key supplied"); 2308 break; 2309 case eVarSetOperationClear: 2310 dictionary.clear (); 2311 break; 2312 case eVarSetOperationAppend: 2313 case eVarSetOperationAssign: 2314 { 2315 // Clear the dictionary if it's an assign with new_value as NULL. 2316 if (new_value == NULL && op == eVarSetOperationAssign) 2317 { 2318 dictionary.clear (); 2319 break; 2320 } 2321 Args args (new_value); 2322 size_t num_args = args.GetArgumentCount(); 2323 RegularExpression regex("(\\[\"?)?" // Regex match 1 (optional key prefix of '["' pr '[') 2324 "([A-Za-z_][A-Za-z_0-9]*)" // Regex match 2 (key string) 2325 "(\"?\\])?" // Regex match 3 (optional key suffix of '"]' pr ']') 2326 "=" // The equal sign that is required 2327 "(.*)"); // Regex match 4 (value string) 2328 std::string key, value; 2329 2330 for (size_t i = 0; i < num_args; ++i) 2331 { 2332 const char *key_equal_value_arg = args.GetArgumentAtIndex (i); 2333 // Execute the regular expression on each arg. 2334 if (regex.Execute(key_equal_value_arg, 5)) 2335 { 2336 // The regular expression succeeded. The match at index 2337 // zero will be the entire string that matched the entire 2338 // regular expression. The match at index 1 - 4 will be 2339 // as mentioned above by the creation of the regex pattern. 2340 // Match index 2 is the key, match index 4 is the value. 2341 regex.GetMatchAtIndex (key_equal_value_arg, 2, key); 2342 regex.GetMatchAtIndex (key_equal_value_arg, 4, value); 2343 dictionary[key] = value; 2344 } 2345 else 2346 { 2347 err.SetErrorString ("invalid format for dictionary value, expected one of '[\"<key>\"]=<value>', '[<key>]=<value>', or '<key>=<value>'"); 2348 } 2349 } 2350 } 2351 break; 2352 case eVarSetOperationInsertBefore: 2353 case eVarSetOperationInsertAfter: 2354 err.SetErrorString ("specified operation cannot be performed on dictionary variables"); 2355 break; 2356 default: 2357 err.SetErrorString ("unrecognized operation"); 2358 break; 2359 } 2360 } 2361 2362 const char * 2363 UserSettingsController::EnumToString (const OptionEnumValueElement *enum_values, 2364 int value) 2365 { 2366 int i = 0; 2367 while (enum_values[i].string_value != NULL) 2368 { 2369 if (enum_values[i].value == value) 2370 return enum_values[i].string_value; 2371 ++i; 2372 } 2373 2374 return ""; 2375 } 2376 2377 2378 void 2379 UserSettingsController::UpdateEnumVariable (OptionEnumValueElement *enum_values, 2380 int *enum_var, 2381 const char *new_value, 2382 Error &error) 2383 { 2384 *enum_var = Args::StringToOptionEnum (new_value, enum_values, enum_values[0].value, error); 2385 } 2386 2387 void 2388 UserSettingsController::RenameInstanceSettings (const char *old_name, const char *new_name) 2389 { 2390 Mutex::Locker live_mutex (m_live_settings_mutex); 2391 Mutex::Locker pending_mutex (m_pending_settings_mutex); 2392 std::string old_name_key (old_name); 2393 std::string new_name_key (new_name); 2394 2395 // First, find the live instance settings for the old_name. If they don't exist in the live settings 2396 // list, then this is not a setting that can be renamed. 2397 2398 if ((old_name_key[0] != '[') || (old_name_key[old_name_key.size() -1] != ']')) 2399 { 2400 StreamString tmp_str; 2401 tmp_str.Printf ("[%s]", old_name); 2402 old_name_key = tmp_str.GetData(); 2403 } 2404 2405 if ((new_name_key[0] != '[') || (new_name_key[new_name_key.size() -1] != ']')) 2406 { 2407 StreamString tmp_str; 2408 tmp_str.Printf ("[%s]", new_name); 2409 new_name_key = tmp_str.GetData(); 2410 } 2411 2412 if (old_name_key.compare (new_name_key) == 0) 2413 return; 2414 2415 size_t len = new_name_key.length(); 2416 std::string stripped_new_name = new_name_key.substr (1, len-2); // new name without the '[ ]' 2417 2418 InstanceSettingsMap::iterator pos; 2419 2420 pos = m_live_settings.find (old_name_key); 2421 if (pos != m_live_settings.end()) 2422 { 2423 InstanceSettings *live_settings = pos->second; 2424 2425 // Rename the settings. 2426 live_settings->ChangeInstanceName (stripped_new_name); 2427 2428 // Now see if there are any pending settings for the new name; if so, copy them into live_settings. 2429 std::map<std::string, InstanceSettingsSP>::iterator pending_pos; 2430 pending_pos = m_pending_settings.find (new_name_key); 2431 if (pending_pos != m_pending_settings.end()) 2432 { 2433 InstanceSettingsSP pending_settings_sp = pending_pos->second; 2434 live_settings->CopyInstanceSettings (pending_settings_sp, false); 2435 } 2436 2437 // Erase the old entry (under the old name) from live settings. 2438 m_live_settings.erase (pos); 2439 2440 // Add the new entry, with the new name, into live settings. 2441 m_live_settings[new_name_key] = live_settings; 2442 } 2443 } 2444 2445 //---------------------------------------------------------------------- 2446 // class InstanceSettings 2447 //---------------------------------------------------------------------- 2448 2449 InstanceSettings::InstanceSettings (UserSettingsController &owner, const char *instance_name, bool live_instance) : 2450 m_owner (owner), 2451 m_instance_name (instance_name) 2452 { 2453 if ((m_instance_name != InstanceSettings::GetDefaultName()) 2454 && (m_instance_name != InstanceSettings::InvalidName()) 2455 && live_instance) 2456 m_owner.RegisterInstanceSettings (this); 2457 } 2458 2459 InstanceSettings::~InstanceSettings () 2460 { 2461 if (m_instance_name != InstanceSettings::GetDefaultName()) 2462 m_owner.UnregisterInstanceSettings (this); 2463 } 2464 2465 const ConstString & 2466 InstanceSettings::GetDefaultName () 2467 { 2468 static const ConstString g_default_settings_name ("[DEFAULT]"); 2469 2470 return g_default_settings_name; 2471 } 2472 2473 const ConstString & 2474 InstanceSettings::InvalidName () 2475 { 2476 static const ConstString g_invalid_name ("Invalid instance name"); 2477 2478 return g_invalid_name; 2479 } 2480 2481 void 2482 InstanceSettings::ChangeInstanceName (const std::string &new_instance_name) 2483 { 2484 m_instance_name.SetCString (new_instance_name.c_str()); 2485 } 2486 2487 2488