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