ComponentFactory.cc Source File

Back to the index.

ComponentFactory.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008-2010 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 #ifndef UNSTABLE_DEVEL
135  && !componentList[i].GetAttribute("stable").empty()
136 #endif
137  )
138  return componentList[i].Create(args);
139 
140  ++ i;
141  }
142 
143  for (i=0; componentListRunTime != NULL && i<componentListRunTime->size(); ++i) {
144  if (componentName == (*componentListRunTime)[i].componentName
145 #ifndef UNSTABLE_DEVEL
146  && !(*componentListRunTime)[i].GetAttribute("stable").empty()
147 #endif
148  )
149  return (*componentListRunTime)[i].Create(args);
150  }
151 
152  return NULL;
153 }
154 
155 
157 {
158  // A copy of the default args (for helpful debug output):
159  ComponentCreationSettings defaultSettings = settings;
160 
161  // Merge in the overrides:
162  for (ComponentCreationSettings::const_iterator it = createArgs.componentCreationSettings.begin();
163  it != createArgs.componentCreationSettings.end(); ++it) {
164  const string& key = it->first;
165  const string& value = it->second;
166 
167  if (settings.find(key) == settings.end()) {
168  if (createArgs.gxemul != NULL) {
169  stringstream ss;
170  ss << "Unknown setting '" << key << "'. "
171  "Available settings (with default values) are:\n";
172  for (ComponentCreationSettings::const_iterator it2 = defaultSettings.begin();
173  it2 != defaultSettings.end(); ++it2)
174  ss << " " << it2->first << " = " << it2->second << "\n";
175 
176  createArgs.gxemul->GetUI()->ShowDebugMessage(ss.str());
177  }
178 
179  return false;
180  }
181 
182  settings[key] = value;
183  }
184 
185  return true;
186 }
187 
188 
189 string ComponentFactory::GetAttribute(const string& name,
190  const string& attributeName)
191 {
192  size_t i = 0;
193  while (componentList[i].componentName != NULL) {
194  if (name == componentList[i].componentName)
195  return componentList[i].GetAttribute(attributeName);
196 
197  ++ i;
198  }
199 
200  for (i=0; componentListRunTime!=NULL && i<componentListRunTime->size(); ++i) {
201  if (name == (*componentListRunTime)[i].componentName)
202  return (*componentListRunTime)[i].GetAttribute(
203  attributeName);
204  }
205 
206  return "";
207 }
208 
209 
210 bool ComponentFactory::HasAttribute(const string& name,
211  const string& attributeName)
212 {
213  return !GetAttribute(name, attributeName).empty();
214 }
215 
216 
217 vector<string> ComponentFactory::GetAllComponentNames(bool onlyTemplates)
218 {
219  vector<string> result;
220 
221  size_t i = 0;
222  while (componentList[i].componentName != NULL) {
223  if ((!onlyTemplates ||
224  componentList[i].GetAttribute("template") == "yes")
225 #ifndef UNSTABLE_DEVEL
226  && !componentList[i].GetAttribute("stable").empty()
227 #endif
228  )
229  result.push_back(componentList[i].componentName);
230  ++ i;
231  }
232 
233  for (i=0; componentListRunTime!=NULL && i<componentListRunTime->size(); ++i) {
234  if ((!onlyTemplates ||
235  (*componentListRunTime)[i].GetAttribute("template") == "yes")
236 #ifndef UNSTABLE_DEVEL
237  && !(*componentListRunTime)[i].GetAttribute("stable").empty()
238 #endif
239  )
240  result.push_back((*componentListRunTime)[i].componentName);
241  }
242 
243  return result;
244 }
245 
246 
247 /*****************************************************************************/
248 
249 
250 #ifdef WITHUNITTESTS
251 
252 static void Test_ComponentFactory_Nonexistant()
253 {
254  refcount_ptr<Component> component =
256  UnitTest::Assert("nonexistant component should not be created",
257  component.IsNULL() == true);
258 }
259 
260 static void Test_ComponentFactory_SimpleDummy()
261 {
262  refcount_ptr<Component> component =
264  UnitTest::Assert("dummy component should be possible to create",
265  component.IsNULL() == false);
266 
267  UnitTest::Assert("the class name should be 'dummy'",
268  component->GetClassName(), "dummy");
269  UnitTest::Assert("the dummy component should have children",
270  component->GetChildren().size(), 0);
271 }
272 
273 static void Test_ComponentFactory_FromTemplate()
274 {
275  refcount_ptr<Component> component =
277  UnitTest::Assert("component should be possible to create from template",
278  component.IsNULL() == false);
279 
280  UnitTest::Assert("the class name should be 'machine'",
281  component->GetClassName(), "machine");
282  UnitTest::Assert("the component should have children",
283  component->GetChildren().size() > 0);
284 
285  refcount_ptr<Component> clone = component->Clone();
286  UnitTest::Assert("cloning should have been possible",
287  clone.IsNULL() == false);
288 
289  UnitTest::Assert("clone: the class name should still be 'machine'",
290  clone->GetClassName(), "machine");
291  UnitTest::Assert("clone: the clone should also have children",
292  clone->GetChildren().size() > 0);
293 }
294 
295 static void Test_ComponentFactory_HasAttribute()
296 {
297  UnitTest::Assert("nonexistantattr should not exist",
298  !ComponentFactory::HasAttribute("testm88k", "nonexistantattr"));
299 
300  UnitTest::Assert("testm88k is a machine",
301  ComponentFactory::HasAttribute("testm88k", "machine"));
302 
303  UnitTest::Assert("testm88k is stable",
304  ComponentFactory::HasAttribute("testm88k", "stable"));
305 
306  UnitTest::Assert("testm88k has a description",
307  ComponentFactory::HasAttribute("testm88k", "description"));
308 }
309 
311 {
312  UNITTEST(Test_ComponentFactory_Nonexistant);
313  UNITTEST(Test_ComponentFactory_SimpleDummy);
314  UNITTEST(Test_ComponentFactory_FromTemplate);
315  UNITTEST(Test_ComponentFactory_HasAttribute);
316 }
317 
318 #endif
virtual void ShowDebugMessage(const string &msg)=0
Shows a debug message.
static refcount_ptr< Component > CreateComponent(const string &componentNameAndOptionalArgs, GXemul *gxemul=NULL)
Creates a component given a short component name.
Components & GetChildren()
Gets pointers to child components.
Definition: Component.cc:674
string(* GetAttribute)(const string &attributeName)
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
string GetClassName() const
Gets the class name of the component.
Definition: Component.cc:54
The main emulator class.
Definition: GXemul.h:54
#define UNITTESTS(class)
Helper for unit test case execution.
Definition: UnitTest.h:184
map< string, string > ComponentCreationSettings
Definition: Component.h:46
static bool HasAttribute(const string &name, const string &attributeName)
Checks if a component has a specific attribute.
const char * componentName
static void UnregisterAllComponentClasses()
Unregisters all manually registered component classes.
static vector< string > GetAllComponentNames(bool onlyTemplates)
Returns a vector of all available component names.
A factory which creates Component objects.
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.
static void Assert(const string &strFailMessage, bool condition)
Asserts that a boolean condition is correct.
Definition: UnitTest.cc:40
refcount_ptr< Component > Clone() const
Clones the component and all its children.
Definition: Component.cc:76
ComponentCreationSettings componentCreationSettings
Definition: Component.h:51
static string GetAttribute(const string &name, const string &attributeName)
Gets a specific attribute value for a component.
UI * GetUI()
Gets a pointer to the GXemul instance&#39; active UI.
Definition: GXemul.cc:661
static bool GetCreationArgOverrides(ComponentCreationSettings &settings, const ComponentCreateArgs &createArgs)
Get override arguments for component creation.
#define UNITTEST(functionname)
Helper for unit test case execution.
Definition: UnitTest.h:217
bool IsNULL() const
Checks whether or not an object is referenced by the reference counted pointer.
Definition: refcount_ptr.h:216
refcount_ptr< Component >(* Create)(const ComponentCreateArgs &args)

Generated on Fri Dec 7 2018 19:52:23 for GXemul by doxygen 1.8.13