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 for (int i = 0; i < num_extra_levels; ++i) 1718 { 1719 ConstString child_level (partial_setting_name_pieces.GetArgumentAtIndex (0)); 1720 bool found = false; 1721 int num_children = usc_sp->GetNumChildren(); 1722 UserSettingsControllerSP child_usc_sp = usc_sp; 1723 1724 for (int j = 0; j < num_children && !found; ++j) 1725 { 1726 if (child_usc_sp->GetChildAtIndex (j)->GetLevelName() == child_level) 1727 { 1728 found = true; 1729 child_usc_sp = child_usc_sp->GetChildAtIndex (j); 1730 partial_setting_name_pieces.Shift(); 1731 } 1732 } 1733 if (! found) 1734 { 1735 return 0; // Unable to find a matching child level name; something is wrong, so return immediately. 1736 } 1737 } 1738 1739 // Now there should be exactly two name pieces left. If not there is an error, so return immediately 1740 1741 if (partial_setting_name_pieces.GetArgumentCount() != 2) 1742 return 0; 1743 1744 std::string next_name (partial_setting_name_pieces.GetArgumentAtIndex (0)); 1745 int len = next_name.length(); 1746 partial_setting_name_pieces.Shift(); 1747 1748 if ((next_name[0] == '[') && (next_name[len-1] == ']')) 1749 { 1750 // 'next_name' is an instance name. The last name piece must be a non-empty partial match against an 1751 // instance_name, assuming 'next_name' is valid. 1752 1753 if (usc_sp->IsLiveInstance (next_name)) 1754 { 1755 std::string complete_prefix; 1756 usc_sp->BuildParentPrefix (complete_prefix); 1757 1758 num_matches = usc_sp->InstanceVariableMatches(partial_setting_name_pieces.GetArgumentAtIndex(0), 1759 complete_prefix, 1760 next_name.c_str(), 1761 matches); 1762 word_complete = true; 1763 if (num_matches > 1) 1764 word_complete = false; 1765 1766 return num_matches; 1767 } 1768 else 1769 return 0; // Invalid instance_name 1770 } 1771 else 1772 { 1773 // 'next_name' must be a child name. Find the correct child and pass the remaining piece to be resolved. 1774 bool found = false; 1775 int num_children = usc_sp->GetNumChildren(); 1776 ConstString child_level (next_name.c_str()); 1777 for (int i = 0; i < num_children; ++i) 1778 { 1779 if (usc_sp->GetChildAtIndex (i)->GetLevelName() == child_level) 1780 { 1781 found = true; 1782 return UserSettingsController::CompleteSettingsNames (usc_sp->GetChildAtIndex (i), 1783 partial_setting_name_pieces, 1784 word_complete, matches); 1785 } 1786 } 1787 if (!found) 1788 return 0; 1789 } 1790 } 1791 else if (num_name_pieces == 1) 1792 { 1793 std::string complete_prefix; 1794 usc_sp->BuildParentPrefix (complete_prefix); 1795 1796 word_complete = true; 1797 std::string name (partial_setting_name_pieces.GetArgumentAtIndex (0)); 1798 1799 if (name[0] == '[') 1800 { 1801 // It's a partial instance name. 1802 1803 num_matches = usc_sp->LiveInstanceMatches (name.c_str(), complete_prefix, word_complete, matches); 1804 } 1805 else 1806 { 1807 // It could be anything *except* an instance name... 1808 1809 num_matches = usc_sp->GlobalVariableMatches (name.c_str(), complete_prefix, matches); 1810 num_matches += usc_sp->InstanceVariableMatches (name.c_str(), complete_prefix, NULL, matches); 1811 num_matches += usc_sp->ChildMatches (name.c_str(), complete_prefix, word_complete, matches); 1812 } 1813 1814 if (num_matches > 1) 1815 word_complete = false; 1816 1817 return num_matches; 1818 } 1819 else 1820 { 1821 // We have a user settings controller with a blank partial string. Return everything possible at this level. 1822 1823 std::string complete_prefix; 1824 usc_sp->BuildParentPrefix (complete_prefix); 1825 num_matches = usc_sp->GlobalVariableMatches (NULL, complete_prefix, matches); 1826 num_matches += usc_sp->InstanceVariableMatches (NULL, complete_prefix, NULL, matches); 1827 num_matches += usc_sp->LiveInstanceMatches (NULL, complete_prefix, word_complete, matches); 1828 num_matches += usc_sp->ChildMatches (NULL, complete_prefix, word_complete, matches); 1829 word_complete = false; 1830 return num_matches; 1831 } 1832 1833 return num_matches; 1834 } 1835 1836 int 1837 UserSettingsController::GlobalVariableMatches (const char *partial_name, 1838 const std::string &complete_prefix, 1839 StringList &matches) 1840 { 1841 int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0; 1842 int num_matches = 0; 1843 1844 for (size_t i = 0; i < m_settings.global_settings.size(); ++i) 1845 { 1846 const SettingEntry &entry = m_settings.global_settings[i]; 1847 std::string var_name (entry.var_name); 1848 if ((partial_len == 0) 1849 || ((partial_len <= var_name.length()) 1850 && (var_name.find (partial_name) == 0))) 1851 { 1852 StreamString match_name; 1853 if (complete_prefix.length() > 0) 1854 { 1855 match_name.Printf ("%s.%s", complete_prefix.c_str(), var_name.c_str()); 1856 matches.AppendString (match_name.GetData()); 1857 } 1858 else 1859 matches.AppendString (var_name.c_str()); 1860 ++num_matches; 1861 } 1862 } 1863 return num_matches; 1864 } 1865 1866 int 1867 UserSettingsController::InstanceVariableMatches (const char *partial_name, 1868 const std::string &complete_prefix, 1869 const char *instance_name, 1870 StringList &matches) 1871 { 1872 int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0; 1873 int num_matches = 0; 1874 1875 for (size_t i = 0; i < m_settings.instance_settings.size(); ++i) 1876 { 1877 SettingEntry &entry = m_settings.instance_settings[i]; 1878 std::string var_name (entry.var_name); 1879 if ((partial_len == 0) 1880 || ((partial_len <= var_name.length()) 1881 && (var_name.find (partial_name) == 0))) 1882 { 1883 StreamString match_name; 1884 if (complete_prefix.length() > 0) 1885 { 1886 if (instance_name != NULL) 1887 match_name.Printf ("%s.%s.%s", complete_prefix.c_str(), instance_name, var_name.c_str()); 1888 else 1889 match_name.Printf ("%s.%s", complete_prefix.c_str(), var_name.c_str()); 1890 1891 matches.AppendString (match_name.GetData()); 1892 } 1893 else 1894 { 1895 if (instance_name != NULL) 1896 { 1897 match_name.Printf ("%s.%s", instance_name, var_name.c_str()); 1898 matches.AppendString (match_name.GetData()); 1899 } 1900 else 1901 matches.AppendString (var_name.c_str()); 1902 } 1903 ++num_matches; 1904 } 1905 } 1906 return num_matches; 1907 } 1908 1909 int 1910 UserSettingsController::LiveInstanceMatches (const char *partial_name, 1911 const std::string &complete_prefix, 1912 bool &word_complete, 1913 StringList &matches) 1914 { 1915 int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0; 1916 int num_matches = 0; 1917 1918 InstanceSettingsMap::iterator pos; 1919 Mutex::Locker locker (m_live_settings_mutex); 1920 for (pos = m_live_settings.begin(); pos != m_live_settings.end(); ++pos) 1921 { 1922 std::string instance_name = pos->first; 1923 if ((partial_len == 0) 1924 || ((partial_len <= instance_name.length()) 1925 && (instance_name.find (partial_name) == 0))) 1926 { 1927 StreamString match_name; 1928 if (complete_prefix.length() > 0) 1929 match_name.Printf ("%s.%s.", complete_prefix.c_str(), instance_name.c_str()); 1930 else 1931 match_name.Printf ("%s.", instance_name.c_str()); 1932 matches.AppendString (match_name.GetData()); 1933 ++num_matches; 1934 } 1935 } 1936 1937 if (num_matches > 0) 1938 word_complete = false; 1939 1940 return num_matches; 1941 } 1942 1943 int 1944 UserSettingsController::ChildMatches (const char *partial_name, 1945 const std::string &complete_prefix, 1946 bool &word_complete, 1947 StringList &matches) 1948 { 1949 int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0; 1950 int num_children = GetNumChildren(); 1951 int num_matches = 0; 1952 for (int i = 0; i < num_children; ++i) 1953 { 1954 std::string child_name (GetChildAtIndex(i)->GetLevelName().GetCString()); 1955 StreamString match_name; 1956 if ((partial_len == 0) 1957 || ((partial_len <= child_name.length()) 1958 && (child_name.find (partial_name) == 0))) 1959 { 1960 if (complete_prefix.length() > 0) 1961 match_name.Printf ("%s.%s.", complete_prefix.c_str(), child_name.c_str()); 1962 else 1963 match_name.Printf ("%s.", child_name.c_str()); 1964 matches.AppendString (match_name.GetData()); 1965 ++num_matches; 1966 } 1967 } 1968 1969 if (num_matches > 0) 1970 word_complete = false; 1971 1972 return num_matches; 1973 } 1974 1975 void 1976 UserSettingsController::VerifyOperationForType (SettableVariableType var_type, 1977 VarSetOperationType op, 1978 const ConstString &var_name, 1979 Error &err) 1980 { 1981 if (op == eVarSetOperationAssign) 1982 return; 1983 1984 1985 if (op == eVarSetOperationInvalid) 1986 { 1987 err.SetErrorString ("invalid 'settings' subcommand operation"); 1988 return; 1989 } 1990 1991 switch (op) 1992 { 1993 case eVarSetOperationInsertBefore: 1994 case eVarSetOperationInsertAfter: 1995 if (var_type != eSetVarTypeArray) 1996 err.SetErrorString ("invalid operation: this operation can only be performed on array variables"); 1997 break; 1998 case eVarSetOperationReplace: 1999 case eVarSetOperationRemove: 2000 if ((var_type != eSetVarTypeArray) 2001 && (var_type != eSetVarTypeDictionary)) 2002 err.SetErrorString ("invalid operation: this operation can only be performed on array or dictionary variables"); 2003 break; 2004 case eVarSetOperationAppend: 2005 case eVarSetOperationClear: 2006 if ((var_type != eSetVarTypeArray) 2007 && (var_type != eSetVarTypeDictionary) 2008 && (var_type != eSetVarTypeString)) 2009 err.SetErrorString ("invalid operation: this operation can only be performed on array, dictionary or string variables"); 2010 break; 2011 default: 2012 break; 2013 } 2014 2015 return; 2016 } 2017 2018 void 2019 UserSettingsController::UpdateStringVariable (VarSetOperationType op, 2020 std::string &string_var, 2021 const char *new_value, 2022 Error &err) 2023 { 2024 if (op == eVarSetOperationAssign) 2025 { 2026 if (new_value && new_value[0]) 2027 string_var.assign (new_value); 2028 else 2029 string_var.clear(); 2030 } 2031 else if (op == eVarSetOperationAppend) 2032 { 2033 if (new_value && new_value[0]) 2034 string_var.append (new_value); 2035 } 2036 else if (op == eVarSetOperationClear) 2037 string_var.clear(); 2038 else 2039 err.SetErrorString ("unrecognized operation. Cannot update value"); 2040 } 2041 2042 Error 2043 UserSettingsController::UpdateStringOptionValue (const char *value, 2044 VarSetOperationType op, 2045 OptionValueString &option_value) 2046 { 2047 Error error; 2048 if (op == eVarSetOperationAssign) 2049 { 2050 option_value.SetCurrentValue (value); 2051 } 2052 else if (op == eVarSetOperationAppend) 2053 { 2054 option_value.AppendToCurrentValue (value); 2055 } 2056 else if (op == eVarSetOperationClear) 2057 { 2058 option_value.Clear(); 2059 } 2060 else 2061 { 2062 error.SetErrorString ("unrecognized operation, cannot update value"); 2063 } 2064 return error; 2065 } 2066 2067 Error 2068 UserSettingsController::UpdateFileSpecOptionValue (const char *value, 2069 VarSetOperationType op, 2070 OptionValueFileSpec &option_value) 2071 { 2072 Error error; 2073 if (op == eVarSetOperationAssign) 2074 { 2075 option_value.GetCurrentValue().SetFile (value, false); 2076 } 2077 else if (op == eVarSetOperationAppend) 2078 { 2079 char path[PATH_MAX]; 2080 if (option_value.GetCurrentValue().GetPath (path, sizeof(path))) 2081 { 2082 int path_len = ::strlen (path); 2083 int value_len = ::strlen (value); 2084 if (value_len + 1 > sizeof(path) - path_len) 2085 { 2086 error.SetErrorString("path too long."); 2087 } 2088 else 2089 { 2090 ::strncat (path, value, sizeof(path) - path_len - 1); 2091 option_value.GetCurrentValue().SetFile (path, false); 2092 } 2093 } 2094 else 2095 { 2096 error.SetErrorString("path too long."); 2097 } 2098 } 2099 else if (op == eVarSetOperationClear) 2100 { 2101 option_value.Clear(); 2102 } 2103 else 2104 { 2105 error.SetErrorString ("operation not supported for FileSpec option value type."); 2106 } 2107 return error; 2108 } 2109 2110 2111 void 2112 UserSettingsController::UpdateBooleanVariable (VarSetOperationType op, 2113 bool &bool_value, 2114 const char *value_cstr, 2115 bool clear_value, 2116 Error &err) 2117 { 2118 switch (op) 2119 { 2120 case eVarSetOperationReplace: 2121 case eVarSetOperationInsertBefore: 2122 case eVarSetOperationInsertAfter: 2123 case eVarSetOperationRemove: 2124 case eVarSetOperationAppend: 2125 case eVarSetOperationInvalid: 2126 default: 2127 err.SetErrorString ("invalid operation for Boolean variable, cannot update value"); 2128 break; 2129 2130 case eVarSetOperationClear: 2131 err.Clear(); 2132 bool_value = clear_value; 2133 break; 2134 2135 case eVarSetOperationAssign: 2136 { 2137 bool success = false; 2138 2139 2140 if (value_cstr == NULL) 2141 err.SetErrorStringWithFormat ("invalid boolean string value (NULL)"); 2142 else if (value_cstr[0] == '\0') 2143 err.SetErrorStringWithFormat ("invalid boolean string value (empty)"); 2144 else 2145 { 2146 bool new_value = Args::StringToBoolean (value_cstr, false, &success); 2147 if (success) 2148 { 2149 err.Clear(); 2150 bool_value = new_value; 2151 } 2152 else 2153 err.SetErrorStringWithFormat ("invalid boolean string value: '%s'", value_cstr); 2154 } 2155 } 2156 break; 2157 } 2158 } 2159 Error 2160 UserSettingsController::UpdateBooleanOptionValue (const char *value, 2161 VarSetOperationType op, 2162 OptionValueBoolean &option_value) 2163 { 2164 Error error; 2165 switch (op) 2166 { 2167 case eVarSetOperationReplace: 2168 case eVarSetOperationInsertBefore: 2169 case eVarSetOperationInsertAfter: 2170 case eVarSetOperationRemove: 2171 case eVarSetOperationAppend: 2172 case eVarSetOperationInvalid: 2173 default: 2174 error.SetErrorString ("Invalid operation for Boolean variable. Cannot update value.\n"); 2175 break; 2176 2177 case eVarSetOperationClear: 2178 option_value.Clear(); 2179 break; 2180 2181 case eVarSetOperationAssign: 2182 { 2183 bool success = false; 2184 error = option_value.SetValueFromCString(value); 2185 2186 if (value == NULL) 2187 error.SetErrorStringWithFormat ("invalid boolean string value (NULL)\n"); 2188 else if (value[0] == '\0') 2189 error.SetErrorStringWithFormat ("invalid boolean string value (empty)\n"); 2190 else 2191 { 2192 bool new_value = Args::StringToBoolean (value, false, &success); 2193 if (success) 2194 { 2195 error.Clear(); 2196 option_value = new_value; 2197 } 2198 else 2199 error.SetErrorStringWithFormat ("invalid boolean string value: '%s'\n", value); 2200 } 2201 } 2202 break; 2203 } 2204 return error; 2205 } 2206 2207 void 2208 UserSettingsController::UpdateStringArrayVariable (VarSetOperationType op, 2209 const char *index_value, 2210 Args &array_var, 2211 const char *new_value, 2212 Error &err) 2213 { 2214 int index = -1; 2215 bool valid_index = true; 2216 2217 if (index_value != NULL) 2218 { 2219 for (int i = 0; i < strlen(index_value); ++i) 2220 if (!isdigit (index_value[i])) 2221 { 2222 valid_index = false; 2223 err.SetErrorStringWithFormat ("'%s' is not a valid integer index, cannot update array value", 2224 index_value); 2225 } 2226 2227 if (valid_index) 2228 index = atoi (index_value); 2229 2230 if (index < 0 2231 || index >= array_var.GetArgumentCount()) 2232 { 2233 valid_index = false; 2234 err.SetErrorStringWithFormat ("%d is outside the bounds of the specified array variable, " 2235 "cannot update array value", index); 2236 } 2237 } 2238 2239 switch (op) 2240 { 2241 case eVarSetOperationAssign: 2242 array_var.SetCommandString (new_value); 2243 break; 2244 case eVarSetOperationReplace: 2245 { 2246 if (valid_index) 2247 array_var.ReplaceArgumentAtIndex (index, new_value); 2248 break; 2249 } 2250 case eVarSetOperationInsertBefore: 2251 case eVarSetOperationInsertAfter: 2252 { 2253 if (valid_index) 2254 { 2255 Args new_array (new_value); 2256 if (op == eVarSetOperationInsertAfter) 2257 ++index; 2258 for (int i = 0; i < new_array.GetArgumentCount(); ++i) 2259 array_var.InsertArgumentAtIndex (index, new_array.GetArgumentAtIndex (i)); 2260 } 2261 break; 2262 } 2263 case eVarSetOperationRemove: 2264 { 2265 if (valid_index) 2266 array_var.DeleteArgumentAtIndex (index); 2267 break; 2268 } 2269 case eVarSetOperationAppend: 2270 { 2271 Args new_array (new_value); 2272 array_var.AppendArguments (new_array); 2273 break; 2274 } 2275 case eVarSetOperationClear: 2276 array_var.Clear(); 2277 break; 2278 default: 2279 err.SetErrorString ("unrecognized operation, cannot update value"); 2280 break; 2281 } 2282 } 2283 2284 void 2285 UserSettingsController::UpdateDictionaryVariable (VarSetOperationType op, 2286 const char *index_value, 2287 std::map<std::string, std::string> &dictionary, 2288 const char *new_value, 2289 Error &err) 2290 { 2291 switch (op) 2292 { 2293 case eVarSetOperationReplace: 2294 if (index_value != NULL) 2295 { 2296 std::string key (index_value); 2297 std::map<std::string, std::string>::iterator pos; 2298 2299 pos = dictionary.find (key); 2300 if (pos != dictionary.end()) 2301 dictionary[key] = new_value; 2302 else 2303 err.SetErrorStringWithFormat ("'%s' is not an existing key; cannot replace value", index_value); 2304 } 2305 else 2306 err.SetErrorString ("'settings replace' requires a key for dictionary variables, no key supplied"); 2307 break; 2308 case eVarSetOperationRemove: 2309 if (index_value != NULL) 2310 { 2311 std::string key (index_value); 2312 dictionary.erase (key); 2313 } 2314 else 2315 err.SetErrorString ("'settings remove' requires a key for dictionary variables, no key supplied"); 2316 break; 2317 case eVarSetOperationClear: 2318 dictionary.clear (); 2319 break; 2320 case eVarSetOperationAppend: 2321 case eVarSetOperationAssign: 2322 { 2323 // Clear the dictionary if it's an assign with new_value as NULL. 2324 if (new_value == NULL && op == eVarSetOperationAssign) 2325 { 2326 dictionary.clear (); 2327 break; 2328 } 2329 Args args (new_value); 2330 size_t num_args = args.GetArgumentCount(); 2331 RegularExpression regex("(\\[\"?)?" // Regex match 1 (optional key prefix of '["' pr '[') 2332 "([A-Za-z_][A-Za-z_0-9]*)" // Regex match 2 (key string) 2333 "(\"?\\])?" // Regex match 3 (optional key suffix of '"]' pr ']') 2334 "=" // The equal sign that is required 2335 "(.*)"); // Regex match 4 (value string) 2336 std::string key, value; 2337 2338 for (size_t i = 0; i < num_args; ++i) 2339 { 2340 const char *key_equal_value_arg = args.GetArgumentAtIndex (i); 2341 // Execute the regular expression on each arg. 2342 if (regex.Execute(key_equal_value_arg, 5)) 2343 { 2344 // The regular expression succeeded. The match at index 2345 // zero will be the entire string that matched the entire 2346 // regular expression. The match at index 1 - 4 will be 2347 // as mentioned above by the creation of the regex pattern. 2348 // Match index 2 is the key, match index 4 is the value. 2349 regex.GetMatchAtIndex (key_equal_value_arg, 2, key); 2350 regex.GetMatchAtIndex (key_equal_value_arg, 4, value); 2351 dictionary[key] = value; 2352 } 2353 else 2354 { 2355 err.SetErrorString ("invalid format for dictionary value, expected one of '[\"<key>\"]=<value>', '[<key>]=<value>', or '<key>=<value>'"); 2356 } 2357 } 2358 } 2359 break; 2360 case eVarSetOperationInsertBefore: 2361 case eVarSetOperationInsertAfter: 2362 err.SetErrorString ("specified operation cannot be performed on dictionary variables"); 2363 break; 2364 default: 2365 err.SetErrorString ("unrecognized operation"); 2366 break; 2367 } 2368 } 2369 2370 const char * 2371 UserSettingsController::EnumToString (const OptionEnumValueElement *enum_values, 2372 int value) 2373 { 2374 int i = 0; 2375 while (enum_values[i].string_value != NULL) 2376 { 2377 if (enum_values[i].value == value) 2378 return enum_values[i].string_value; 2379 ++i; 2380 } 2381 2382 return ""; 2383 } 2384 2385 2386 void 2387 UserSettingsController::UpdateEnumVariable (OptionEnumValueElement *enum_values, 2388 int *enum_var, 2389 const char *new_value, 2390 Error &error) 2391 { 2392 *enum_var = Args::StringToOptionEnum (new_value, enum_values, enum_values[0].value, error); 2393 } 2394 2395 void 2396 UserSettingsController::RenameInstanceSettings (const char *old_name, const char *new_name) 2397 { 2398 Mutex::Locker live_mutex (m_live_settings_mutex); 2399 Mutex::Locker pending_mutex (m_pending_settings_mutex); 2400 std::string old_name_key (old_name); 2401 std::string new_name_key (new_name); 2402 2403 // First, find the live instance settings for the old_name. If they don't exist in the live settings 2404 // list, then this is not a setting that can be renamed. 2405 2406 if ((old_name_key[0] != '[') || (old_name_key[old_name_key.size() -1] != ']')) 2407 { 2408 StreamString tmp_str; 2409 tmp_str.Printf ("[%s]", old_name); 2410 old_name_key = tmp_str.GetData(); 2411 } 2412 2413 if ((new_name_key[0] != '[') || (new_name_key[new_name_key.size() -1] != ']')) 2414 { 2415 StreamString tmp_str; 2416 tmp_str.Printf ("[%s]", new_name); 2417 new_name_key = tmp_str.GetData(); 2418 } 2419 2420 if (old_name_key.compare (new_name_key) == 0) 2421 return; 2422 2423 size_t len = new_name_key.length(); 2424 std::string stripped_new_name = new_name_key.substr (1, len-2); // new name without the '[ ]' 2425 2426 InstanceSettingsMap::iterator pos; 2427 2428 pos = m_live_settings.find (old_name_key); 2429 if (pos != m_live_settings.end()) 2430 { 2431 InstanceSettings *live_settings = pos->second; 2432 2433 // Rename the settings. 2434 live_settings->ChangeInstanceName (stripped_new_name); 2435 2436 // Now see if there are any pending settings for the new name; if so, copy them into live_settings. 2437 std::map<std::string, InstanceSettingsSP>::iterator pending_pos; 2438 pending_pos = m_pending_settings.find (new_name_key); 2439 if (pending_pos != m_pending_settings.end()) 2440 { 2441 InstanceSettingsSP pending_settings_sp = pending_pos->second; 2442 live_settings->CopyInstanceSettings (pending_settings_sp, false); 2443 } 2444 2445 // Erase the old entry (under the old name) from live settings. 2446 m_live_settings.erase (pos); 2447 2448 // Add the new entry, with the new name, into live settings. 2449 m_live_settings[new_name_key] = live_settings; 2450 } 2451 } 2452 2453 //---------------------------------------------------------------------- 2454 // class InstanceSettings 2455 //---------------------------------------------------------------------- 2456 2457 InstanceSettings::InstanceSettings (UserSettingsController &owner, const char *instance_name, bool live_instance) : 2458 m_owner (owner), 2459 m_instance_name (instance_name) 2460 { 2461 if ((m_instance_name != InstanceSettings::GetDefaultName()) 2462 && (m_instance_name != InstanceSettings::InvalidName()) 2463 && live_instance) 2464 m_owner.RegisterInstanceSettings (this); 2465 } 2466 2467 InstanceSettings::~InstanceSettings () 2468 { 2469 if (m_instance_name != InstanceSettings::GetDefaultName()) 2470 m_owner.UnregisterInstanceSettings (this); 2471 } 2472 2473 const ConstString & 2474 InstanceSettings::GetDefaultName () 2475 { 2476 static const ConstString g_default_settings_name ("[DEFAULT]"); 2477 2478 return g_default_settings_name; 2479 } 2480 2481 const ConstString & 2482 InstanceSettings::InvalidName () 2483 { 2484 static const ConstString g_invalid_name ("Invalid instance name"); 2485 2486 return g_invalid_name; 2487 } 2488 2489 void 2490 InstanceSettings::ChangeInstanceName (const std::string &new_instance_name) 2491 { 2492 m_instance_name.SetCString (new_instance_name.c_str()); 2493 } 2494 2495 2496