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