blob: f9d6c68dfd39d0179eea7529a386e709126e157f [file] [log] [blame]
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001//====-- 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"
Greg Clayton6ad07dd2010-12-19 03:41:24 +000015#include "lldb/Core/RegularExpression.h"
Caroline Tice3df9a8d2010-09-04 00:03:46 +000016#include "lldb/Core/Stream.h"
17#include "lldb/Core/StreamString.h"
18#include "lldb/Interpreter/CommandInterpreter.h"
19
Greg Claytonbfe5f3b2011-02-18 01:44:25 +000020using namespace lldb;
Caroline Tice3df9a8d2010-09-04 00:03:46 +000021using namespace lldb_private;
22
Greg Claytonbfe5f3b2011-02-18 01:44:25 +000023static void
24DumpSettingEntry (CommandInterpreter &interpreter,
25 StreamString &result_stream,
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 (result_stream,
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 (result_stream,
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 (result_stream,
60 "",
61 " ",
62 description.GetData(),
63 max_len);
64 }
65 }
66}
67
Caroline Tice3df9a8d2010-09-04 00:03:46 +000068UserSettingsController::UserSettingsController (const char *level_name,
Greg Claytonbfe5f3b2011-02-18 01:44:25 +000069 const UserSettingsControllerSP &parent) :
Caroline Tice3df9a8d2010-09-04 00:03:46 +000070 m_default_settings (),
71 m_settings (),
72 m_children (),
73 m_pending_settings (),
74 m_live_settings (),
75 m_children_mutex (Mutex::eMutexTypeNormal),
Jim Inghama767c9a2010-09-07 23:31:30 +000076 m_pending_settings_mutex (Mutex::eMutexTypeRecursive),
77 m_live_settings_mutex (Mutex::eMutexTypeRecursive)
Caroline Tice3df9a8d2010-09-04 00:03:46 +000078{
79 m_settings.parent = parent;
80 m_settings.level_name.SetCString (level_name);
81}
82
83UserSettingsController::~UserSettingsController ()
84{
85 m_live_settings.clear();
86}
87
Jim Ingham95852752010-09-07 20:27:09 +000088bool
Greg Clayton1b654882010-09-19 02:33:57 +000089UserSettingsController::SetGlobalVariable
90(
91 const ConstString &var_name,
92 const char *index_value,
93 const char *value,
94 const SettingEntry &entry,
Greg Claytonbfe5f3b2011-02-18 01:44:25 +000095 const VarSetOperationType op,
Greg Clayton1b654882010-09-19 02:33:57 +000096 Error &err
97)
98{
99 err.SetErrorString ("UserSettingsController has no global settings");
100 return false;
101}
102
103bool
104UserSettingsController::GetGlobalVariable
105(
106 const ConstString &var_name,
Caroline Ticedaccaa92010-09-20 20:44:43 +0000107 StringList &value,
108 Error &err
Greg Clayton1b654882010-09-19 02:33:57 +0000109)
110{
111 return false;
112}
113
114bool
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000115UserSettingsController::InitializeSettingsController (UserSettingsControllerSP &controller_sp,
Jim Ingham95852752010-09-07 20:27:09 +0000116 SettingEntry *global_settings,
117 SettingEntry *instance_settings)
118{
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000119 const UserSettingsControllerSP &parent = controller_sp->GetParent ();
Jim Ingham95852752010-09-07 20:27:09 +0000120 if (parent)
Greg Claytondbe54502010-11-19 03:46:01 +0000121 parent->RegisterChild (controller_sp);
Jim Ingham95852752010-09-07 20:27:09 +0000122
Caroline Tice91123da2010-09-08 17:48:55 +0000123 controller_sp->CreateSettingsVector (global_settings, true);
124 controller_sp->CreateSettingsVector (instance_settings, false);
Jim Ingham95852752010-09-07 20:27:09 +0000125
Caroline Tice91123da2010-09-08 17:48:55 +0000126 controller_sp->InitializeGlobalVariables ();
Jim Ingham95852752010-09-07 20:27:09 +0000127 controller_sp->CreateDefaultInstanceSettings ();
128
129 return true;
130}
131
132void
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000133UserSettingsController::FinalizeSettingsController (UserSettingsControllerSP &controller_sp)
Jim Ingham95852752010-09-07 20:27:09 +0000134{
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000135 const UserSettingsControllerSP &parent = controller_sp->GetParent ();
Jim Ingham95852752010-09-07 20:27:09 +0000136 if (parent)
137 parent->RemoveChild (controller_sp);
138}
139
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000140void
141UserSettingsController::InitializeGlobalVariables ()
142{
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000143 int num_entries;
144 const char *prefix = GetLevelName().AsCString();
145
Caroline Ticedaccaa92010-09-20 20:44:43 +0000146 num_entries = m_settings.global_settings.size();
147 for (int i = 0; i < num_entries; ++i)
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000148 {
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000149 const SettingEntry &entry = m_settings.global_settings[i];
Caroline Ticedaccaa92010-09-20 20:44:43 +0000150 if (entry.default_value != NULL)
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000151 {
Caroline Ticedaccaa92010-09-20 20:44:43 +0000152 StreamString full_name;
153 if (prefix[0] != '\0')
154 full_name.Printf ("%s.%s", prefix, entry.var_name);
155 else
156 full_name.Printf ("%s", entry.var_name);
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000157 SetVariable (full_name.GetData(), entry.default_value, eVarSetOperationAssign, false, "");
Caroline Ticedaccaa92010-09-20 20:44:43 +0000158 }
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000159 }
160}
161
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000162const UserSettingsControllerSP &
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000163UserSettingsController::GetParent ()
164{
165 return m_settings.parent;
166}
167
168void
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000169UserSettingsController::RegisterChild (const UserSettingsControllerSP &child)
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000170{
171 Mutex::Locker locker (m_children_mutex);
172
173 // Verify child is not already in m_children.
174 size_t num_children = m_children.size();
175 bool found = false;
176 for (size_t i = 0; i < num_children; ++i)
177 {
178 if (m_children[i].get() == child.get())
179 found = true;
180 }
181
182 // Add child to m_children.
183 if (! found)
184 m_children.push_back (child);
185}
186
187const ConstString &
188UserSettingsController::GetLevelName ()
189{
190 return m_settings.level_name;
191}
192
193size_t
194UserSettingsController::GetNumChildren ()
195{
196 return m_children.size();
197}
198
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000199const UserSettingsControllerSP
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000200UserSettingsController::GetChildAtIndex (size_t index)
201{
202 if (index < m_children.size())
203 return m_children[index];
204
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000205 UserSettingsControllerSP dummy_value;
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000206
207 return dummy_value;
208}
209
210const SettingEntry *
211UserSettingsController::GetGlobalEntry (const ConstString &var_name)
212{
213
214 for (int i = 0; i < m_settings.global_settings.size(); ++i)
215 {
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000216 const SettingEntry &entry = m_settings.global_settings[i];
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000217 ConstString entry_name (entry.var_name);
218 if (entry_name == var_name)
219 return &entry;
220 }
221
222 return NULL;
223}
224
225const SettingEntry *
226UserSettingsController::GetInstanceEntry (const ConstString &const_var_name)
227{
228
229 for (int i = 0; i < m_settings.instance_settings.size(); ++i)
230 {
231 SettingEntry &entry = m_settings.instance_settings[i];
232 ConstString entry_name (entry.var_name);
233 if (entry_name == const_var_name)
234 return &entry;
235 }
236
237 return NULL;
238}
239
240void
241UserSettingsController::BuildParentPrefix (std::string &parent_prefix)
242{
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000243 UserSettingsControllerSP parent = GetParent();
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000244 if (parent.get() != NULL)
245 {
246 parent->BuildParentPrefix (parent_prefix);
247 if (parent_prefix.length() > 0)
248 parent_prefix.append (".");
249 }
250 parent_prefix.append (GetLevelName().AsCString());
251}
252
253void
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000254UserSettingsController::RemoveChild (const UserSettingsControllerSP &child)
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000255{
256 Mutex::Locker locker (m_children_mutex);
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000257 std::vector<UserSettingsControllerSP>::iterator pos, end = m_children.end();
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000258
259 for (pos = m_children.begin(); pos != end; ++pos)
260 {
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000261 UserSettingsControllerSP entry = *pos;
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000262 if (entry == child)
263 {
264 m_children.erase (pos);
265 break;
266 }
267 }
268}
269
270Error
271UserSettingsController::SetVariable (const char *full_dot_name,
272 const char *value,
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000273 const VarSetOperationType op,
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000274 const bool override,
Caroline Tice101c7c22010-09-09 06:25:08 +0000275 const char *debugger_instance_name,
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000276 const char *index_value)
277{
278 Error err;
279 ConstString const_var_name;
280 const ConstString &default_name = InstanceSettings::GetDefaultName();
281
282 Args names = UserSettingsController::BreakNameIntoPieces (full_dot_name);
283 int num_pieces = names.GetArgumentCount();
284
285 if (num_pieces < 1)
286 {
287 err.SetErrorStringWithFormat ("'%s' is not a valid variable name; cannot assign value.\n", full_dot_name);
288 return err;
289 }
290
291 ConstString prefix (names.GetArgumentAtIndex (0));
292
293 if ((prefix == m_settings.level_name)
294 || (m_settings.level_name.GetLength() == 0))
295 {
296
297 if (prefix == m_settings.level_name)
298 {
299 names.Shift ();
300 num_pieces = names.GetArgumentCount();
301 }
302
303 if (num_pieces == 0)
304 {
305 err.SetErrorString ("No variable name specified; cannot assign value.\n");
306 return err;
307 }
308 else if (num_pieces == 1)
309 {
310
311 // Must be one of the class-wide settings.
312
313 const_var_name.SetCString (names.GetArgumentAtIndex (0));
314 const SettingEntry *entry = GetGlobalEntry (const_var_name);
315 if (entry)
316 {
317 UserSettingsController::VerifyOperationForType (entry->var_type, op, const_var_name, err);
318
319 if (err.Fail())
320 return err;
321
322 if ((value == NULL || value[0] == '\0')
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000323 && (op == eVarSetOperationAssign))
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000324 {
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000325 if (entry->var_type != eSetVarTypeEnum)
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000326 value = entry->default_value;
327 else
328 value = entry->enum_values[0].string_value;
329 }
Greg Clayton1b654882010-09-19 02:33:57 +0000330 SetGlobalVariable (const_var_name, index_value, value, *entry, op, err);
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000331 }
332 else
333 {
334 // MIGHT be instance variable, to be for ALL instances.
335
336 entry = GetInstanceEntry (const_var_name);
337 if (entry == NULL)
338 {
339 err.SetErrorStringWithFormat ("Unable to find variable '%s.%s'; cannot assign value.\n",
340 prefix.AsCString(), const_var_name.AsCString());
341 return err;
342 }
343 else
344 {
345 UserSettingsController::VerifyOperationForType (entry->var_type, op, const_var_name, err);
346
347 if (err.Fail())
348 return err;
349
350 if ((value == NULL || value[0] == '\0')
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000351 && (op == eVarSetOperationAssign))
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000352 {
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000353 if (entry->var_type != eSetVarTypeEnum)
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000354 value = entry->default_value;
355 else
356 value = entry->enum_values[0].string_value;
357 }
358
Caroline Tice101c7c22010-09-09 06:25:08 +0000359 if ((m_settings.level_name.GetLength() > 0)
360 || strlen (debugger_instance_name) == 0)
361 {
362 // Set the default settings
363 m_default_settings->UpdateInstanceSettingsVariable (const_var_name, index_value, value,
364 default_name, *entry, op, err, true);
365 }
366 else
367 {
368 // We're at the Debugger level; find the correct debugger instance and set those settings
369 StreamString tmp_name;
370 if (debugger_instance_name[0] != '[')
371 tmp_name.Printf ("[%s]", debugger_instance_name);
372 else
373 tmp_name.Printf ("%s", debugger_instance_name);
374 ConstString dbg_name (tmp_name.GetData());
375 InstanceSettings *dbg_settings = FindSettingsForInstance (dbg_name);
376 if (dbg_settings)
377 dbg_settings->UpdateInstanceSettingsVariable (const_var_name, index_value, value, dbg_name,
378 *entry, op, err, false);
379 }
380
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000381 if (override)
382 {
383 OverrideAllInstances (const_var_name, value, op, index_value, err);
384
385 // Update all pending records as well.
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000386// std::map<std::string, InstanceSettingsSP>::iterator pos, end = m_pending_settings.end();
Caroline Tice1559a462010-09-27 00:30:10 +0000387// for (pos = m_pending_settings.begin(); pos != end; end++)
388// {
389// const ConstString instance_name (pos->first.c_str());
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000390// InstanceSettingsSP setting_sp = pos->second;
Caroline Tice1559a462010-09-27 00:30:10 +0000391// setting_sp->UpdateInstanceSettingsVariable (const_var_name, index_value, value,
392// instance_name, *entry, op, err, true);
393// }
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000394 }
395 }
396 }
397 }
398 else
399 {
400 // Either a child's setting or an instance setting.
401
402 if (names.GetArgumentAtIndex(0)[0] == '[')
403 {
404 // An instance setting. Supposedly.
405
406 ConstString instance_name (names.GetArgumentAtIndex (0));
407
408 // First verify that there is only one more name.
409
410 names.Shift();
411
412 if (names.GetArgumentCount() != 1)
413 {
414 err.SetErrorStringWithFormat ("Invalid variable name format '%s'; cannot assign value.\n",
415 full_dot_name);
416 return err;
417 }
418
419 // Next verify that it is a valid instance setting name.
420
421 const_var_name.SetCString (names.GetArgumentAtIndex (0));
422 const SettingEntry *entry = GetInstanceEntry (const_var_name);
423
424 if (entry == NULL)
425 {
426 err.SetErrorStringWithFormat ("Unknown instance variable '%s'; cannot assign value.\n",
427 const_var_name.AsCString());
428 return err;
429 }
430
431 UserSettingsController::VerifyOperationForType (entry->var_type, op, const_var_name, err);
432
433 if (err.Fail())
434 return err;
435
436 if ((value == NULL || value[0] == '\0')
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000437 && (op == eVarSetOperationAssign))
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000438 {
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000439 if (entry->var_type != eSetVarTypeEnum)
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000440 value = entry->default_value;
441 else
442 value = entry->enum_values[0].string_value;
443 }
444
445 // Now look for existing instance with given instance name; if not found, find or create pending
446 // setting for instance with given name.
447
448 InstanceSettings *current_settings = FindSettingsForInstance (instance_name);
449
450 if (current_settings != NULL)
451 {
452 current_settings->UpdateInstanceSettingsVariable (const_var_name, index_value, value,
453 instance_name, *entry, op, err, false);
454
455 }
456 else
457 {
458 // Instance does not currently exist; make or update a pending setting for it.
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000459 InstanceSettingsSP current_settings_sp = PendingSettingsForInstance (instance_name);
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000460
461 // Now we have a settings record, update it appropriately.
462
463 current_settings_sp->UpdateInstanceSettingsVariable (const_var_name, index_value, value,
464 instance_name, *entry, op, err, true);
465
466 { // Scope for mutex.
467 Mutex::Locker locker (m_pending_settings_mutex);
468 m_pending_settings[instance_name.AsCString()] = current_settings_sp;
469 }
470
471 if (override)
472 {
473 OverrideAllInstances (const_var_name, value, op, index_value, err);
474
475 // Update all pending records as well.
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000476 std::map<std::string, InstanceSettingsSP>::iterator pos;
477 std::map<std::string, InstanceSettingsSP>::iterator end = m_pending_settings.end();
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000478 for (pos = m_pending_settings.begin(); pos != end; end++)
479 {
480 const ConstString tmp_inst_name (pos->first.c_str());
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000481 InstanceSettingsSP setting_sp = pos->second;
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000482 setting_sp->UpdateInstanceSettingsVariable (const_var_name, index_value, value,
483 tmp_inst_name, *entry, op, err, true);
484 }
485 }
486 }
487 }
488 else
489 {
490 // A child setting.
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000491 UserSettingsControllerSP child;
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000492 ConstString child_prefix (names.GetArgumentAtIndex (0));
493 int num_children = GetNumChildren();
494 bool found = false;
495 for (int i = 0; i < num_children && !found; ++i)
496 {
497 child = GetChildAtIndex (i);
498 ConstString current_prefix = child->GetLevelName();
499 if (current_prefix == child_prefix)
500 {
501 found = true;
502 std::string new_name;
503 for (int j = 0; j < names.GetArgumentCount(); ++j)
504 {
505 if (j > 0)
506 new_name += '.';
507 new_name += names.GetArgumentAtIndex (j);
508 }
Caroline Tice101c7c22010-09-09 06:25:08 +0000509 return child->SetVariable (new_name.c_str(), value, op, override, debugger_instance_name,
510 index_value);
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000511 }
512 }
513 if (!found)
514 {
515 err.SetErrorStringWithFormat ("Unable to find variable '%s'; cannot assign value.\n",
516 full_dot_name);
517 return err;
518 }
519 }
520 }
521 }
522 else
523 {
524 err.SetErrorStringWithFormat ("'%s' is not a valid level name; was expecting '%s'. Cannot assign value.\n",
525 prefix.AsCString(), m_settings.level_name.AsCString());
526 }
527
528 return err;
529}
530
531StringList
Greg Clayton1b654882010-09-19 02:33:57 +0000532UserSettingsController::GetVariable
533(
534 const char *full_dot_name,
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000535 SettableVariableType &var_type,
Caroline Ticedaccaa92010-09-20 20:44:43 +0000536 const char *debugger_instance_name,
537 Error &err
Greg Clayton1b654882010-09-19 02:33:57 +0000538)
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000539{
540 Args names = UserSettingsController::BreakNameIntoPieces (full_dot_name);
541 ConstString const_var_name;
542 StringList value;
543
544 int num_pieces = names.GetArgumentCount();
545
546 ConstString prefix (names.GetArgumentAtIndex (0));
547 const_var_name.SetCString (names.GetArgumentAtIndex (num_pieces - 1));
548
549 const SettingEntry *global_entry = GetGlobalEntry (const_var_name);
550 const SettingEntry *instance_entry = GetInstanceEntry (const_var_name);
551
552 if ((prefix != m_settings.level_name)
553 && (m_settings.level_name.GetLength () > 0))
554 {
Caroline Ticedaccaa92010-09-20 20:44:43 +0000555 err.SetErrorString ("Invalid variable name");
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000556 return value;
557 }
558
559 // prefix name matched; remove it from names.
560 if (m_settings.level_name.GetLength() > 0)
561 names.Shift();
562
563 // Should we pass this off to a child? If there is more than one name piece left, and the next name piece
564 // matches a child prefix, then yes.
565
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000566 UserSettingsControllerSP child;
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000567 if (names.GetArgumentCount() > 1)
568 {
569 ConstString child_prefix (names.GetArgumentAtIndex (0));
570 bool found = false;
571 for (int i = 0; i < m_children.size() && !found; ++i)
572 {
573 if (child_prefix == m_children[i]->GetLevelName())
574 {
575 found = true;
576 child = m_children[i];
577 std::string new_name;
578 for (int j = 0; j < names.GetArgumentCount(); ++j)
579 {
580 if (j > 0)
581 new_name += '.';
582 new_name += names.GetArgumentAtIndex (j);
583 }
Caroline Ticedaccaa92010-09-20 20:44:43 +0000584 return child->GetVariable (new_name.c_str(), var_type, debugger_instance_name, err);
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000585 }
586 }
587
588 if (!found)
589 {
590 // Cannot be handled by a child, because name did not match any child prefixes.
591 // Cannot be a class-wide variable because there are too many name pieces.
592
593 if (instance_entry != NULL)
594 {
595 var_type = instance_entry->var_type;
596 ConstString instance_name (names.GetArgumentAtIndex (0));
597 InstanceSettings *current_settings = FindSettingsForInstance (instance_name);
598
599 if (current_settings != NULL)
600 {
Caroline Tice12cecd72010-09-20 21:37:42 +0000601 current_settings->GetInstanceSettingsValue (*instance_entry, const_var_name, value, &err);
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000602 }
603 else
604 {
605 // Look for instance name setting in pending settings.
606
607 std::string inst_name_str = instance_name.AsCString();
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000608 std::map<std::string, InstanceSettingsSP>::iterator pos;
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000609
610 pos = m_pending_settings.find (inst_name_str);
611 if (pos != m_pending_settings.end())
612 {
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000613 InstanceSettingsSP settings_sp = pos->second;
Caroline Tice12cecd72010-09-20 21:37:42 +0000614 settings_sp->GetInstanceSettingsValue (*instance_entry, const_var_name, value, &err);
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000615 }
616 else
617 {
Caroline Tice101c7c22010-09-09 06:25:08 +0000618 if (m_settings.level_name.GetLength() > 0)
619 {
620 // No valid instance name; assume they want the default settings.
Caroline Tice12cecd72010-09-20 21:37:42 +0000621 m_default_settings->GetInstanceSettingsValue (*instance_entry, const_var_name, value, &err);
Caroline Tice101c7c22010-09-09 06:25:08 +0000622 }
623 else
624 {
625 // We're at the Debugger level; use the debugger's instance settings.
626 StreamString tmp_name;
627 if (debugger_instance_name[0] != '[')
628 tmp_name.Printf ("[%s]", debugger_instance_name);
629 else
630 tmp_name.Printf ("%s", debugger_instance_name);
631 ConstString dbg_name (debugger_instance_name);
632 InstanceSettings *dbg_settings = FindSettingsForInstance (dbg_name);
633 if (dbg_settings)
Caroline Tice12cecd72010-09-20 21:37:42 +0000634 dbg_settings->GetInstanceSettingsValue (*instance_entry, const_var_name, value, &err);
Caroline Tice101c7c22010-09-09 06:25:08 +0000635 }
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000636 }
637 }
638 }
639 else
Caroline Ticedaccaa92010-09-20 20:44:43 +0000640 err.SetErrorString ("Invalid variable name");
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000641 }
642 }
643 else
644 {
645 // Only one name left. It must belong to the current level, or be an error.
646 if ((global_entry == NULL)
647 && (instance_entry == NULL))
648 {
Caroline Ticedaccaa92010-09-20 20:44:43 +0000649 err.SetErrorString ("Invalid variable name");
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000650 }
651 else if (global_entry)
652 {
653 var_type = global_entry->var_type;
Caroline Ticedaccaa92010-09-20 20:44:43 +0000654 GetGlobalVariable (const_var_name, value, err);
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000655 }
656 else if (instance_entry)
657 {
658 var_type = instance_entry->var_type;
Caroline Tice101c7c22010-09-09 06:25:08 +0000659 if (m_settings.level_name.GetLength() > 0)
Caroline Tice12cecd72010-09-20 21:37:42 +0000660 m_default_settings->GetInstanceSettingsValue (*instance_entry, const_var_name, value, &err);
Caroline Tice101c7c22010-09-09 06:25:08 +0000661 else
662 {
663 // We're at the Debugger level; use the debugger's instance settings.
664 StreamString tmp_name;
665 if (debugger_instance_name[0] != '[')
666 tmp_name.Printf ("[%s]", debugger_instance_name);
667 else
668 tmp_name.Printf ("%s", debugger_instance_name);
669 ConstString dbg_name (tmp_name.GetData());
670 InstanceSettings *dbg_settings = FindSettingsForInstance (dbg_name);
671 if (dbg_settings)
Caroline Tice12cecd72010-09-20 21:37:42 +0000672 dbg_settings->GetInstanceSettingsValue (*instance_entry, const_var_name, value, &err);
Caroline Tice101c7c22010-09-09 06:25:08 +0000673 }
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000674 }
675 }
676
677 return value;
678}
679
680void
681UserSettingsController::RemovePendingSettings (const ConstString &instance_name)
682{
Caroline Tice91123da2010-09-08 17:48:55 +0000683 StreamString tmp_name;
684
685 // Add surrounding brackets to instance name if not already present.
686
687 if (instance_name.AsCString()[0] != '[')
688 tmp_name.Printf ("[%s]", instance_name.AsCString());
689 else
690 tmp_name.Printf ("%s", instance_name.AsCString());
691
692 std::string instance_name_str (tmp_name.GetData());
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000693 std::map<std::string, InstanceSettingsSP>::iterator pos;
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000694 Mutex::Locker locker (m_pending_settings_mutex);
695
696 m_pending_settings.erase (instance_name_str);
697}
698
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000699const InstanceSettingsSP &
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000700UserSettingsController::FindPendingSettings (const ConstString &instance_name)
701{
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000702 std::map<std::string, InstanceSettingsSP>::iterator pos;
Caroline Tice91123da2010-09-08 17:48:55 +0000703 StreamString tmp_name;
704
705 // Add surrounding brackets to instance name if not already present.
706
707 if (instance_name.AsCString()[0] != '[')
708 tmp_name.Printf ("[%s]", instance_name.AsCString());
709 else
710 tmp_name.Printf ("%s", instance_name.AsCString());
711
712 std::string instance_name_str (tmp_name.GetData()); // Need std::string for std::map look-up
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000713
714 { // Scope for mutex.
715 Mutex::Locker locker (m_pending_settings_mutex);
716
717 pos = m_pending_settings.find (instance_name_str);
718 if (pos != m_pending_settings.end())
719 return pos->second;
720 }
721
722 return m_default_settings;
723}
724
725void
726UserSettingsController::CreateDefaultInstanceSettings ()
727{
728 Error err;
729 const ConstString &default_name = InstanceSettings::GetDefaultName();
730 for (int i = 0; i < m_settings.instance_settings.size(); ++i)
731 {
732 SettingEntry &entry = m_settings.instance_settings[i];
733 ConstString var_name (entry.var_name);
734 const char *value = entry.default_value;
735
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000736 if (entry.var_type == eSetVarTypeEnum)
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000737 value = entry.enum_values[0].string_value;
738
739 m_default_settings->UpdateInstanceSettingsVariable (var_name, NULL, value, default_name, entry,
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000740 eVarSetOperationAssign, err, true);
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000741 }
742}
743
744void
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000745UserSettingsController::CopyDefaultSettings (const InstanceSettingsSP &actual_settings,
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000746 const ConstString &instance_name,
747 bool pending)
748{
749 Error err;
750 for (int i = 0; i < m_settings.instance_settings.size(); ++i)
751 {
752 SettingEntry &entry = m_settings.instance_settings[i];
753 ConstString var_name (entry.var_name);
754 StringList value;
Caroline Tice12cecd72010-09-20 21:37:42 +0000755 m_default_settings->GetInstanceSettingsValue (entry, var_name, value, NULL);
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000756
757 std::string value_str;
758 if (value.GetSize() == 1)
759 value_str.append (value.GetStringAtIndex (0));
760 else if (value.GetSize() > 1)
761 {
762 for (int j = 0; j < value.GetSize(); ++j)
763 {
764 if (j > 0)
765 value_str.append (" ");
766 value_str.append (value.GetStringAtIndex (j));
767 }
768 }
769
770 actual_settings->UpdateInstanceSettingsVariable (var_name, NULL, value_str.c_str(), instance_name, entry,
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000771 eVarSetOperationAssign, err, pending);
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000772
773 }
774}
775
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000776InstanceSettingsSP
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000777UserSettingsController::PendingSettingsForInstance (const ConstString &instance_name)
778{
779 std::string name_str (instance_name.AsCString());
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000780 std::map<std::string, InstanceSettingsSP>::iterator pos;
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000781 Mutex::Locker locker (m_pending_settings_mutex);
782
783 pos = m_pending_settings.find (name_str);
784 if (pos != m_pending_settings.end())
Greg Clayton1b654882010-09-19 02:33:57 +0000785 {
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000786 InstanceSettingsSP settings_sp = pos->second;
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000787 return settings_sp;
Greg Clayton1b654882010-09-19 02:33:57 +0000788 }
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000789 else
Greg Clayton1b654882010-09-19 02:33:57 +0000790 {
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000791 InstanceSettingsSP new_settings_sp = CreateInstanceSettings (instance_name.AsCString());
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000792 CopyDefaultSettings (new_settings_sp, instance_name, true);
793 m_pending_settings[name_str] = new_settings_sp;
794 return new_settings_sp;
Greg Clayton1b654882010-09-19 02:33:57 +0000795 }
796
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000797 // Should never reach this line.
798
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000799 InstanceSettingsSP dummy;
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000800
801 return dummy;
802}
803
804void
805UserSettingsController::GetAllDefaultSettingValues (StreamString &result_stream)
806{
807 std::string parent_prefix;
808 BuildParentPrefix (parent_prefix);
809 const char *prefix = parent_prefix.c_str();
810
811 for (int i = 0; i < m_settings.instance_settings.size(); ++i)
812 {
813 SettingEntry &entry = m_settings.instance_settings[i];
814 ConstString var_name (entry.var_name);
815 StringList tmp_value;
Caroline Tice12cecd72010-09-20 21:37:42 +0000816 m_default_settings->GetInstanceSettingsValue (entry, var_name, tmp_value, NULL);
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000817
818 StreamString value_string;
Caroline Tice2d5289d2010-12-10 00:26:54 +0000819 bool multi_value = false;
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000820
821 if (tmp_value.GetSize() == 1)
822 value_string.Printf ("%s", tmp_value.GetStringAtIndex (0));
823 else
824 {
825 for (int j = 0; j < tmp_value.GetSize(); ++j)
Caroline Tice2d5289d2010-12-10 00:26:54 +0000826 {
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000827 if (entry.var_type == eSetVarTypeArray)
Caroline Tice2d5289d2010-12-10 00:26:54 +0000828 value_string.Printf ("\n [%d]: '%s'", j, tmp_value.GetStringAtIndex (j));
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000829 else if (entry.var_type == eSetVarTypeDictionary)
Caroline Tice2d5289d2010-12-10 00:26:54 +0000830 value_string.Printf ("\n '%s'", tmp_value.GetStringAtIndex (j));
831 }
832 multi_value = true;
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000833 }
834
Caroline Ticeded2fa32010-09-15 05:35:14 +0000835 if (! parent_prefix.empty())
Caroline Tice2d5289d2010-12-10 00:26:54 +0000836 {
837 if (multi_value)
838 result_stream.Printf ("%s.%s (%s):%s\n", prefix, var_name.AsCString(),
839 UserSettingsController::GetTypeString (entry.var_type), value_string.GetData());
840 else
841 result_stream.Printf ("%s.%s (%s) = '%s'\n", prefix, var_name.AsCString(),
842 UserSettingsController::GetTypeString (entry.var_type), value_string.GetData());
843 }
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000844 }
845}
846
847void
848UserSettingsController::GetAllPendingSettingValues (StreamString &result_stream)
849{
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000850 std::map<std::string, InstanceSettingsSP>::iterator pos;
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000851
852 std::string parent_prefix;
853 BuildParentPrefix (parent_prefix);
854 const char *prefix = parent_prefix.c_str();
855
856 for (pos = m_pending_settings.begin(); pos != m_pending_settings.end(); ++pos)
857 {
858 std::string tmp_name = pos->first;
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000859 InstanceSettingsSP settings_sp = pos->second;
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000860
861 const ConstString instance_name (tmp_name.c_str());
862
863 for (int i = 0; i < m_settings.instance_settings.size(); ++i)
864 {
865 SettingEntry &entry = m_settings.instance_settings[i];
866 ConstString var_name (entry.var_name);
867 StringList tmp_value;
Caroline Tice12cecd72010-09-20 21:37:42 +0000868 settings_sp->GetInstanceSettingsValue (entry, var_name, tmp_value, NULL);
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000869
870 StreamString value_str;
871
872 if (tmp_value.GetSize() == 0)
Caroline Ticeded2fa32010-09-15 05:35:14 +0000873 value_str.Printf ("");
874 else if (tmp_value.GetSize() == 1)
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000875 value_str.Printf ("%s", tmp_value.GetStringAtIndex (0));
876 else
877 {
878 for (int j = 0; j < tmp_value.GetSize(); ++j)
879 value_str.Printf ("%s ", tmp_value.GetStringAtIndex (j));
880 }
881
882 if (parent_prefix.length() > 0)
883 {
884 result_stream.Printf ("%s.%s.%s (%s) = '%s' [pending]\n", prefix, instance_name.AsCString(),
885 var_name.AsCString(), UserSettingsController::GetTypeString (entry.var_type),
886 value_str.GetData());
887 }
888 else
889 {
890 result_stream.Printf ("%s (%s) = '%s' [pending]\n", var_name.AsCString(),
891 UserSettingsController::GetTypeString (entry.var_type),
892 value_str.GetData());
893 }
894 }
895 }
896}
897
898InstanceSettings *
899UserSettingsController::FindSettingsForInstance (const ConstString &instance_name)
900{
901 std::string instance_name_str (instance_name.AsCString());
902 std::map<std::string, InstanceSettings *>::iterator pos;
903
904 pos = m_live_settings.find (instance_name_str);
905 if (pos != m_live_settings.end ())
906 {
907 InstanceSettings *settings = pos->second;
908 return settings;
909 }
910
911 return NULL;
912}
913
914void
915UserSettingsController::GetAllInstanceVariableValues (CommandInterpreter &interpreter,
916 StreamString &result_stream)
917{
918 std::map<std::string, InstanceSettings *>::iterator pos;
919 std::string parent_prefix;
920 BuildParentPrefix (parent_prefix);
921 const char *prefix = parent_prefix.c_str();
922 StreamString description;
923
924 for (pos = m_live_settings.begin(); pos != m_live_settings.end(); ++pos)
925 {
926 std::string instance_name = pos->first;
927 InstanceSettings *settings = pos->second;
928
929 for (int i = 0; i < m_settings.instance_settings.size(); ++i)
930 {
931 SettingEntry &entry = m_settings.instance_settings[i];
932 const ConstString var_name (entry.var_name);
933 StringList tmp_value;
Caroline Tice12cecd72010-09-20 21:37:42 +0000934 settings->GetInstanceSettingsValue (entry, var_name, tmp_value, NULL);
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000935 StreamString tmp_value_str;
936
937 if (tmp_value.GetSize() == 0)
Caroline Ticeded2fa32010-09-15 05:35:14 +0000938 tmp_value_str.Printf ("");
939 else if (tmp_value.GetSize() == 1)
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000940 tmp_value_str.Printf ("%s", tmp_value.GetStringAtIndex (0));
941 else
942 {
943 for (int j = 0; j < tmp_value.GetSize(); ++j)
944 tmp_value_str.Printf ("%s ",tmp_value.GetStringAtIndex (j));
945 }
946
947 description.Clear();
948 if (parent_prefix.length() > 0)
949 {
950 description.Printf ("%s.%s.%s (%s) = '%s'", prefix, instance_name.c_str(), var_name.AsCString(),
951 UserSettingsController::GetTypeString (entry.var_type),
952 tmp_value_str.GetData());
953 }
954 else
955 {
956 description.Printf ("%s (%s) = '%s'", var_name.AsCString(),
957 UserSettingsController::GetTypeString (entry.var_type), tmp_value_str.GetData());
958 }
959 result_stream.Printf ("%s\n", description.GetData());
960 }
961 }
962}
963
964void
965UserSettingsController::OverrideAllInstances (const ConstString &var_name,
966 const char *value,
Greg Claytonbfe5f3b2011-02-18 01:44:25 +0000967 VarSetOperationType op,
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000968 const char *index_value,
969 Error &err)
970{
971 std::map<std::string, InstanceSettings *>::iterator pos;
972 StreamString description;
973
974 for (pos = m_live_settings.begin(); pos != m_live_settings.end(); ++pos)
975 {
976 InstanceSettings *settings = pos->second;
977 StreamString tmp_name;
978 tmp_name.Printf ("[%s]", settings->GetInstanceName().AsCString());
979 const ConstString instance_name (tmp_name.GetData());
980 const SettingEntry *entry = GetInstanceEntry (var_name);
981 settings->UpdateInstanceSettingsVariable (var_name, index_value, value, instance_name, *entry, op, err, false);
982
983 }
984}
985
986void
987UserSettingsController::RegisterInstanceSettings (InstanceSettings *instance_settings)
988{
989 Mutex::Locker locker (m_live_settings_mutex);
990 StreamString tmp_name;
991 tmp_name.Printf ("[%s]", instance_settings->GetInstanceName().AsCString());
992 const ConstString instance_name (tmp_name.GetData());
993 std::string instance_name_str (instance_name.AsCString());
994 if (instance_name_str.compare (InstanceSettings::GetDefaultName().AsCString()) != 0)
995 m_live_settings[instance_name_str] = instance_settings;
996}
997
998void
999UserSettingsController::UnregisterInstanceSettings (InstanceSettings *instance)
1000{
1001 Mutex::Locker locker (m_live_settings_mutex);
1002 StreamString tmp_name;
1003 tmp_name.Printf ("[%s]", instance->GetInstanceName().AsCString());
1004 std::string instance_name (tmp_name.GetData());
1005
1006 std::map <std::string, InstanceSettings *>::iterator pos;
1007
1008 pos = m_live_settings.find (instance_name);
1009 if (pos != m_live_settings.end())
1010 m_live_settings.erase (pos);
1011}
1012
1013void
1014UserSettingsController::CreateSettingsVector (const SettingEntry *table,
1015 bool global)
1016{
1017 int i = 0;
1018 while (table[i].var_name != NULL)
1019 {
1020 const SettingEntry &table_entry = table[i];
1021 ConstString const_var_name (table_entry.var_name);
1022 SettingEntry new_entry;
1023
1024 new_entry = table_entry;
1025 new_entry.var_name = const_var_name.AsCString();
1026
1027 if (global)
1028 m_settings.global_settings.push_back (new_entry);
1029 else
1030 m_settings.instance_settings.push_back (new_entry);
1031
1032 ++i;
1033 }
1034}
1035
1036//----------------------------------------------------------------------
1037// UserSettingsController static methods
1038//----------------------------------------------------------------------
1039
1040int
1041FindMaxNameLength (std::vector<SettingEntry> table)
1042{
1043 int max_length = 1;
1044
1045 for (int i = 0; i < table.size(); ++i)
1046 {
1047 int len = strlen (table[i].var_name);
1048 if (len > max_length)
1049 max_length = len;
1050 }
1051
1052 return max_length;
1053}
1054
1055const char *
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001056UserSettingsController::GetTypeString (SettableVariableType var_type)
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001057{
1058 switch (var_type)
1059 {
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001060 case eSetVarTypeInt:
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001061 return "int";
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001062 case eSetVarTypeBoolean:
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001063 return "boolean";
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001064 case eSetVarTypeString:
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001065 return "string";
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001066 case eSetVarTypeArray:
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001067 return "array";
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001068 case eSetVarTypeDictionary:
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001069 return "dictionary";
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001070 case eSetVarTypeEnum:
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001071 return "enum";
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001072 case eSetVarTypeNone:
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001073 return "no type";
1074 }
1075
1076 return "";
1077}
1078
1079void
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001080UserSettingsController::PrintEnumValues (const OptionEnumValueElement *enum_values, Stream &str)
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001081{
1082 int i = 0;
1083 while (enum_values[i].string_value != NULL)
1084 {
1085 str.Printf ("%s ", enum_values[i].string_value);
1086 ++i;
1087 }
1088
1089}
1090
1091void
1092UserSettingsController::FindAllSettingsDescriptions (CommandInterpreter &interpreter,
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001093 UserSettingsControllerSP root,
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001094 std::string &current_prefix,
1095 StreamString &result_stream,
1096 Error &err)
1097{
1098 // Write out current prefix line.
1099 StreamString prefix_line;
1100 StreamString description;
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001101 uint32_t max_len = FindMaxNameLength (root->m_settings.global_settings);
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001102 int num_entries = root->m_settings.global_settings.size();
1103
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001104 if (! current_prefix.empty())
1105 result_stream.Printf ("\n'%s' variables:\n\n", current_prefix.c_str());
1106 else
1107 result_stream.Printf ("\nTop level variables:\n\n");
1108
1109 if (num_entries > 0)
1110 {
1111 // Write out all "global" variables.
1112 for (int i = 0; i < num_entries; ++i)
1113 {
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001114 DumpSettingEntry (interpreter, result_stream, max_len, root->m_settings.global_settings[i]);
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001115 }
1116 }
1117
1118 num_entries = root->m_settings.instance_settings.size();
1119 max_len = FindMaxNameLength (root->m_settings.instance_settings);
1120
1121 if (num_entries > 0)
1122 {
1123 // Write out all instance variables.
1124 for (int i = 0; i < num_entries; ++i)
1125 {
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001126 DumpSettingEntry (interpreter, result_stream, max_len, root->m_settings.instance_settings[i]);
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001127 }
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001128 }
1129
1130 // Now, recurse across all children.
1131 int num_children = root->GetNumChildren();
1132 for (int i = 0; i < num_children; ++i)
1133 {
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001134 UserSettingsControllerSP child = root->GetChildAtIndex (i);
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001135
1136 if (child)
1137 {
1138 ConstString child_prefix = child->GetLevelName();
1139 StreamString new_prefix;
Caroline Ticeded2fa32010-09-15 05:35:14 +00001140 if (! current_prefix.empty())
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001141 new_prefix.Printf ("%s.%s", current_prefix.c_str(), child_prefix.AsCString());
1142 else
1143 new_prefix.Printf ("%s", child_prefix.AsCString());
1144 std::string new_prefix_str = new_prefix.GetData();
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001145 UserSettingsController::FindAllSettingsDescriptions (interpreter,
1146 child,
1147 new_prefix_str,
1148 result_stream,
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001149 err);
1150 }
1151 }
1152}
1153
1154void
Caroline Tice7d9edf62010-09-15 06:56:39 +00001155UserSettingsController::FindSettingsDescriptions (CommandInterpreter &interpreter,
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001156 UserSettingsControllerSP root,
Caroline Tice7d9edf62010-09-15 06:56:39 +00001157 std::string &current_prefix,
1158 const char *search_name,
1159 StreamString &result_stream,
1160 Error &err)
1161{
1162 Args names = UserSettingsController::BreakNameIntoPieces (search_name);
1163 int num_pieces = names.GetArgumentCount ();
1164
1165 if (num_pieces == 0)
1166 return;
1167
1168 if (root->GetLevelName().GetLength() > 0)
1169 {
1170 ConstString prefix (names.GetArgumentAtIndex (0));
1171 if (prefix != root->GetLevelName())
1172 {
1173 std::string parent_prefix;
1174 root->BuildParentPrefix (parent_prefix);
1175 err.SetErrorStringWithFormat ("Cannot find match for '%s.%s'\n", parent_prefix.c_str(),
1176 prefix.AsCString());
1177 return;
1178 }
1179 else
1180 {
1181 names.Shift();
1182 --num_pieces;
1183 }
1184 }
1185
1186 // If there's nothing left then dump all global and instance descriptions for this root.
1187 if (num_pieces == 0)
1188 {
1189 StreamString prefix_line;
1190 StreamString description;
1191 uint32_t max_len;
1192 int num_entries = root->m_settings.global_settings.size();
1193
1194 max_len = FindMaxNameLength (root->m_settings.global_settings);
1195
1196 result_stream.Printf ("\n'%s' variables:\n\n", search_name);
1197
1198 if (num_entries > 0)
1199 {
1200 // Write out all "global" variables.
1201 for (int i = 0; i < num_entries; ++i)
1202 {
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001203 DumpSettingEntry (interpreter, result_stream, max_len, root->m_settings.global_settings[i]);
Caroline Tice7d9edf62010-09-15 06:56:39 +00001204 }
1205 }
1206
1207 num_entries = root->m_settings.instance_settings.size();
1208 max_len = FindMaxNameLength (root->m_settings.instance_settings);
1209
1210 if (num_entries > 0)
1211 {
1212 // Write out all instance variables.
1213 for (int i = 0; i < num_entries; ++i)
1214 {
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001215 DumpSettingEntry (interpreter, result_stream, max_len, root->m_settings.instance_settings[i]);
Caroline Tice7d9edf62010-09-15 06:56:39 +00001216 }
1217 }
1218 }
1219 else if (num_pieces == 1)
1220 {
1221 ConstString var_name (names.GetArgumentAtIndex (0));
1222 bool is_global = false;
1223
1224 const SettingEntry *setting_entry = root->GetGlobalEntry (var_name);
1225
1226 if (setting_entry == NULL)
1227 setting_entry = root->GetInstanceEntry (var_name);
1228 else
1229 is_global = true;
1230
1231 // Check to see if it is a global or instance variable name.
1232 if (setting_entry != NULL)
1233 {
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001234 DumpSettingEntry (interpreter, result_stream, var_name.GetLength(), *setting_entry);
Caroline Tice7d9edf62010-09-15 06:56:39 +00001235 }
1236 else
1237 {
1238 // It must be a child name.
1239 int num_children = root->GetNumChildren();
1240 bool found = false;
1241 for (int i = 0; i < num_children && !found; ++i)
1242 {
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001243 UserSettingsControllerSP child = root->GetChildAtIndex (i);
Caroline Tice7d9edf62010-09-15 06:56:39 +00001244 if (child)
1245 {
1246 ConstString child_prefix = child->GetLevelName();
1247 if (child_prefix == var_name)
1248 {
1249 found = true;
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001250 UserSettingsController::FindSettingsDescriptions (interpreter,
1251 child,
1252 current_prefix,
1253 var_name.AsCString(),
1254 result_stream,
1255 err);
Caroline Tice7d9edf62010-09-15 06:56:39 +00001256 }
1257 }
1258 }
1259 if (!found)
1260 {
1261 std::string parent_prefix;
1262 root->BuildParentPrefix (parent_prefix);
1263 err.SetErrorStringWithFormat ("Cannot find match for '%s.%s'\n", parent_prefix.c_str(), search_name);
1264 return;
1265 }
1266 }
1267 }
1268 else
1269 {
1270 // It must be a child name; find the child and call this function recursively on child.
1271 ConstString child_name (names.GetArgumentAtIndex (0));
1272
1273 StreamString rest_of_search_name;
1274 for (int i = 0; i < num_pieces; ++i)
1275 {
1276 rest_of_search_name.Printf ("%s", names.GetArgumentAtIndex (i));
1277 if ((i + 1) < num_pieces)
1278 rest_of_search_name.Printf (".");
1279 }
1280
1281 int num_children = root->GetNumChildren();
1282 bool found = false;
1283 for (int i = 0; i < num_children && !found; ++i)
1284 {
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001285 UserSettingsControllerSP child = root->GetChildAtIndex (i);
Caroline Tice7d9edf62010-09-15 06:56:39 +00001286 if (child)
1287 {
1288 ConstString child_prefix = child->GetLevelName();
1289 if (child_prefix == child_name)
1290 {
1291 found = true;
1292 UserSettingsController::FindSettingsDescriptions (interpreter, child, current_prefix,
1293 rest_of_search_name.GetData(), result_stream,
1294 err);
1295 }
1296 }
1297 }
1298 if (!found)
1299 {
1300 std::string parent_prefix;
1301 root->BuildParentPrefix (parent_prefix);
1302 err.SetErrorStringWithFormat ("Cannot find match for '%s.%s'\n", parent_prefix.c_str(), search_name);
1303 return;
1304 }
1305 }
1306}
1307
1308void
Caroline Tice73fd2722011-02-04 00:16:49 +00001309UserSettingsController::SearchAllSettingsDescriptions (CommandInterpreter &interpreter,
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001310 UserSettingsControllerSP root,
Caroline Tice73fd2722011-02-04 00:16:49 +00001311 std::string &current_prefix,
1312 const char *search_word,
1313 StreamString &result_stream)
1314{
1315 if ((search_word == NULL) || (strlen (search_word) == 0))
1316 return;
1317
1318 int num_entries = root->m_settings.global_settings.size();
1319
1320 if (num_entries > 0)
1321 {
1322 for (int i = 0; i < num_entries; ++i)
1323 {
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001324 const SettingEntry &entry = root->m_settings.global_settings[i];
Caroline Tice73fd2722011-02-04 00:16:49 +00001325 if (strcasestr (entry.description, search_word) != NULL)
1326 {
1327 StreamString var_name;
1328 if (current_prefix.size() > 0)
1329 var_name.Printf ("%s.%s", current_prefix.c_str(), entry.var_name);
1330 else
1331 var_name.Printf ("%s", entry.var_name);
1332 interpreter.OutputFormattedHelpText (result_stream, var_name.GetData(), "--", entry.description,
1333 var_name.GetSize());
1334 }
1335 }
1336 }
1337
1338 num_entries = root->m_settings.instance_settings.size();
1339 if (num_entries > 0)
1340 {
1341 for (int i = 0; i < num_entries; ++i)
1342 {
1343 SettingEntry &entry = root->m_settings.instance_settings[i];
1344 if (strcasestr (entry.description, search_word) != NULL)
1345 {
1346 StreamString var_name;
1347 if (current_prefix.size() > 0)
1348 var_name.Printf ("%s.%s", current_prefix.c_str(), entry.var_name);
1349 else
1350 var_name.Printf ("%s", entry.var_name);
1351 interpreter.OutputFormattedHelpText (result_stream, var_name.GetData(), "--", entry.description,
1352 var_name.GetSize());
1353 }
1354 }
1355 }
1356
1357 int num_children = root->GetNumChildren ();
1358 for (int i = 0; i < num_children; ++i)
1359 {
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001360 UserSettingsControllerSP child = root->GetChildAtIndex (i);
Caroline Tice73fd2722011-02-04 00:16:49 +00001361
1362 if (child)
1363 {
1364 ConstString child_prefix = child->GetLevelName();
1365 StreamString new_prefix;
1366 if (! current_prefix.empty())
1367 new_prefix.Printf ("%s.%s", current_prefix.c_str(), child_prefix.AsCString());
1368 else
1369 new_prefix.Printf ("%s", child_prefix.AsCString());
1370 std::string new_prefix_str = new_prefix.GetData();
1371 UserSettingsController::SearchAllSettingsDescriptions (interpreter, child, new_prefix_str, search_word,
1372 result_stream);
1373 }
1374 }
1375}
1376
1377void
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001378UserSettingsController::GetAllVariableValues (CommandInterpreter &interpreter,
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001379 UserSettingsControllerSP root,
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001380 std::string &current_prefix,
1381 StreamString &result_stream,
1382 Error &err)
1383{
1384 StreamString description;
1385 int num_entries = root->m_settings.global_settings.size();
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001386 SettableVariableType var_type;
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001387
1388
1389 for (int i = 0; i < num_entries; ++i)
1390 {
1391 StreamString full_var_name;
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001392 const SettingEntry &entry = root->m_settings.global_settings[i];
Caroline Ticeded2fa32010-09-15 05:35:14 +00001393 if (! current_prefix.empty())
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001394 full_var_name.Printf ("%s.%s", current_prefix.c_str(), entry.var_name);
1395 else
1396 full_var_name.Printf ("%s", entry.var_name);
Caroline Tice101c7c22010-09-09 06:25:08 +00001397 StringList value = root->GetVariable (full_var_name.GetData(), var_type,
Caroline Ticedaccaa92010-09-20 20:44:43 +00001398 interpreter.GetDebugger().GetInstanceName().AsCString(), err);
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001399 description.Clear();
1400 if (value.GetSize() == 1)
Caroline Tice49e27372010-09-07 18:35:40 +00001401 description.Printf ("%s (%s) = '%s'", full_var_name.GetData(), GetTypeString (entry.var_type),
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001402 value.GetStringAtIndex (0));
1403 else
1404 {
Caroline Tice2d5289d2010-12-10 00:26:54 +00001405 description.Printf ("%s (%s):\n", full_var_name.GetData(), GetTypeString (entry.var_type));
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001406 for (int j = 0; j < value.GetSize(); ++j)
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001407 if (entry.var_type == eSetVarTypeArray)
Caroline Tice2d5289d2010-12-10 00:26:54 +00001408 description.Printf (" [%d]: '%s'\n", j, value.GetStringAtIndex (j));
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001409 else if (entry.var_type == eSetVarTypeDictionary)
Caroline Tice2d5289d2010-12-10 00:26:54 +00001410 description.Printf (" '%s'\n", value.GetStringAtIndex (j));
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001411 }
1412
1413 result_stream.Printf ("%s\n", description.GetData());
1414 }
1415
1416 root->GetAllInstanceVariableValues (interpreter, result_stream);
1417 root->GetAllPendingSettingValues (result_stream);
Caroline Tice101c7c22010-09-09 06:25:08 +00001418 if (root->GetLevelName().GetLength() > 0) // Don't bother with default values for Debugger level.
1419 root->GetAllDefaultSettingValues (result_stream);
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001420
1421
1422 // Now, recurse across all children.
1423 int num_children = root->GetNumChildren();
1424 for (int i = 0; i < num_children; ++i)
1425 {
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001426 UserSettingsControllerSP child = root->GetChildAtIndex (i);
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001427
1428 if (child)
1429 {
1430 ConstString child_prefix = child->GetLevelName();
1431 StreamString new_prefix;
Caroline Ticeded2fa32010-09-15 05:35:14 +00001432 if (! current_prefix.empty())
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001433 new_prefix.Printf ("%s.%s", current_prefix.c_str(), child_prefix.AsCString());
1434 else
1435 new_prefix.Printf ("%s", child_prefix.AsCString());
1436 std::string new_prefix_str = new_prefix.GetData();
1437 UserSettingsController::GetAllVariableValues (interpreter, child, new_prefix_str, result_stream,
1438 err);
1439 }
1440 }
1441
1442}
1443
1444Args
1445UserSettingsController::BreakNameIntoPieces (const char *full_dot_name)
1446{
1447 Args return_value;
1448 std::string name_string (full_dot_name);
1449 bool done = false;
1450
1451 std::string piece;
1452 std::string remainder (full_dot_name);
1453
1454 while (!done)
1455 {
1456 size_t idx = remainder.find_first_of ('.');
1457 piece = remainder.substr (0, idx);
1458 return_value.AppendArgument (piece.c_str());
1459 if (idx != std::string::npos)
1460 remainder = remainder.substr (idx+1);
1461 else
1462 done = true;
1463 }
1464
1465 return return_value;
1466}
1467
1468bool
1469UserSettingsController::IsLiveInstance (const std::string &instance_name)
1470{
1471 std::map<std::string, InstanceSettings *>::iterator pos;
1472
1473 pos = m_live_settings.find (instance_name);
1474 if (pos != m_live_settings.end())
1475 return true;
1476
1477 return false;
1478}
1479
1480int
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001481UserSettingsController::CompleteSettingsValue (UserSettingsControllerSP root_settings,
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001482 const char *full_dot_name,
1483 const char *partial_value,
1484 bool &word_complete,
1485 StringList &matches)
1486{
1487 Args names = UserSettingsController::BreakNameIntoPieces (full_dot_name);
1488 int num_pieces = names.GetArgumentCount();
1489 word_complete = true;
1490
1491 ConstString root_level = root_settings->GetLevelName();
1492 int num_extra_levels = num_pieces - 2;
1493 if ((num_extra_levels > 0)
1494 && root_level.GetLength() > 0)
1495 {
1496 ConstString current_level (names.GetArgumentAtIndex (0));
1497 if (current_level == root_level)
1498 {
1499 names.Shift();
1500 --num_extra_levels;
1501 }
1502 else
1503 return 0;
1504 }
1505
1506 for (int i = 0; i < num_extra_levels; ++i)
1507 {
1508 ConstString child_level (names.GetArgumentAtIndex (0));
1509 bool found = false;
1510 int num_children = root_settings->GetNumChildren();
1511 for (int j = 0; j < num_children && !found; ++j)
1512 {
1513 if (root_settings->GetChildAtIndex (j)->GetLevelName() == child_level)
1514 {
1515 found = true;
1516 root_settings = root_settings->GetChildAtIndex (j);
1517 names.Shift();
1518 }
1519 }
1520 if (!found)
1521 return 0;
1522 }
1523
1524 if (names.GetArgumentCount() != 2)
1525 return 0;
1526
1527 std::string next_name (names.GetArgumentAtIndex (0));
1528 int len = next_name.length();
1529 names.Shift();
1530
1531 if ((next_name[0] == '[') && (next_name[len-1] == ']'))
1532 {
1533 // 'next_name' is instance name. Instance names are irrelevent here.
1534 }
1535 else
1536 {
1537 // 'next_name' is child name.
1538 bool found = false;
1539 int num_children = root_settings->GetNumChildren();
1540 ConstString child_level (next_name.c_str());
1541 for (int j = 0; j < num_children && !found; ++j)
1542 {
1543 if (root_settings->GetChildAtIndex (j)->GetLevelName() == child_level)
1544 {
1545 found = true;
1546 root_settings = root_settings->GetChildAtIndex (j);
1547 }
1548 }
1549 if (!found)
1550 return 0;
1551 }
1552
1553 ConstString var_name (names.GetArgumentAtIndex(0));
1554 const SettingEntry *entry = root_settings->GetGlobalEntry (var_name);
1555 if (entry == NULL)
1556 entry = root_settings->GetInstanceEntry (var_name);
1557
1558 if (entry == NULL)
1559 return 0;
1560
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001561 if (entry->var_type == eSetVarTypeBoolean)
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001562 return UserSettingsController::BooleanMatches (partial_value, word_complete, matches);
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001563 else if (entry->var_type == eSetVarTypeEnum)
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001564 return UserSettingsController::EnumMatches (partial_value, entry->enum_values, word_complete, matches);
1565 else
1566 return 0;
1567}
1568
1569int
1570UserSettingsController::BooleanMatches (const char *partial_value,
1571 bool &word_complete,
1572 StringList &matches)
1573{
1574 static const std::string true_string ("true");
1575 static const std::string false_string ("false");
1576
1577 if (partial_value == NULL)
1578 {
1579 matches.AppendString ("true");
1580 matches.AppendString ("false");
1581 }
1582 else
1583 {
1584 int partial_len = strlen (partial_value);
1585
1586 if ((partial_len <= true_string.length())
1587 && (true_string.find (partial_value) == 0))
1588 matches.AppendString ("true");
1589 else if ((partial_len <= false_string.length())
1590 && (false_string.find (partial_value) == 0))
1591 matches.AppendString ("false");
1592 }
1593
1594 word_complete = false;
1595 if (matches.GetSize() == 1)
1596 word_complete = true;
1597
1598 return matches.GetSize();
1599}
1600
1601int
1602UserSettingsController::EnumMatches (const char *partial_value,
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001603 OptionEnumValueElement *enum_values,
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001604 bool &word_complete,
1605 StringList &matches)
1606{
1607 int len = (partial_value != NULL) ? strlen (partial_value) : 0;
1608
1609 int i = 0;
1610 while (enum_values[i].string_value != NULL)
1611 {
1612 if (len == 0)
1613 matches.AppendString (enum_values[i].string_value);
1614 else
1615 {
1616 std::string tmp_value (enum_values[i].string_value);
1617 if ((len <= tmp_value.length())
1618 && tmp_value.find (partial_value) == 0)
1619 matches.AppendString (enum_values[i].string_value);
1620 }
1621 ++i;
1622 }
1623
1624 word_complete = false;
1625 if (matches.GetSize() == 1)
1626 word_complete = true;
1627
1628 return matches.GetSize();
1629}
1630
1631int
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001632UserSettingsController::CompleteSettingsNames (UserSettingsControllerSP root_settings,
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001633 Args &partial_setting_name_pieces,
1634 bool &word_complete,
1635 StringList &matches)
1636{
1637 int num_matches = 0;
1638 int num_name_pieces = partial_setting_name_pieces.GetArgumentCount();
1639
1640 if (num_name_pieces > 1)
1641 {
1642 // There are at least two pieces, perhaps with multiple level names preceding them.
1643 // First traverse all the extra levels, until we have exactly two pieces left.
1644
1645 int num_extra_levels = num_name_pieces - 2;
1646
1647 // Deal with current level first.
1648
1649 ConstString root_level = root_settings->GetLevelName();
1650 if ((num_extra_levels > 0)
1651 && (root_level.GetLength() > 0))
1652 {
1653 ConstString current_level (partial_setting_name_pieces.GetArgumentAtIndex (0));
1654 if (current_level == root_level)
1655 {
1656 partial_setting_name_pieces.Shift();
1657 --num_extra_levels;
1658 }
1659 else
1660 return 0; // The current level did not match the name pieces; something is wrong, so return immediately
1661
1662 }
1663
1664 for (int i = 0; i < num_extra_levels; ++i)
1665 {
1666 ConstString child_level (partial_setting_name_pieces.GetArgumentAtIndex (0));
1667 bool found = false;
1668 int num_children = root_settings->GetNumChildren();
1669 for (int j = 0; j < num_children && !found; ++j)
1670 {
1671 if (root_settings->GetChildAtIndex (j)->GetLevelName() == child_level)
1672 {
1673 found = true;
1674 root_settings = root_settings->GetChildAtIndex (j);
1675 partial_setting_name_pieces.Shift();
1676 }
1677 }
1678 if (! found)
1679 {
1680 return 0; // Unable to find a matching child level name; something is wrong, so return immediately.
1681 }
1682 }
1683
1684 // Now there should be exactly two name pieces left. If not there is an error, so return immediately
1685
1686 if (partial_setting_name_pieces.GetArgumentCount() != 2)
1687 return 0;
1688
1689 std::string next_name (partial_setting_name_pieces.GetArgumentAtIndex (0));
1690 int len = next_name.length();
1691 partial_setting_name_pieces.Shift();
1692
1693 if ((next_name[0] == '[') && (next_name[len-1] == ']'))
1694 {
1695 // 'next_name' is an instance name. The last name piece must be a non-empty partial match against an
1696 // instance_name, assuming 'next_name' is valid.
1697
1698 if (root_settings->IsLiveInstance (next_name))
1699 {
1700 std::string complete_prefix;
1701 root_settings->BuildParentPrefix (complete_prefix);
1702
1703 num_matches = root_settings->InstanceVariableMatches(partial_setting_name_pieces.GetArgumentAtIndex(0),
1704 complete_prefix,
1705 next_name.c_str(),
1706 matches);
1707 word_complete = true;
1708 if (num_matches > 1)
1709 word_complete = false;
1710
1711 return num_matches;
1712 }
1713 else
1714 return 0; // Invalid instance_name
1715 }
1716 else
1717 {
1718 // 'next_name' must be a child name. Find the correct child and pass the remaining piece to be resolved.
1719 bool found = false;
1720 int num_children = root_settings->GetNumChildren();
1721 ConstString child_level (next_name.c_str());
1722 for (int i = 0; i < num_children; ++i)
1723 {
1724 if (root_settings->GetChildAtIndex (i)->GetLevelName() == child_level)
1725 {
1726 found = true;
1727 return UserSettingsController::CompleteSettingsNames (root_settings->GetChildAtIndex (i),
1728 partial_setting_name_pieces,
1729 word_complete, matches);
1730 }
1731 }
1732 if (!found)
1733 return 0;
1734 }
1735 }
1736 else if (num_name_pieces == 1)
1737 {
1738 std::string complete_prefix;
1739 root_settings->BuildParentPrefix (complete_prefix);
1740
1741 word_complete = true;
1742 std::string name (partial_setting_name_pieces.GetArgumentAtIndex (0));
1743
1744 if (name[0] == '[')
1745 {
1746 // It's a partial instance name.
1747
1748 num_matches = root_settings->LiveInstanceMatches (name.c_str(), complete_prefix, word_complete, matches);
1749 }
1750 else
1751 {
1752 // It could be anything *except* an instance name...
1753
1754 num_matches = root_settings->GlobalVariableMatches (name.c_str(), complete_prefix, matches);
1755 num_matches += root_settings->InstanceVariableMatches (name.c_str(), complete_prefix, NULL, matches);
1756 num_matches += root_settings->ChildMatches (name.c_str(), complete_prefix, word_complete, matches);
1757 }
1758
1759 if (num_matches > 1)
1760 word_complete = false;
1761
1762 return num_matches;
1763 }
1764 else
1765 {
1766 // We have a user settings controller with a blank partial string. Return everything possible at this level.
1767
1768 std::string complete_prefix;
1769 root_settings->BuildParentPrefix (complete_prefix);
1770 num_matches = root_settings->GlobalVariableMatches (NULL, complete_prefix, matches);
1771 num_matches += root_settings->InstanceVariableMatches (NULL, complete_prefix, NULL, matches);
1772 num_matches += root_settings->LiveInstanceMatches (NULL, complete_prefix, word_complete, matches);
1773 num_matches += root_settings->ChildMatches (NULL, complete_prefix, word_complete, matches);
1774 word_complete = false;
1775 return num_matches;
1776 }
1777
1778 return num_matches;
1779}
1780
1781int
1782UserSettingsController::GlobalVariableMatches (const char *partial_name,
1783 const std::string &complete_prefix,
1784 StringList &matches)
1785{
1786 int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0;
1787 int num_matches = 0;
1788
1789 for (size_t i = 0; i < m_settings.global_settings.size(); ++i)
1790 {
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001791 const SettingEntry &entry = m_settings.global_settings[i];
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001792 std::string var_name (entry.var_name);
1793 if ((partial_len == 0)
1794 || ((partial_len <= var_name.length())
1795 && (var_name.find (partial_name) == 0)))
1796 {
1797 StreamString match_name;
1798 if (complete_prefix.length() > 0)
1799 {
1800 match_name.Printf ("%s.%s", complete_prefix.c_str(), var_name.c_str());
1801 matches.AppendString (match_name.GetData());
1802 }
1803 else
1804 matches.AppendString (var_name.c_str());
1805 ++num_matches;
1806 }
1807 }
1808 return num_matches;
1809}
1810
1811int
1812UserSettingsController::InstanceVariableMatches (const char *partial_name,
1813 const std::string &complete_prefix,
1814 const char *instance_name,
1815 StringList &matches)
1816{
1817 int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0;
1818 int num_matches = 0;
1819
1820 for (size_t i = 0; i < m_settings.instance_settings.size(); ++i)
1821 {
1822 SettingEntry &entry = m_settings.instance_settings[i];
1823 std::string var_name (entry.var_name);
1824 if ((partial_len == 0)
1825 || ((partial_len <= var_name.length())
1826 && (var_name.find (partial_name) == 0)))
1827 {
1828 StreamString match_name;
1829 if (complete_prefix.length() > 0)
1830 {
1831 if (instance_name != NULL)
1832 match_name.Printf ("%s.%s.%s", complete_prefix.c_str(), instance_name, var_name.c_str());
1833 else
1834 match_name.Printf ("%s.%s", complete_prefix.c_str(), var_name.c_str());
1835
1836 matches.AppendString (match_name.GetData());
1837 }
1838 else
1839 {
1840 if (instance_name != NULL)
1841 {
1842 match_name.Printf ("%s.%s", instance_name, var_name.c_str());
1843 matches.AppendString (match_name.GetData());
1844 }
1845 else
1846 matches.AppendString (var_name.c_str());
1847 }
1848 ++num_matches;
1849 }
1850 }
1851 return num_matches;
1852}
1853
1854int
1855UserSettingsController::LiveInstanceMatches (const char *partial_name,
1856 const std::string &complete_prefix,
1857 bool &word_complete,
1858 StringList &matches)
1859{
1860 int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0;
1861 int num_matches = 0;
1862
1863 std::map<std::string, InstanceSettings*>::iterator pos;
1864 for (pos = m_live_settings.begin(); pos != m_live_settings.end(); ++pos)
1865 {
1866 std::string instance_name = pos->first;
1867 if ((partial_len == 0)
1868 || ((partial_len <= instance_name.length())
1869 && (instance_name.find (partial_name) == 0)))
1870 {
1871 StreamString match_name;
1872 if (complete_prefix.length() > 0)
1873 match_name.Printf ("%s.%s.", complete_prefix.c_str(), instance_name.c_str());
1874 else
1875 match_name.Printf ("%s.", instance_name.c_str());
1876 matches.AppendString (match_name.GetData());
1877 ++num_matches;
1878 }
1879 }
1880
1881 if (num_matches > 0)
1882 word_complete = false;
1883
1884 return num_matches;
1885}
1886
1887int
1888UserSettingsController::ChildMatches (const char *partial_name,
1889 const std::string &complete_prefix,
1890 bool &word_complete,
1891 StringList &matches)
1892{
1893 int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0;
1894 int num_children = GetNumChildren();
1895 int num_matches = 0;
1896 for (int i = 0; i < num_children; ++i)
1897 {
1898 std::string child_name (GetChildAtIndex(i)->GetLevelName().AsCString());
1899 StreamString match_name;
1900 if ((partial_len == 0)
1901 || ((partial_len <= child_name.length())
1902 && (child_name.find (partial_name) == 0)))
1903 {
1904 if (complete_prefix.length() > 0)
1905 match_name.Printf ("%s.%s.", complete_prefix.c_str(), child_name.c_str());
1906 else
1907 match_name.Printf ("%s.", child_name.c_str());
1908 matches.AppendString (match_name.GetData());
1909 ++num_matches;
1910 }
1911 }
1912
1913 if (num_matches > 0)
1914 word_complete = false;
1915
1916 return num_matches;
1917}
1918
1919void
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001920UserSettingsController::VerifyOperationForType (SettableVariableType var_type,
1921 VarSetOperationType op,
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001922 const ConstString &var_name,
1923 Error &err)
1924{
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001925 if (op == eVarSetOperationAssign)
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001926 return;
1927
1928
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001929 if (op == eVarSetOperationInvalid)
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001930 {
1931 err.SetErrorString ("Invalid 'settings ' subcommand operation.\n");
1932 return;
1933 }
1934
1935 switch (op)
1936 {
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001937 case eVarSetOperationInsertBefore:
1938 case eVarSetOperationInsertAfter:
1939 if (var_type != eSetVarTypeArray)
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001940 err.SetErrorString ("Invalid operation: This operation can only be performed on array variables.\n");
1941 break;
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001942 case eVarSetOperationReplace:
1943 case eVarSetOperationRemove:
1944 if ((var_type != eSetVarTypeArray)
1945 && (var_type != eSetVarTypeDictionary))
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001946 err.SetErrorString ("Invalid operation: This operation can only be performed on array or dictionary"
1947 " variables.\n");
1948 break;
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001949 case eVarSetOperationAppend:
1950 case eVarSetOperationClear:
1951 if ((var_type != eSetVarTypeArray)
1952 && (var_type != eSetVarTypeDictionary)
1953 && (var_type != eSetVarTypeString))
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001954 err.SetErrorString ("Invalid operation: This operation can only be performed on array, dictionary "
1955 "or string variables.\n");
1956 break;
1957 default:
1958 break;
1959 }
1960
1961 return;
1962}
1963
1964void
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001965UserSettingsController::UpdateStringVariable (VarSetOperationType op,
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001966 std::string &string_var,
1967 const char *new_value,
1968 Error &err)
1969{
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001970 if (op == eVarSetOperationAssign)
Greg Claytonbd82a5d2011-01-23 05:56:20 +00001971 {
1972 if (new_value && new_value[0])
1973 string_var.assign (new_value);
1974 else
1975 string_var.clear();
1976 }
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001977 else if (op == eVarSetOperationAppend)
Greg Claytonbd82a5d2011-01-23 05:56:20 +00001978 {
1979 if (new_value && new_value[0])
1980 string_var.append (new_value);
1981 }
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001982 else if (op == eVarSetOperationClear)
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001983 string_var.clear();
1984 else
1985 err.SetErrorString ("Unrecognized operation. Cannot update value.\n");
1986}
1987
1988void
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001989UserSettingsController::UpdateBooleanVariable (VarSetOperationType op,
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001990 bool &bool_var,
1991 const char *new_value,
1992 Error &err)
1993{
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00001994 if (op != eVarSetOperationAssign)
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001995 err.SetErrorString ("Invalid operation for Boolean variable. Cannot update value.\n");
1996
Greg Claytonbd82a5d2011-01-23 05:56:20 +00001997 if (new_value && new_value[0])
1998 {
1999 if ((::strcasecmp(new_value, "true") == 0) ||
2000 (::strcasecmp(new_value, "yes") == 0) ||
2001 (::strcasecmp(new_value, "on") == 0) ||
2002 (::strcasecmp(new_value, "1") == 0))
2003 bool_var = true;
2004 else
2005 if ((::strcasecmp(new_value, "false") == 0) ||
2006 (::strcasecmp(new_value, "no") == 0) ||
2007 (::strcasecmp(new_value, "off") == 0) ||
2008 (::strcasecmp(new_value, "0") == 0))
2009 bool_var = false;
2010 else
2011 err.SetErrorStringWithFormat ("Invalid boolean value '%s'\n", new_value);
2012 }
2013 else
2014 err.SetErrorString ("Invalid value. Cannot perform update.\n");
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002015
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002016}
2017
2018void
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00002019UserSettingsController::UpdateStringArrayVariable (VarSetOperationType op,
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002020 const char *index_value,
2021 Args &array_var,
2022 const char *new_value,
2023 Error &err)
2024{
2025 int index = -1;
2026 bool valid_index = true;
2027
2028 if (index_value != NULL)
2029 {
2030 for (int i = 0; i < strlen(index_value); ++i)
2031 if (!isdigit (index_value[i]))
2032 {
2033 valid_index = false;
2034 err.SetErrorStringWithFormat ("'%s' is not a valid integer index. Cannot update array value.\n",
2035 index_value);
2036 }
2037
2038 if (valid_index)
2039 index = atoi (index_value);
2040
2041 if (index < 0
2042 || index >= array_var.GetArgumentCount())
2043 {
2044 valid_index = false;
2045 err.SetErrorStringWithFormat ("%d is outside the bounds of the specified array variable. "
2046 "Cannot update array value.\n", index);
2047 }
2048 }
2049
2050 switch (op)
2051 {
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00002052 case eVarSetOperationAssign:
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002053 array_var.SetCommandString (new_value);
2054 break;
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00002055 case eVarSetOperationReplace:
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002056 {
2057 if (valid_index)
2058 array_var.ReplaceArgumentAtIndex (index, new_value);
2059 break;
2060 }
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00002061 case eVarSetOperationInsertBefore:
2062 case eVarSetOperationInsertAfter:
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002063 {
2064 if (valid_index)
2065 {
2066 Args new_array (new_value);
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00002067 if (op == eVarSetOperationInsertAfter)
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002068 ++index;
2069 for (int i = 0; i < new_array.GetArgumentCount(); ++i)
2070 array_var.InsertArgumentAtIndex (index, new_array.GetArgumentAtIndex (i));
2071 }
2072 break;
2073 }
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00002074 case eVarSetOperationRemove:
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002075 {
2076 if (valid_index)
2077 array_var.DeleteArgumentAtIndex (index);
2078 break;
2079 }
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00002080 case eVarSetOperationAppend:
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002081 {
2082 Args new_array (new_value);
2083 array_var.AppendArguments (new_array);
2084 break;
2085 }
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00002086 case eVarSetOperationClear:
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002087 array_var.Clear();
2088 break;
2089 default:
2090 err.SetErrorString ("Unrecognized operation. Cannot update value.\n");
2091 break;
2092 }
2093}
2094
2095void
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00002096UserSettingsController::UpdateDictionaryVariable (VarSetOperationType op,
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002097 const char *index_value,
2098 std::map<std::string, std::string> &dictionary,
2099 const char *new_value,
2100 Error &err)
2101{
2102 switch (op)
2103 {
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00002104 case eVarSetOperationReplace:
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002105 if (index_value != NULL)
2106 {
2107 std::string key (index_value);
2108 std::map<std::string, std::string>::iterator pos;
2109
2110 pos = dictionary.find (key);
2111 if (pos != dictionary.end())
2112 dictionary[key] = new_value;
2113 else
2114 err.SetErrorStringWithFormat ("'%s' is not an existing key; cannot replace value.\n", index_value);
2115 }
2116 else
2117 err.SetErrorString ("'settings replace' requires a key for dictionary variables. No key supplied.\n");
2118 break;
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00002119 case eVarSetOperationRemove:
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002120 if (index_value != NULL)
2121 {
2122 std::string key (index_value);
2123 dictionary.erase (key);
2124 }
2125 else
2126 err.SetErrorString ("'settings remove' requires a key for dictionary variables. No key supplied.\n");
2127 break;
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00002128 case eVarSetOperationClear:
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002129 dictionary.clear ();
2130 break;
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00002131 case eVarSetOperationAppend:
2132 case eVarSetOperationAssign:
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002133 {
Johnny Chen73b4f712010-10-20 01:03:00 +00002134 // Clear the dictionary if it's an assign with new_value as NULL.
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00002135 if (new_value == NULL && op == eVarSetOperationAssign)
Johnny Chen73b4f712010-10-20 01:03:00 +00002136 {
2137 dictionary.clear ();
2138 break;
2139 }
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002140 Args args (new_value);
2141 size_t num_args = args.GetArgumentCount();
Greg Clayton6ad07dd2010-12-19 03:41:24 +00002142 RegularExpression regex("(\\[\"?)?" // Regex match 1 (optional key prefix of '["' pr '[')
2143 "([A-Za-z_][A-Za-z_0-9]*)" // Regex match 2 (key string)
2144 "(\"?\\])?" // Regex match 3 (optional key suffix of '"]' pr ']')
2145 "=" // The equal sign that is required
2146 "(.*)"); // Regex match 4 (value string)
2147 std::string key, value;
2148
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002149 for (size_t i = 0; i < num_args; ++i)
2150 {
Greg Clayton6ad07dd2010-12-19 03:41:24 +00002151 const char *key_equal_value_arg = args.GetArgumentAtIndex (i);
2152 // Execute the regular expression on each arg.
2153 if (regex.Execute(key_equal_value_arg, 5))
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002154 {
Greg Clayton6ad07dd2010-12-19 03:41:24 +00002155 // The regular expression succeeded. The match at index
2156 // zero will be the entire string that matched the entire
2157 // regular expression. The match at index 1 - 4 will be
2158 // as mentioned above by the creation of the regex pattern.
2159 // Match index 2 is the key, match index 4 is the value.
2160 regex.GetMatchAtIndex (key_equal_value_arg, 2, key);
2161 regex.GetMatchAtIndex (key_equal_value_arg, 4, value);
2162 dictionary[key] = value;
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002163 }
2164 else
Greg Clayton6ad07dd2010-12-19 03:41:24 +00002165 {
2166 err.SetErrorString ("Invalid format for dictionary value. Expected one of '[\"<key>\"]=<value>', '[<key>]=<value>', or '<key>=<value>'\n");
2167 }
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002168 }
2169 }
2170 break;
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00002171 case eVarSetOperationInsertBefore:
2172 case eVarSetOperationInsertAfter:
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002173 err.SetErrorString ("Specified operation cannot be performed on dictionary variables.\n");
2174 break;
2175 default:
2176 err.SetErrorString ("Unrecognized operation.\n");
2177 break;
2178 }
2179}
2180
2181const char *
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00002182UserSettingsController::EnumToString (const OptionEnumValueElement *enum_values,
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002183 int value)
2184{
2185 int i = 0;
2186 while (enum_values[i].string_value != NULL)
2187 {
2188 if (enum_values[i].value == value)
2189 return enum_values[i].string_value;
2190 ++i;
2191 }
2192
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00002193 return "";
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002194}
2195
2196
2197void
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00002198UserSettingsController::UpdateEnumVariable (OptionEnumValueElement *enum_values,
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002199 int *enum_var,
2200 const char *new_value,
2201 Error &err)
2202{
2203 bool found_one;
2204
2205 *enum_var = Args::StringToOptionEnum (new_value, enum_values, enum_values[0].value, &found_one);
2206
2207 if (!found_one)
2208 err.SetErrorString ("Invalid enumeration value; cannot update variable.\n");
2209}
2210
Caroline Ticeded2fa32010-09-15 05:35:14 +00002211void
2212UserSettingsController::RenameInstanceSettings (const char *old_name, const char *new_name)
2213{
2214 Mutex::Locker live_mutex (m_live_settings_mutex);
2215 Mutex::Locker pending_mutex (m_pending_settings_mutex);
2216 std::string old_name_key (old_name);
2217 std::string new_name_key (new_name);
2218
2219 // First, find the live instance settings for the old_name. If they don't exist in the live settings
2220 // list, then this is not a setting that can be renamed.
2221
2222 if ((old_name_key[0] != '[') || (old_name_key[old_name_key.size() -1] != ']'))
Caroline Tice1559a462010-09-27 00:30:10 +00002223 {
Caroline Ticeded2fa32010-09-15 05:35:14 +00002224 StreamString tmp_str;
2225 tmp_str.Printf ("[%s]", old_name);
2226 old_name_key = tmp_str.GetData();
Caroline Tice1559a462010-09-27 00:30:10 +00002227 }
Caroline Ticeded2fa32010-09-15 05:35:14 +00002228
2229 if ((new_name_key[0] != '[') || (new_name_key[new_name_key.size() -1] != ']'))
Caroline Tice1559a462010-09-27 00:30:10 +00002230 {
Caroline Ticeded2fa32010-09-15 05:35:14 +00002231 StreamString tmp_str;
2232 tmp_str.Printf ("[%s]", new_name);
2233 new_name_key = tmp_str.GetData();
Caroline Tice1559a462010-09-27 00:30:10 +00002234 }
2235
2236 if (old_name_key.compare (new_name_key) == 0)
2237 return;
2238
2239 size_t len = new_name_key.length();
2240 std::string stripped_new_name = new_name_key.substr (1, len-2); // new name without the '[ ]'
Caroline Ticeded2fa32010-09-15 05:35:14 +00002241
2242 std::map<std::string, InstanceSettings *>::iterator pos;
2243
2244 pos = m_live_settings.find (old_name_key);
2245 if (pos != m_live_settings.end())
2246 {
2247 InstanceSettings *live_settings = pos->second;
2248
2249 // Rename the settings.
Caroline Tice1559a462010-09-27 00:30:10 +00002250 live_settings->ChangeInstanceName (stripped_new_name);
Caroline Ticeded2fa32010-09-15 05:35:14 +00002251
2252 // Now see if there are any pending settings for the new name; if so, copy them into live_settings.
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00002253 std::map<std::string, InstanceSettingsSP>::iterator pending_pos;
Caroline Ticeded2fa32010-09-15 05:35:14 +00002254 pending_pos = m_pending_settings.find (new_name_key);
2255 if (pending_pos != m_pending_settings.end())
2256 {
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00002257 InstanceSettingsSP pending_settings_sp = pending_pos->second;
Caroline Ticeded2fa32010-09-15 05:35:14 +00002258 live_settings->CopyInstanceSettings (pending_settings_sp, false);
2259 }
2260
2261 // Erase the old entry (under the old name) from live settings.
2262 m_live_settings.erase (pos);
2263
2264 // Add the new entry, with the new name, into live settings.
2265 m_live_settings[new_name_key] = live_settings;
2266 }
2267}
2268
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002269//----------------------------------------------------------------------
2270// class InstanceSettings
2271//----------------------------------------------------------------------
2272
Caroline Tice91123da2010-09-08 17:48:55 +00002273InstanceSettings::InstanceSettings (UserSettingsController &owner, const char *instance_name, bool live_instance) :
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002274 m_owner (owner),
2275 m_instance_name (instance_name)
2276{
Caroline Tice91123da2010-09-08 17:48:55 +00002277 if ((m_instance_name != InstanceSettings::GetDefaultName())
Caroline Tice9e41c152010-09-16 19:05:55 +00002278 && (m_instance_name != InstanceSettings::InvalidName())
Caroline Tice91123da2010-09-08 17:48:55 +00002279 && live_instance)
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002280 m_owner.RegisterInstanceSettings (this);
2281}
2282
2283InstanceSettings::~InstanceSettings ()
2284{
2285 if (m_instance_name != InstanceSettings::GetDefaultName())
2286 m_owner.UnregisterInstanceSettings (this);
2287}
2288
2289const ConstString &
2290InstanceSettings::GetDefaultName ()
2291{
2292 static const ConstString g_default_settings_name ("[DEFAULT]");
2293
2294 return g_default_settings_name;
2295}
Caroline Ticeded2fa32010-09-15 05:35:14 +00002296
Caroline Tice9e41c152010-09-16 19:05:55 +00002297const ConstString &
2298InstanceSettings::InvalidName ()
2299{
2300 static const ConstString g_invalid_name ("Invalid instance name");
2301
2302 return g_invalid_name;
2303}
2304
Caroline Ticeded2fa32010-09-15 05:35:14 +00002305void
2306InstanceSettings::ChangeInstanceName (const std::string &new_instance_name)
2307{
2308 m_instance_name.SetCString (new_instance_name.c_str());
2309}
2310
2311