ComponentFactory.cc Source File

Back to the index.

ComponentFactory.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008-2019 Anders Gavare. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * 3. The name of the author may not be used to endorse or promote products
13  * derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #include <assert.h>
29 #include <string.h>
30 
31 #include "ComponentFactory.h"
32 #include "GXemul.h"
33 #include "StringHelper.h"
34 
35 
37  const char* componentName;
39  string (*GetAttribute)(const string& attributeName);
40 };
41 
42 // Static list of components:
43 // (Note: components*.h is autogenerated by the configure script.)
44 #include "../../components_h.h"
45 static struct ComponentListEntry componentList[] = {
46 #include "../../components.h"
47  { NULL, NULL, NULL }
48 };
49 
50 // List of components that are added dynamically at runtime:
51 static vector<ComponentListEntry>* componentListRunTime = NULL;
52 
53 
55  refcount_ptr<Component> (*createFunc)(const ComponentCreateArgs& args),
56  string (*getAttributeFunc)(const string& attributeName))
57 {
58  // Attempt to create a component using this name first.
59  // Don't add the new component class if the name is already in use.
60  refcount_ptr<Component> component = CreateComponent(name);
61  if (!component.IsNULL()) {
62  assert(false);
63  return false;
64  }
65 
66  if (componentListRunTime == NULL)
67  componentListRunTime = new vector<ComponentListEntry>();
68 
70  cle.componentName = name;
71  cle.Create = createFunc;
72  cle.GetAttribute = getAttributeFunc;
73 
74  componentListRunTime->push_back(cle);
75 
76  return true;
77 }
78 
79 
81 {
82  delete componentListRunTime;
83  componentListRunTime = NULL;
84 }
85 
86 
88  const string& componentNameAndOptionalArgs, GXemul* gxemul)
89 {
91  args.gxemul = gxemul;
92 
93  string componentName = componentNameAndOptionalArgs;
94  size_t p = componentName.find('(');
95  if (p != string::npos && p > 0) {
96  componentName = componentName.substr(0, p);
97 
98  string argstring = componentNameAndOptionalArgs.substr(p+1);
99 
100  // Arguments don't end with a )? Then something's wrong.
101  if (argstring[argstring.length()-1] != ')') {
102  if (gxemul != NULL)
103  gxemul->GetUI()->ShowDebugMessage("Unmatched parenthesis?\n");
104 
105  return NULL;
106  }
107 
108  argstring = argstring.substr(0, argstring.length()-1);
109 
110  // argstring is now e.g. "cpu=R4400,ncpus=4"
111 
112  // Split into assignments:
113  vector<string> assignments = StringHelper::SplitStringIntoVector(argstring, ',');
114 
115  // Split each assignment into key and value:
116  for (size_t i=0; i<assignments.size(); ++i) {
117  vector<string> keyAndValue = StringHelper::SplitStringIntoVector(assignments[i], '=');
118  if (keyAndValue.size() != 2) {
119  if (gxemul != NULL)
120  gxemul->GetUI()->ShowDebugMessage("Not a key=value pair: " + assignments[i]);
121 
122  return NULL;
123  }
124 
125  args.componentCreationSettings[keyAndValue[0]] = keyAndValue[1];
126  }
127  }
128 
129  // Find the className in the list of available components, and
130  // call the corresponding create function, if found:
131  size_t i = 0;
132  while (componentList[i].componentName != NULL) {
133  if (componentName == componentList[i].componentName)
134  return componentList[i].Create(args);
135 
136  ++ i;
137  }
138 
139  for (i=0; componentListRunTime != NULL && i<componentListRunTime->size(); ++i) {
140  if (componentName == (*componentListRunTime)[i].componentName)
141  return (*componentListRunTime)[i].Create(args);
142  }
143 
144  if (gxemul != NULL)
145  gxemul->GetUI()->ShowDebugMessage("Unknown component: " + componentNameAndOptionalArgs + "\n");
146 
147  return NULL;
148 }
149 
150 
152 {
153  // A copy of the default args (for helpful debug output):
154  ComponentCreationSettings defaultSettings = settings;
155 
156  // Merge in the overrides:
157  for (ComponentCreationSettings::const_iterator it = createArgs.componentCreationSettings.begin();
158  it != createArgs.componentCreationSettings.end(); ++it) {
159  const string& key = it->first;
160  const string& value = it->second;
161 
162  if (settings.find(key) == settings.end()) {
163  if (createArgs.gxemul != NULL) {
164  stringstream ss;
165  ss << "Unknown setting '" << key << "'. "
166  "Available settings (with default values) are:\n";
167  for (ComponentCreationSettings::const_iterator it2 = defaultSettings.begin();
168  it2 != defaultSettings.end(); ++it2)
169  ss << " " << it2->first << " = " << it2->second << "\n";
170 
171  createArgs.gxemul->GetUI()->ShowDebugMessage(ss.str());
172  }
173 
174  return false;
175  }
176 
177  settings[key] = value;
178  }
179 
180  return true;
181 }
182 
183 
184 string ComponentFactory::GetAttribute(const string& name,
185  const string& attributeName)
186 {
187  size_t i = 0;
188  while (componentList[i].componentName != NULL) {
189  if (name == componentList[i].componentName)
190  return componentList[i].GetAttribute(attributeName);
191 
192  ++ i;
193  }
194 
195  for (i=0; componentListRunTime!=NULL && i<componentListRunTime->size(); ++i) {
196  if (name == (*componentListRunTime)[i].componentName)
197  return (*componentListRunTime)[i].GetAttribute(
198  attributeName);
199  }
200 
201  return "";
202 }
203 
204 
205 bool ComponentFactory::HasAttribute(const string& name,
206  const string& attributeName)
207 {
208  return !GetAttribute(name, attributeName).empty();
209 }
210 
211 
212 vector<string> ComponentFactory::GetAllComponentNames(bool onlyTemplates)
213 {
214  vector<string> result;
215 
216  size_t i = 0;
217  while (componentList[i].componentName != NULL) {
218  if ((!onlyTemplates ||
219  componentList[i].GetAttribute("template") == "yes"))
220  result.push_back(componentList[i].componentName);
221  ++ i;
222  }
223 
224  for (i=0; componentListRunTime!=NULL && i<componentListRunTime->size(); ++i) {
225  if ((!onlyTemplates ||
226  (*componentListRunTime)[i].GetAttribute("template") == "yes"))
227  result.push_back((*componentListRunTime)[i].componentName);
228  }
229 
230  return result;
231 }
232 
233 
234 /*****************************************************************************/
235 
236 
237 #ifdef WITHUNITTESTS
238 
239 static void Test_ComponentFactory_Nonexistant()
240 {
241  refcount_ptr<Component> component =
243  UnitTest::Assert("nonexistant component should not be created",
244  component.IsNULL() == true);
245 }
246 
247 static void Test_ComponentFactory_SimpleDummy()
248 {
249  refcount_ptr<Component> component =
251  UnitTest::Assert("dummy component should be possible to create",
252  component.IsNULL() == false);
253 
254  UnitTest::Assert("the class name should be 'dummy'",
255  component->GetClassName(), "dummy");
256  UnitTest::Assert("the dummy component should have children",
257  component->GetChildren().size(), 0);
258 }
259 
260 static void Test_ComponentFactory_FromTemplate()
261 {
262  refcount_ptr<Component> component =
264  UnitTest::Assert("component should be possible to create from template",
265  component.IsNULL() == false);
266 
267  UnitTest::Assert("the class name should be 'machine'",
268  component->GetClassName(), "machine");
269  UnitTest::Assert("the component should have children",
270  component->GetChildren().size() > 0);
271 
272  refcount_ptr<Component> clone = component->Clone();
273  UnitTest::Assert("cloning should have been possible",
274  clone.IsNULL() == false);
275 
276  UnitTest::Assert("clone: the class name should still be 'machine'",
277  clone->GetClassName(), "machine");
278  UnitTest::Assert("clone: the clone should also have children",
279  clone->GetChildren().size() > 0);
280 }
281 
282 static void Test_ComponentFactory_HasAttribute()
283 {
284  UnitTest::Assert("nonexistantattr should not exist",
285  !ComponentFactory::HasAttribute("testm88k", "nonexistantattr"));
286 
287  UnitTest::Assert("testm88k is a machine",
288  ComponentFactory::HasAttribute("testm88k", "machine"));
289 
290  UnitTest::Assert("testm88k has a description",
291  ComponentFactory::HasAttribute("testm88k", "description"));
292 }
293 
295 {
296  UNITTEST(Test_ComponentFactory_Nonexistant);
297  UNITTEST(Test_ComponentFactory_SimpleDummy);
298  UNITTEST(Test_ComponentFactory_FromTemplate);
299  UNITTEST(Test_ComponentFactory_HasAttribute);
300 }
301 
302 #endif
Component::GetChildren
Components & GetChildren()
Gets pointers to child components.
Definition: Component.cc:674
refcount_ptr::IsNULL
bool IsNULL() const
Checks whether or not an object is referenced by the reference counted pointer.
Definition: refcount_ptr.h:218
ComponentFactory::GetCreationArgOverrides
static bool GetCreationArgOverrides(ComponentCreationSettings &settings, const ComponentCreateArgs &createArgs)
Get override arguments for component creation.
Definition: ComponentFactory.cc:151
ComponentFactory.h
GXemul
The main emulator class.
Definition: GXemul.h:55
StringHelper::SplitStringIntoVector
static vector< string > SplitStringIntoVector(const string &str, const char splitter)
Splits a string with a certain delimiter into a vector of strings.
Definition: StringHelper.cc:99
ComponentListEntry::GetAttribute
string(* GetAttribute)(const string &attributeName)
Definition: ComponentFactory.cc:39
refcount_ptr< Component >
ComponentFactory::GetAllComponentNames
static vector< string > GetAllComponentNames(bool onlyTemplates)
Returns a vector of all available component names.
Definition: ComponentFactory.cc:212
UNITTESTS
#define UNITTESTS(class)
Helper for unit test case execution.
Definition: UnitTest.h:184
ComponentFactory::RegisterComponentClass
static bool RegisterComponentClass(const char *name, refcount_ptr< Component >(*createFunc)(const ComponentCreateArgs &args), string(*getAttributeFunc)(const string &attributeName))
Adds a new component class to the factory at runtime.
Definition: ComponentFactory.cc:54
ComponentFactory
A factory which creates Component objects.
Definition: ComponentFactory.h:61
UNITTEST
#define UNITTEST(functionname)
Helper for unit test case execution.
Definition: UnitTest.h:217
ComponentFactory::UnregisterAllComponentClasses
static void UnregisterAllComponentClasses()
Unregisters all manually registered component classes.
Definition: ComponentFactory.cc:80
UnitTest::Assert
static void Assert(const string &strFailMessage, bool condition)
Asserts that a boolean condition is correct.
Definition: UnitTest.cc:40
UI::ShowDebugMessage
virtual void ShowDebugMessage(const string &msg)=0
Shows a debug message.
Component::GetClassName
string GetClassName() const
Gets the class name of the component.
Definition: Component.cc:54
ComponentListEntry::componentName
const char * componentName
Definition: ComponentFactory.cc:37
ComponentFactory::CreateComponent
static refcount_ptr< Component > CreateComponent(const string &componentNameAndOptionalArgs, GXemul *gxemul=NULL)
Creates a component given a short component name.
Definition: ComponentFactory.cc:87
StringHelper.h
ComponentCreateArgs::gxemul
GXemul * gxemul
Definition: Component.h:50
settings
Definition: settings.cc:57
ComponentFactory::GetAttribute
static string GetAttribute(const string &name, const string &attributeName)
Gets a specific attribute value for a component.
Definition: ComponentFactory.cc:184
ComponentCreationSettings
map< string, string > ComponentCreationSettings
Definition: Component.h:46
GXemul::GetUI
UI * GetUI()
Gets a pointer to the GXemul instance' active UI.
Definition: GXemul.cc:653
ComponentFactory::HasAttribute
static bool HasAttribute(const string &name, const string &attributeName)
Checks if a component has a specific attribute.
Definition: ComponentFactory.cc:205
ComponentCreateArgs::componentCreationSettings
ComponentCreationSettings componentCreationSettings
Definition: Component.h:51
Component::Clone
refcount_ptr< Component > Clone() const
Clones the component and all its children.
Definition: Component.cc:76
ComponentListEntry
Definition: ComponentFactory.cc:36
ComponentCreateArgs
Definition: Component.h:49
GXemul.h
ComponentListEntry::Create
refcount_ptr< Component >(* Create)(const ComponentCreateArgs &args)
Definition: ComponentFactory.cc:38

Generated on Tue Aug 25 2020 19:25:06 for GXemul by doxygen 1.8.18