blob: 071d8f1896544d7df7db58144b9ae704d48693fe [file] [log] [blame]
piotr437f5462014-02-04 17:57:25 +01001#
2# Copyright 2010 Free Software Foundation, Inc.
3#
Vasil Velichkov1789ae22019-08-13 20:32:05 +00004# This file was generated by gr_modtool, a tool from the GNU Radio framework
5# This file is a part of gr-gsm
piotr437f5462014-02-04 17:57:25 +01006#
7# GNU Radio is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 3, or (at your option)
10# any later version.
11#
12# GNU Radio is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with GNU Radio; see the file COPYING. If not, write to
19# the Free Software Foundation, Inc., 51 Franklin Street,
20# Boston, MA 02110-1301, USA.
21#
22"""
23A base class is created.
24
25Classes based upon this are used to make more user-friendly interfaces
26to the doxygen xml docs than the generated classes provide.
27"""
Vasil Velichkov1789ae22019-08-13 20:32:05 +000028from __future__ import print_function
29from __future__ import unicode_literals
piotr437f5462014-02-04 17:57:25 +010030
31import os
32import pdb
33
34from xml.parsers.expat import ExpatError
35
Vasil Velichkov1789ae22019-08-13 20:32:05 +000036from .generated import compound
piotr437f5462014-02-04 17:57:25 +010037
38
39class Base(object):
40
Vasil Velichkov1789ae22019-08-13 20:32:05 +000041 class Duplicate(Exception):
piotr437f5462014-02-04 17:57:25 +010042 pass
43
Vasil Velichkov1789ae22019-08-13 20:32:05 +000044 class NoSuchMember(Exception):
piotr437f5462014-02-04 17:57:25 +010045 pass
46
Vasil Velichkov1789ae22019-08-13 20:32:05 +000047 class ParsingError(Exception):
piotr437f5462014-02-04 17:57:25 +010048 pass
49
50 def __init__(self, parse_data, top=None):
51 self._parsed = False
52 self._error = False
53 self._parse_data = parse_data
54 self._members = []
55 self._dict_members = {}
56 self._in_category = {}
57 self._data = {}
58 if top is not None:
59 self._xml_path = top._xml_path
60 # Set up holder of references
61 else:
62 top = self
63 self._refs = {}
64 self._xml_path = parse_data
65 self.top = top
66
67 @classmethod
68 def from_refid(cls, refid, top=None):
69 """ Instantiate class from a refid rather than parsing object. """
70 # First check to see if its already been instantiated.
71 if top is not None and refid in top._refs:
72 return top._refs[refid]
73 # Otherwise create a new instance and set refid.
74 inst = cls(None, top=top)
75 inst.refid = refid
76 inst.add_ref(inst)
77 return inst
78
79 @classmethod
80 def from_parse_data(cls, parse_data, top=None):
81 refid = getattr(parse_data, 'refid', None)
82 if refid is not None and top is not None and refid in top._refs:
83 return top._refs[refid]
84 inst = cls(parse_data, top=top)
85 if refid is not None:
86 inst.refid = refid
87 inst.add_ref(inst)
88 return inst
89
90 def add_ref(self, obj):
91 if hasattr(obj, 'refid'):
92 self.top._refs[obj.refid] = obj
93
94 mem_classes = []
95
96 def get_cls(self, mem):
97 for cls in self.mem_classes:
98 if cls.can_parse(mem):
99 return cls
Vasil Velichkov1789ae22019-08-13 20:32:05 +0000100 raise Exception(("Did not find a class for object '%s'." \
piotr437f5462014-02-04 17:57:25 +0100101 % (mem.get_name())))
102
103 def convert_mem(self, mem):
104 try:
105 cls = self.get_cls(mem)
106 converted = cls.from_parse_data(mem, self.top)
107 if converted is None:
Vasil Velichkov1789ae22019-08-13 20:32:05 +0000108 raise Exception('No class matched this object.')
piotr437f5462014-02-04 17:57:25 +0100109 self.add_ref(converted)
110 return converted
Vasil Velichkov1789ae22019-08-13 20:32:05 +0000111 except Exception as e:
112 print(e)
piotr437f5462014-02-04 17:57:25 +0100113
114 @classmethod
115 def includes(cls, inst):
116 return isinstance(inst, cls)
117
118 @classmethod
119 def can_parse(cls, obj):
120 return False
121
122 def _parse(self):
123 self._parsed = True
124
125 def _get_dict_members(self, cat=None):
126 """
127 For given category a dictionary is returned mapping member names to
128 members of that category. For names that are duplicated the name is
129 mapped to None.
130 """
131 self.confirm_no_error()
132 if cat not in self._dict_members:
133 new_dict = {}
134 for mem in self.in_category(cat):
135 if mem.name() not in new_dict:
136 new_dict[mem.name()] = mem
137 else:
138 new_dict[mem.name()] = self.Duplicate
139 self._dict_members[cat] = new_dict
140 return self._dict_members[cat]
141
142 def in_category(self, cat):
143 self.confirm_no_error()
144 if cat is None:
145 return self._members
146 if cat not in self._in_category:
147 self._in_category[cat] = [mem for mem in self._members
148 if cat.includes(mem)]
149 return self._in_category[cat]
150
151 def get_member(self, name, cat=None):
152 self.confirm_no_error()
153 # Check if it's in a namespace or class.
154 bits = name.split('::')
155 first = bits[0]
156 rest = '::'.join(bits[1:])
157 member = self._get_dict_members(cat).get(first, self.NoSuchMember)
158 # Raise any errors that are returned.
159 if member in set([self.NoSuchMember, self.Duplicate]):
160 raise member()
161 if rest:
162 return member.get_member(rest, cat=cat)
163 return member
164
165 def has_member(self, name, cat=None):
166 try:
167 mem = self.get_member(name, cat=cat)
168 return True
169 except self.NoSuchMember:
170 return False
171
172 def data(self):
173 self.confirm_no_error()
174 return self._data
175
176 def members(self):
177 self.confirm_no_error()
178 return self._members
179
180 def process_memberdefs(self):
181 mdtss = []
182 for sec in self._retrieved_data.compounddef.sectiondef:
183 mdtss += sec.memberdef
184 # At the moment we lose all information associated with sections.
185 # Sometimes a memberdef is in several sectiondef.
186 # We make sure we don't get duplicates here.
187 uniques = set([])
188 for mem in mdtss:
189 converted = self.convert_mem(mem)
190 pair = (mem.name, mem.__class__)
191 if pair not in uniques:
192 uniques.add(pair)
193 self._members.append(converted)
194
195 def retrieve_data(self):
196 filename = os.path.join(self._xml_path, self.refid + '.xml')
197 try:
198 self._retrieved_data = compound.parse(filename)
199 except ExpatError:
200 print('Error in xml in file %s' % filename)
201 self._error = True
202 self._retrieved_data = None
203
204 def check_parsed(self):
205 if not self._parsed:
206 self._parse()
207
208 def confirm_no_error(self):
209 self.check_parsed()
210 if self._error:
211 raise self.ParsingError()
212
213 def error(self):
214 self.check_parsed()
215 return self._error
216
217 def name(self):
218 # first see if we can do it without processing.
219 if self._parse_data is not None:
220 return self._parse_data.name
221 self.check_parsed()
222 return self._retrieved_data.compounddef.name