Sync with 5.4.0
[deliverable/titan.core.git] / compiler2 / asn1 / Tag.cc
CommitLineData
970ed795 1///////////////////////////////////////////////////////////////////////////////
3abe9331 2// Copyright (c) 2000-2015 Ericsson Telecom AB
970ed795
EL
3// All rights reserved. This program and the accompanying materials
4// are made available under the terms of the Eclipse Public License v1.0
5// which accompanies this distribution, and is available at
6// http://www.eclipse.org/legal/epl-v10.html
7///////////////////////////////////////////////////////////////////////////////
8#include "Tag.hh"
9#include "../Type.hh"
10#include "../Value.hh"
11#include <limits.h>
12
13namespace Asn {
14
15 // =================================
16 // ===== Tag
17 // =================================
18
19 Tag::Tag(tagplicit_t p_plicit, tagclass_t p_tagclass, Value *p_tagvalue)
20 : Node(), Location(),
21 plicit(p_plicit), tagclass(p_tagclass), tagvalue(p_tagvalue),
22 is_auto(false)
23 {
24 if(!p_tagvalue)
25 FATAL_ERROR("NULL parameter: Asn::Tag::Tag()");
26 }
27
28 Tag::Tag(tagplicit_t p_plicit, tagclass_t p_tagclass, Int p_tagval)
29 : Node(), Location(),
30 plicit(p_plicit), tagclass(p_tagclass), tagvalue(0),
31 tagval(p_tagval), is_auto(false)
32 {
33 if(tagval<0) FATAL_ERROR("Asn::Tag::Tag(): negative value");
34 }
35
36 Tag::Tag(const Tag& p)
37 : Node(p), Location(p),
38 plicit(p.plicit), tagclass(p.tagclass),
39 is_auto(p.is_auto)
40 {
41 if (p.tagvalue) tagvalue = p.tagvalue->clone();
42 else {
43 tagvalue = NULL;
44 tagval = p.tagval;
45 }
46 }
47
48 Tag::~Tag()
49 {
50 delete tagvalue;
51 }
52
53 Tag& Tag::operator=(const Tag& p)
54 {
55 if (&p != this) {
56 delete tagvalue;
57 plicit = p.plicit;
58 tagclass = p.tagclass;
59 if (p.tagvalue) tagvalue = p.tagvalue->clone();
60 else {
61 tagvalue = NULL;
62 tagval = p.tagval;
63 }
64 is_auto = p.is_auto;
65 }
66 return *this;
67 }
68
69 bool Tag::operator==(const Tag& p) const
70 {
71 if (tagvalue || p.tagvalue) FATAL_ERROR("Comparison of unchecked tags.");
72 return tagclass == p.tagclass && tagval == p.tagval;
73 }
74
75 bool Tag::operator<(const Tag& p) const
76 {
77 if (tagvalue || p.tagvalue) FATAL_ERROR("Comparison of unchecked tags.");
78 if (tagclass < p.tagclass) return true;
79 else if (tagclass > p.tagclass) return false;
80 else return tagval < p.tagval;
81 }
82
83 const char *Tag::get_tagclass_str() const
84 {
85 switch (tagclass) {
86 case TAG_UNIVERSAL:
87 return "ASN_TAG_UNIV";
88 case TAG_APPLICATION:
89 return "ASN_TAG_APPL";
90 case TAG_CONTEXT:
91 return "ASN_TAG_CONT";
92 case TAG_PRIVATE:
93 return "ASN_TAG_PRIV";
94 default:
95 FATAL_ERROR("Tag::get_tagclass_str()");
96 return NULL;
97 }
98 }
99
100 Int Tag::get_tagvalue()
101 {
102 chk();
103 return tagval;
104 }
105
106 void Tag::set_tagvalue(const Int& p_tagval)
107 {
108 if(tagvalue) {delete tagvalue; tagvalue=0;}
109 tagval=p_tagval;
110 }
111
112 void Tag::set_my_scope(Scope *p_scope)
113 {
114 if (tagvalue) tagvalue->set_my_scope(p_scope);
115 }
116
117 void Tag::chk()
118 {
119 if (!tagvalue) return;
120 Error_Context cntxt(this, "In tag");
121 Value *v = tagvalue->get_value_refd_last();
122 switch (v->get_valuetype()) {
123 case Value::V_INT: {
124 const int_val_t *tagval_int = tagvalue->get_val_Int();
125 if (*tagval_int < 0 || *tagval_int > INT_MAX) {
126 error("Integer value in range 0..%d was expected instead of `%s' "
127 "for tag value", INT_MAX, (tagval_int->t_str()).c_str());
128 goto error;
129 }
130 tagval = tagval_int->get_val();
131 break; }
132 case Value::V_ERROR:
133 goto error;
134 break;
135 default:
136 error("INTEGER value was expected for tag value");
137 goto error;
138 }
139 goto end;
140 error:
141 tagclass=TAG_ERROR;
142 tagval=0;
143 end:
144 delete tagvalue;
145 tagvalue = 0;
146 }
147
148 void Tag::dump(unsigned level) const
149 {
150 string s('[');
151 switch(tagclass) {
152 case TAG_ERROR:
153 s+="<ERROR> "; break;
154 case TAG_NONE:
155 s+="<NONE> "; break;
156 case TAG_ALL:
157 s+="<ALL> "; break;
158 case TAG_UNIVERSAL:
159 s+="UNIVERSAL "; break;
160 case TAG_APPLICATION:
161 s+="APPLICATION "; break;
162 case TAG_CONTEXT:
163 break;
164 case TAG_PRIVATE:
165 s+="PRIVATE "; break;
166 default:
167 s+=" <UNKNOWN CLASS>"; break;
168 } // switch tagclass
169 if(!tagvalue) s+=Int2string(tagval);
170 else s+="<value>";
171 s+="]";
172 switch(plicit) {
173 case TAG_DEFPLICIT:
174 break;
175 case TAG_EXPLICIT:
176 s+=" EXPLICIT"; break;
177 case TAG_IMPLICIT:
178 s+=" IMPLICIT"; break;
179 default:
180 s+=" <UNKNOWN PLICIT>"; break;
181 } // switch plicit
182 if(is_auto) s+=" (auto)";
183 DEBUG(level, "Tag: %s", s.c_str());
184 if(tagvalue) tagvalue->dump(level+1);
185 }
186
187 // =================================
188 // ===== Tags
189 // =================================
190
191 Tags::Tags() : Node()
192 {
193 set_fullname(string("<tags>"));
194 my_scope=0;
195 }
196
197 Tags::Tags(const Tags& p) : Node(p)
198 {
199 for(size_t i=0; i<p.tags.size(); i++)
200 add_tag(p.tags[i]->clone());
201 my_scope=0;
202 }
203
204 Tags::~Tags()
205 {
206 for(size_t i=0; i<tags.size(); i++) delete tags[i];
207 tags.clear();
208 }
209
210 void Tags::set_fullname(const string& p_fullname)
211 {
212 Node::set_fullname(p_fullname);
213 for(size_t i=0; i<tags.size(); i++)
214 tags[i]->set_fullname(get_fullname()+"."+Int2string(i));
215 }
216
217 void Tags::set_my_scope(Scope *p_scope)
218 {
219 my_scope=p_scope;
220 for(size_t i=0; i<tags.size(); i++)
221 tags[i]->set_my_scope(p_scope);
222 }
223
224 void Tags::add_tag(Tag *p_tag)
225 {
226 if(!p_tag)
227 FATAL_ERROR("NULL parameter: Asn::Tags::add_tag()");
228 tags.add(p_tag);
229 p_tag->set_fullname(get_fullname()+"."+Int2string(tags.size()));
230 p_tag->set_my_scope(my_scope);
231 }
232
233 void Tags::chk()
234 {
235 for(size_t i=0; i<tags.size(); i++)
236 tags[i]->chk();
237 }
238
239 void Tags::set_plicit(Type *p_type)
240 {
241 if (!p_type) FATAL_ERROR("NULL parameter: Asn::Tags::set_plicit()");
242 Asn::Module *m = dynamic_cast<Asn::Module*>
243 (p_type->get_my_scope()->get_scope_mod());
244 if (!m) FATAL_ERROR("Asn::Tags::set_plicit()");
245 bool type_needs_explicit = p_type->needs_explicit_tag();
246 bool module_uses_explicit = (m->get_tagdef() == TagDefault::EXPLICIT);
247 Tag *innermost = tags[0];
248 switch (innermost->get_plicit()) {
249 case Tag::TAG_DEFPLICIT:
250 if (module_uses_explicit || type_needs_explicit)
251 innermost->set_plicit(Tag::TAG_EXPLICIT);
252 else innermost->set_plicit(Tag::TAG_IMPLICIT);
253 break;
254 case Tag::TAG_IMPLICIT:
255 if (type_needs_explicit) {
256 p_type->error("Type cannot have IMPLICIT tag");
257 innermost->set_plicit(Tag::TAG_EXPLICIT);
258 }
259 default:
260 break;
261 }
262 for (size_t i = 1; i < tags.size(); i++) {
263 Tag *tag = tags[i];
264 if (tag->get_plicit() == Tag::TAG_DEFPLICIT) {
265 if (module_uses_explicit) tag->set_plicit(Tag::TAG_EXPLICIT);
266 else tag->set_plicit(Tag::TAG_IMPLICIT);
267 }
268 }
269 }
270
271 void Tags::cut_auto_tags()
272 {
273 size_t i = 0;
274 while (i < tags.size()) {
275 Tag *tag = tags[i];
276 if (tag->is_automatic()) {
277 delete tag;
278 tags.replace(i, 1, NULL);
279 } else i++;
280 }
281 }
282
283 void Tags::dump(unsigned level) const
284 {
285 for(size_t i=0; i<tags.size(); i++)
286 tags[i]->dump(level);
287 }
288
289 // =================================
290 // ===== TagCollection
291 // =================================
292
293 TagCollection::TagCollection()
294 : has_all(NULL), is_extensible(false)
295 {
296 }
297
298 TagCollection::TagCollection(const TagCollection& p)
299 : Node(p), Location(p),
300 has_all(p.has_all), is_extensible(p.is_extensible)
301 {
302 for (size_t i = 0; i < p.tag_map.size(); i++)
303 tag_map.add(p.tag_map.get_nth_key(i), 0);
304 }
305
306 TagCollection::~TagCollection()
307 {
308 tag_map.clear();
309 }
310
311 void TagCollection::addTag(const Tag *p_tag)
312 {
313 if (!p_tag)
314 FATAL_ERROR("Asn::TagCollection::addTag()");
315 if (p_tag->get_tagclass() == Tag::TAG_ALL) {
316 if (has_all)
317 FATAL_ERROR("Asn::TagCollection::addTag(): tag 'all'");
318 has_all = p_tag;
319 }
320 else if(p_tag->get_tagclass() == Tag::TAG_ERROR)
321 return;
322 else if(!tag_map.has_key(*p_tag))
323 tag_map.add(*p_tag, 0);
324 else
325 FATAL_ERROR("Asn::TagCollection::addTag(): tag is already in collection");
326 }
327
328 bool TagCollection::hasTag(const Tag *p_tag) const
329 {
330 if (!p_tag) FATAL_ERROR("NULL parameter: Asn::TagCollection::hasTag()");
331 if (has_all) return true;
332 else if (p_tag->get_tagclass() == Tag::TAG_ALL) return !tag_map.empty();
333 else if (p_tag->get_tagclass() == Tag::TAG_ERROR) return false;
334 else return tag_map.has_key(*p_tag);
335 }
336
337 void TagCollection::addTags(const TagCollection *p_tags)
338 {
339 if (!p_tags) FATAL_ERROR("NULL parameter: Asn::TagCollection::addTags()");
340 if (p_tags->is_extensible) setExtensible();
341 if (p_tags->has_all) {
342 if (has_all) FATAL_ERROR("Asn::TagCollection::addTags(): tag 'all'");
343 has_all = p_tags->has_all;
344 }
345 for (size_t i = 0; i < p_tags->tag_map.size(); i++) {
346 const Tag& tag = p_tags->tag_map.get_nth_key(i);
347 if (!tag_map.has_key(tag)) tag_map.add(tag, 0);
348 else FATAL_ERROR("Asn::TagCollection::addTags(): tag is already in collection");
349 }
350 }
351
352 bool TagCollection::hasTags(const TagCollection *p_tags) const
353 {
354 if (!p_tags) FATAL_ERROR("NULL parameter: Asn::TagCollection::hasTags()");
355 if (has_all) return !p_tags->isEmpty();
356 else if (p_tags->has_all) return !isEmpty();
357 for (size_t i = 0; i < p_tags->tag_map.size(); i++)
358 if (tag_map.has_key(p_tags->tag_map.get_nth_key(i))) return true;
359 return false;
360 }
361
362 bool TagCollection::greaterTags(const TagCollection *p_tags) const
363 {
364 if (!p_tags)
365 FATAL_ERROR("NULL parameter: Asn::TagCollection::greaterTags()");
366 if (has_all) return !p_tags->isEmpty();
367 else if (p_tags->has_all) return !isEmpty();
368 else if (tag_map.empty() || p_tags->tag_map.empty()) return true;
369 else return tag_map.get_nth_key(tag_map.size() - 1) <
370 p_tags->tag_map.get_nth_key(0);
371 }
372
373 const Tag *TagCollection::getSmallestTag() const
374 {
375 if (has_all) return has_all;
376 if (tag_map.empty()) FATAL_ERROR("TagCollection::getSmallestTag()");
377 return &tag_map.get_nth_key(0);
378 }
379
380 const Tag *TagCollection::getGreatestTag() const
381 {
382 if (has_all) return has_all;
383 if (tag_map.empty()) FATAL_ERROR("TagCollection::getGreatestTag()");
384 return &tag_map.get_nth_key(tag_map.size() - 1);
385 }
386
387 void TagCollection::setExtensible()
388 {
389 if(is_extensible)
390 error("Illegal use of extensibility notation (possible tag conflict)");
391 else is_extensible=true;
392 }
393
394 bool TagCollection::isEmpty() const
395 {
396 if (has_all || is_extensible) return false;
397 else return tag_map.empty();
398 }
399
400 void TagCollection::clear()
401 {
402 tag_map.clear();
403 has_all = NULL;
404 is_extensible = false;
405 }
406
407} // namespace Asn
This page took 0.0405 seconds and 5 git commands to generate.