1 /**************************************************************************\
2  * Copyright (c) Kongsberg Oil & Gas Technologies AS
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * Redistributions of source code must retain the above copyright notice,
10  * this list of conditions and the following disclaimer.
11  *
12  * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  *
16  * Neither the name of the copyright holder nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 \**************************************************************************/
32 
33 #include <Inventor/scxml/ScXMLEvent.h>
34 
35 /*!
36   \class ScXMLEvent ScXMLEvent.h Inventor/scxml/ScXMLEvent.h
37   \brief Base class for events sent to SCXML state machines.
38 
39   \since Coin 3.0
40   \ingroup scxml
41 */
42 
43 #include <cassert>
44 #include <cstring>
45 #include <map>
46 
47 #include <Inventor/scxml/ScXML.h>
48 
49 // *************************************************************************
50 
51 class ScXMLEvent::PImpl {
52 public:
PImpl(void)53   PImpl(void) { }
~PImpl(void)54   ~PImpl(void)
55   {
56     // FIXME: delete strings in associations map (values only)
57   }
58 
59   std::map<const char *, const char *> associations;
60 };
61 
62 #define PRIVATE(obj) ((obj)->pimpl)
63 
64 SCXML_OBJECT_SOURCE(ScXMLEvent);
65 
66 void
initClass(void)67 ScXMLEvent::initClass(void)
68 {
69   SCXML_OBJECT_INIT_CLASS(ScXMLEvent, ScXMLObject, "ScXMLObject");
70 }
71 
72 void
cleanClass(void)73 ScXMLEvent::cleanClass(void)
74 {
75   ScXMLEvent::classTypeId = SoType::badType();
76 }
77 
ScXMLEvent(void)78 ScXMLEvent::ScXMLEvent(void)
79 : name(SbName::empty())
80 {
81 }
82 
~ScXMLEvent(void)83 ScXMLEvent::~ScXMLEvent(void)
84 {
85 }
86 
87 /*!
88   This method is for setting a string that will identifies this particular
89   event, having this particular state, and can be used for event matching
90   in the SCXML descriptions.
91 
92   The string should, according to spec., be a set of tokens consisting
93   of alphanumeric characters, separated with periods (.). This limitation
94   is not enforced by this implementation.
95 */
96 void
setEventName(const SbName & namearg)97 ScXMLEvent::setEventName(const SbName & namearg)
98 {
99   this->name = namearg;
100 }
101 
102 void
setAssociation(const char * key,const char * value)103 ScXMLEvent::setAssociation(const char * key, const char * value)
104 {
105   assert(key && value);
106   SbName dictentry(key);
107   std::map<const char *, const char *>::iterator findit =
108     PRIVATE(this)->associations.find(dictentry.getString());
109   char * valuecopy = new char [strlen(value) + 1];
110   strcpy(valuecopy, value);
111   if (findit != PRIVATE(this)->associations.end()) {
112     delete [] findit->second;
113     findit->second = valuecopy;
114   } else {
115     std::pair<const char *, const char *> newentry(dictentry.getString(), valuecopy);
116     PRIVATE(this)->associations.insert(newentry);
117   }
118 }
119 
120 const char *
getAssociation(const char * key) const121 ScXMLEvent::getAssociation(const char * key) const
122 {
123   assert(key);
124   SbName dictentry(key);
125   std::map<const char *, const char *>::const_iterator findit =
126     PRIVATE(this)->associations.find(dictentry.getString());
127   if (findit != PRIVATE(this)->associations.end()) {
128     return findit->second;
129   }
130   return NULL;
131 }
132 
133 size_t
getNumAssociations(void) const134 ScXMLEvent::getNumAssociations(void) const
135 {
136   return PRIVATE(this)->associations.size();
137 }
138 
139 size_t
getAssociationKeys(SbList<const char * > & keys) const140 ScXMLEvent::getAssociationKeys(SbList<const char *> & keys) const
141 {
142   std::map<const char *, const char *>::const_iterator it =
143     PRIVATE(this)->associations.begin();
144   size_t count = 0;
145   while (it != PRIVATE(this)->associations.end()) {
146     keys.append(it->first);
147     ++count;
148     ++it;
149   }
150   return count;
151 }
152 
153 ScXMLEvent *
clone(void) const154 ScXMLEvent::clone(void) const
155 {
156   SoType thistype = this->getTypeId();
157   assert(thistype.canCreateInstance());
158   ScXMLEvent * newevent = static_cast<ScXMLEvent *>(thistype.createInstance());
159   newevent->copyContents(this);
160   return newevent;
161 }
162 
163 void
copyContents(const ScXMLEvent * rhs)164 ScXMLEvent::copyContents(const ScXMLEvent * rhs)
165 {
166   this->name = rhs->name;
167   SbList<const char *> keys;
168   size_t numkeys = rhs->getAssociationKeys(keys);
169   for (size_t i = 0; i < numkeys; ++i) {
170     this->setAssociation(keys[i], rhs->getAssociation(keys[i]));
171   }
172 }
173 
174 #undef PRIVATE
175