5 * Created by Bryan Donlan on Thu Mar 10 2005.
6 * Copyright (c) 2004 Alyssa Milburn and Bryan Donlan. All rights reserved.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
23 #include <boost/variant.hpp>
33 class wrongCaosVarTypeException
: public caosException
{
35 wrongCaosVarTypeException() throw() : caosException("Wrong caos variable type") {}
36 wrongCaosVarTypeException(const char *s
) throw() : caosException(s
) { }
37 wrongCaosVarTypeException(const std::string
&s
) throw() : caosException(s
) { }
40 struct nulltype_tag
{ };
43 CAOSNULL
= 0, CAOSAGENT
, CAOSINT
, CAOSFLOAT
, CAOSSTR
, CAOSVEC
48 FRIEND_SERIALIZE(caosVar
)
50 struct typeVisit
: public boost::static_visitor
<variableType
> {
51 variableType
operator()(int) const { return CAOSINT
; }
52 variableType
operator()(float) const { return CAOSFLOAT
; }
53 variableType
operator()(const std::string
&) const { return CAOSSTR
; }
54 variableType
operator()(const AgentRef
&) const { return CAOSAGENT
; }
55 variableType
operator()(nulltype_tag
) const { return CAOSNULL
; }
56 variableType
operator()(const Vector
<float> &) const { return CAOSVEC
; }
59 #define BAD_TYPE(et, gt) \
60 const et &operator()(const gt &) const { \
61 throw wrongCaosVarTypeException( \
62 "Wrong caosVar type: Expected " #et ", got " #gt \
66 struct intVisit
: public boost::static_visitor
<int> {
67 int operator()(int i
) const { return i
; }
68 int operator()(float f
) const {
69 // horror necessary for rounding without C99
70 int x
= (int)f
; float diff
= f
- x
;
72 if (diff
>= 0.5f
) return ++x
; else return x
;
74 if (diff
<= -0.5f
) return --x
; else return x
;
77 int operator()(const Vector
<float> &v
) const {
78 return (int)v
.getMagnitude();
80 BAD_TYPE(int, std::string
);
81 BAD_TYPE(int, AgentRef
);
82 BAD_TYPE(int, nulltype_tag
);
85 struct floatVisit
: public boost::static_visitor
<float> {
86 float operator()(int i
) const { return (float)i
; }
87 float operator()(float f
) const { return f
; }
88 float operator()(const Vector
<float> &v
) const { return v
.getMagnitude(); }
89 BAD_TYPE(float, std::string
);
90 BAD_TYPE(float, AgentRef
);
91 BAD_TYPE(float, nulltype_tag
);
94 struct stringVisit
: public boost::static_visitor
<const std::string
&> {
95 const std::string
&operator()(const std::string
&s
) const {
98 BAD_TYPE(std::string
, AgentRef
);
99 BAD_TYPE(std::string
, nulltype_tag
);
100 BAD_TYPE(std::string
, int);
101 BAD_TYPE(std::string
, float);
102 BAD_TYPE(std::string
, Vector
<float>);
105 struct agentVisit
: public boost::static_visitor
<const AgentRef
&> {
106 const AgentRef
&operator()(const AgentRef
&a
) const {
109 BAD_TYPE(AgentRef
, std::string
);
110 BAD_TYPE(AgentRef
, nulltype_tag
);
111 const AgentRef
&operator()(int i
) const;
112 BAD_TYPE(AgentRef
, float);
113 BAD_TYPE(AgentRef
, Vector
<float>);
116 struct vectorVisit
: public boost::static_visitor
<const Vector
<float> &> {
117 const Vector
<float> &operator()(const Vector
<float> &v
) const {
120 BAD_TYPE(Vector
<float>, std::string
);
121 BAD_TYPE(Vector
<float>, nulltype_tag
);
122 BAD_TYPE(Vector
<float>, int);
123 BAD_TYPE(Vector
<float>, float);
124 BAD_TYPE(Vector
<float>, AgentRef
);
129 boost::variant
<int, float, AgentRef
, std::string
, nulltype_tag
, Vector
<float> > value
;
132 variableType
getType() const {
133 return boost::apply_visitor(typeVisit(), value
);
137 value
= nulltype_tag();
141 return getType() == CAOSNULL
;
150 caosVar
&operator=(const caosVar
©From
) {
151 value
= copyFrom
.value
;
155 caosVar(const caosVar
©From
) : value(copyFrom
.value
) { }
157 caosVar(int v
) { setInt(v
); }
158 caosVar(float v
) { setFloat(v
); }
159 caosVar(Agent
*v
) { setAgent(v
); }
160 caosVar(const AgentRef
&v
) { setAgent(v
); }
161 caosVar(const std::string
&v
) { setString(v
); }
162 caosVar(const Vector
<float> &v
) { setVector(v
); }
164 bool isEmpty() const { return getType() == CAOSNULL
; }
165 bool hasInt() const { return getType() == CAOSINT
; }
166 bool hasFloat() const { return getType() == CAOSFLOAT
; }
167 bool hasAgent() const { return getType() == CAOSAGENT
; }
168 bool hasString() const { return getType() == CAOSSTR
; }
169 bool hasDecimal() const { return getType() == CAOSINT
|| getType() == CAOSFLOAT
|| getType() == CAOSVEC
; }
170 bool hasNumber() const { return hasDecimal(); }
171 bool hasVector() const { return getType() == CAOSVEC
; }
173 void setInt(int i
) { value
= i
; }
174 void setFloat(float i
) { value
= i
; }
175 void setAgent(Agent
*i
) {
178 void setAgent(const AgentRef
&r
) {
181 void setString(const std::string
&i
) {
184 void setVector(const Vector
<float> &v
) {
189 return boost::apply_visitor(intVisit(), value
);
192 float getFloat() const {
193 return boost::apply_visitor(floatVisit(), value
);
196 void getString(std::string
&s
) const {
200 const std::string
&getString() const {
201 return boost::apply_visitor(stringVisit(), value
);
204 boost::shared_ptr
<Agent
> getAgent() const {
205 return getAgentRef().lock();
208 const AgentRef
&getAgentRef() const {
209 return boost::apply_visitor(agentVisit(), value
);
212 const Vector
<float> &getVector() const {
213 return boost::apply_visitor(vectorVisit(), value
);
216 bool operator == (const caosVar
&v
) const;
217 bool operator != (const caosVar
&v
) const { return !(*this == v
); }
218 bool operator > (const caosVar
&v
) const;
219 bool operator < (const caosVar
&v
) const;
221 std::string
dump() const;
224 struct caosVarCompare
{
225 bool operator()(const caosVar
&v1
, const caosVar
&v2
) const {
226 if (v1
.getType() == v2
.getType())
229 return v1
.getType() < v2
.getType();