|
1 #include "attribute-list.h" |
|
2 #include "string.h" |
|
3 #include "singleton.h" |
|
4 |
|
5 namespace ns3 { |
|
6 |
|
7 /********************************************************************* |
|
8 * The AttributeList container implementation |
|
9 *********************************************************************/ |
|
10 |
|
11 AttributeList::AttributeList () |
|
12 {} |
|
13 |
|
14 AttributeList::AttributeList (const AttributeList &o) |
|
15 { |
|
16 for (Attrs::const_iterator i = o.m_attributes.begin (); i != o.m_attributes.end (); i++) |
|
17 { |
|
18 struct Attr attr; |
|
19 attr.checker = i->checker; |
|
20 attr.value = i->value.Copy (); |
|
21 m_attributes.push_back (attr); |
|
22 } |
|
23 } |
|
24 AttributeList & |
|
25 AttributeList::operator = (const AttributeList &o) |
|
26 { |
|
27 Reset (); |
|
28 for (Attrs::const_iterator i = o.m_attributes.begin (); i != o.m_attributes.end (); i++) |
|
29 { |
|
30 struct Attr attr; |
|
31 attr.checker = i->checker; |
|
32 attr.value = i->value.Copy (); |
|
33 m_attributes.push_back (attr); |
|
34 } |
|
35 return *this; |
|
36 } |
|
37 AttributeList::~AttributeList () |
|
38 { |
|
39 Reset (); |
|
40 } |
|
41 |
|
42 void |
|
43 AttributeList::Set (std::string name, Attribute value) |
|
44 { |
|
45 struct TypeId::AttributeInfo info; |
|
46 bool ok = TypeId::LookupAttributeByFullName (name, &info); |
|
47 if (!ok) |
|
48 { |
|
49 NS_FATAL_ERROR ("Could not find attribute "<<name); |
|
50 } |
|
51 ok = DoSet (&info, value); |
|
52 if (!ok) |
|
53 { |
|
54 NS_FATAL_ERROR ("Could not set value for attribute "<<name); |
|
55 } |
|
56 } |
|
57 bool |
|
58 AttributeList::SetFailSafe (std::string name, Attribute value) |
|
59 { |
|
60 struct TypeId::AttributeInfo info; |
|
61 bool ok = TypeId::LookupAttributeByFullName (name, &info); |
|
62 if (!ok) |
|
63 { |
|
64 return false; |
|
65 } |
|
66 ok = DoSet (&info, value); |
|
67 return ok; |
|
68 } |
|
69 void |
|
70 AttributeList::SetWithTid (TypeId tid, std::string name, Attribute value) |
|
71 { |
|
72 struct TypeId::AttributeInfo info; |
|
73 bool ok = tid.LookupAttributeByName (name, &info); |
|
74 if (!ok) |
|
75 { |
|
76 NS_FATAL_ERROR ("Could not find attribute "<<tid.GetName ()<<"::"<<name); |
|
77 } |
|
78 ok = DoSet (&info, value); |
|
79 if (!ok) |
|
80 { |
|
81 NS_FATAL_ERROR ("Could not set value for attribute "<<tid.GetName ()<<"::"<<name); |
|
82 } |
|
83 } |
|
84 |
|
85 void |
|
86 AttributeList::DoSetOne (Ptr<const AttributeChecker> checker, Attribute value) |
|
87 { |
|
88 // get rid of any previous value stored in this |
|
89 // vector of values. |
|
90 for (Attrs::iterator k = m_attributes.begin (); k != m_attributes.end (); k++) |
|
91 { |
|
92 if (k->checker == checker) |
|
93 { |
|
94 m_attributes.erase (k); |
|
95 break; |
|
96 } |
|
97 } |
|
98 // store the new value. |
|
99 struct Attr attr; |
|
100 attr.checker = checker; |
|
101 attr.value = value.Copy (); |
|
102 m_attributes.push_back (attr); |
|
103 } |
|
104 bool |
|
105 AttributeList::DoSet (struct TypeId::AttributeInfo *info, Attribute value) |
|
106 { |
|
107 if (info->checker == 0) |
|
108 { |
|
109 return false; |
|
110 } |
|
111 bool ok = info->checker->Check (value); |
|
112 if (!ok) |
|
113 { |
|
114 // attempt to convert to string. |
|
115 const StringValue *str = value.DynCast<const StringValue *> (); |
|
116 if (str == 0) |
|
117 { |
|
118 return false; |
|
119 } |
|
120 // attempt to convert back to value. |
|
121 Attribute v = info->checker->Create (); |
|
122 ok = v.DeserializeFromString (str->Get ().Get (), info->checker); |
|
123 if (!ok) |
|
124 { |
|
125 return false; |
|
126 } |
|
127 ok = info->checker->Check (v); |
|
128 if (!ok) |
|
129 { |
|
130 return false; |
|
131 } |
|
132 value = v; |
|
133 } |
|
134 DoSetOne (info->checker, value); |
|
135 return true; |
|
136 } |
|
137 void |
|
138 AttributeList::Reset (void) |
|
139 { |
|
140 m_attributes.clear (); |
|
141 } |
|
142 AttributeList * |
|
143 AttributeList::GetGlobal (void) |
|
144 { |
|
145 return Singleton<AttributeList>::Get (); |
|
146 } |
|
147 |
|
148 std::string |
|
149 AttributeList::LookupAttributeFullNameByChecker (Ptr<const AttributeChecker> checker) const |
|
150 { |
|
151 for (uint32_t i = 0; i < TypeId::GetRegisteredN (); i++) |
|
152 { |
|
153 TypeId tid = TypeId::GetRegistered (i); |
|
154 for (uint32_t j = 0; j < tid.GetAttributeListN (); j++) |
|
155 { |
|
156 if (checker == tid.GetAttributeChecker (j)) |
|
157 { |
|
158 return tid.GetAttributeFullName (j); |
|
159 } |
|
160 } |
|
161 } |
|
162 NS_FATAL_ERROR ("Could not find requested Accessor."); |
|
163 // quiet compiler. |
|
164 return ""; |
|
165 } |
|
166 |
|
167 std::string |
|
168 AttributeList::SerializeToString (void) const |
|
169 { |
|
170 std::ostringstream oss; |
|
171 for (Attrs::const_iterator i = m_attributes.begin (); i != m_attributes.end (); i++) |
|
172 { |
|
173 std::string name = LookupAttributeFullNameByChecker (i->checker); |
|
174 oss << name << "=" << i->value.SerializeToString (i->checker); |
|
175 if (i != m_attributes.end ()) |
|
176 { |
|
177 oss << "|"; |
|
178 } |
|
179 } |
|
180 return oss.str (); |
|
181 } |
|
182 bool |
|
183 AttributeList::DeserializeFromString (std::string str) |
|
184 { |
|
185 Reset (); |
|
186 |
|
187 std::string::size_type cur; |
|
188 cur = 0; |
|
189 do { |
|
190 std::string::size_type equal = str.find ("=", cur); |
|
191 if (equal == std::string::npos) |
|
192 { |
|
193 // XXX: invalid attribute. |
|
194 break; |
|
195 } |
|
196 else |
|
197 { |
|
198 std::string name = str.substr (cur, equal-cur); |
|
199 struct TypeId::AttributeInfo info; |
|
200 if (!TypeId::LookupAttributeByFullName (name, &info)) |
|
201 { |
|
202 // XXX invalid name. |
|
203 break; |
|
204 } |
|
205 else |
|
206 { |
|
207 std::string::size_type next = str.find ("|", cur); |
|
208 std::string value; |
|
209 if (next == std::string::npos) |
|
210 { |
|
211 value = str.substr (equal+1, str.size () - (equal+1)); |
|
212 cur = str.size (); |
|
213 } |
|
214 else |
|
215 { |
|
216 value = str.substr (equal+1, next - (equal+1)); |
|
217 cur++; |
|
218 } |
|
219 Attribute val = info.checker->Create (); |
|
220 bool ok = val.DeserializeFromString (value, info.checker); |
|
221 if (!ok) |
|
222 { |
|
223 // XXX invalid value |
|
224 break; |
|
225 } |
|
226 else |
|
227 { |
|
228 DoSetOne (info.checker, val); |
|
229 } |
|
230 } |
|
231 } |
|
232 } while (cur != str.size ()); |
|
233 |
|
234 return true; |
|
235 } |
|
236 |
|
237 } // namespace ns3 |