ARB
ED4_objspec.cxx
Go to the documentation of this file.
1 // =============================================================== //
2 // //
3 // File : ED4_objspec.cxx //
4 // Purpose : hierarchy object specification //
5 // //
6 // Coded by Ralf Westram (coder@reallysoft.de) in October 2011 //
7 // Institute of Microbiology (Technical University Munich) //
8 // http://www.arb-home.de/ //
9 // //
10 // =============================================================== //
11 
12 #include "ed4_class.hxx"
13 
14 #define MAX_POSSIBLE_SPECIFIED_OBJECT_TYPES ((sizeof(ED4_level)*8)-1)
15 
17 
18 inline int level2index(ED4_level lev) {
19  int index = 0;
20  e4_assert(lev);
21  while (lev) {
22  if (lev&1) {
23  e4_assert(lev == 1);
24  return index;
25  }
26  lev = ED4_level(lev>>1);
27  index++;
28  }
29  e4_assert(0); // invalid level
30  return -1U;
31 }
32 inline ED4_level index2level(int index) { return ED4_level(1<<index); }
33 
34 
36 
39  int count;
40 
41  ED4_objspec_registry() : count(0) {
42  for (int i = 0; i<SPECIFIED_OBJECT_TYPES; ++i) known_spec[i] = NULp;
43  }
45 
46 public:
47 
49  int idx = level2index(ospec->level);
50 
51  e4_assert(ospec);
53  e4_assert(!known_spec[idx]); // two object types have same level
54 
55  known_spec[idx] = ospec;
56  count++;
57  }
58 
59  int count_registered() const {
60  return count;
61  }
62 
63  const ED4_objspec *get_object_spec_at_index(int index) const {
64  e4_assert(index >= 0 && index<SPECIFIED_OBJECT_TYPES);
65  return known_spec[index];
66  }
68 
70  for (int i = 0; i<SPECIFIED_OBJECT_TYPES; ++i) {
71  ED4_objspec *spec = known_spec[i];
72  if (spec && spec->is_manager() && spec->allowed_to_contain(lev))
73  return true;
74  }
75  return false;
76  }
77 
79 #if defined(DEBUG)
80  for (int i = 1; i<SPECIFIED_OBJECT_TYPES; ++i) {
81  if (known_spec[i]) {
82  ED4_objspec& spec = *known_spec[i];
84  }
85  }
86 #endif
87  }
88 };
89 
91  static ED4_objspec_registry objspec_registry;
92  return objspec_registry;
93 }
94 
95 bool ED4_objspec::object_specs_initialized = false;
96 bool ED4_objspec::descendants_uptodate = false;
97 
99  e4_assert(!object_specs_initialized);
101  object_specs_initialized = true;
102 }
103 
104 void ED4_objspec::calc_descendants() const {
105  if (possible_descendants == LEV_INVALID) {
106  possible_descendants = LEV_NONE;
107  allowed_descendants = LEV_NONE;
108  if (used_children || allowed_children) {
109  possible_descendants = used_children;
110  allowed_descendants = allowed_children;
111 
112  ED4_objspec_registry& objspec_registry = get_objspec_registry();
113 
114  for (int i = 0; i<SPECIFIED_OBJECT_TYPES; ++i) {
115  const ED4_objspec *child_spec = objspec_registry.get_object_spec_at_index(i);
116  if (child_spec && child_spec != this) {
117  if ((used_children|allowed_children) & child_spec->level) {
118  child_spec->calc_descendants();
119  if (used_children & child_spec->level) possible_descendants = ED4_level(possible_descendants|child_spec->possible_descendants);
120  if (allowed_children & child_spec->level) allowed_descendants = ED4_level(allowed_descendants |child_spec->allowed_descendants);
121  }
122  }
123  }
124  // dump(2);
125  }
126  }
127 }
129  ED4_objspec_registry& objspec_registry = get_objspec_registry();
130 
131  for (int i = 0; i<SPECIFIED_OBJECT_TYPES; ++i) {
132  const ED4_objspec *spec = objspec_registry.get_object_spec_at_index(i);
133  if (spec) {
134  spec->possible_descendants = LEV_INVALID;
135  spec->allowed_descendants = LEV_INVALID;
136  }
137  }
138  for (int i = 0; i<SPECIFIED_OBJECT_TYPES; ++i) {
139  const ED4_objspec *spec = objspec_registry.get_object_spec_at_index(i);
140  if (spec) spec->calc_descendants();
141  }
142 
143  descendants_uptodate = true;
144 }
145 
146 ED4_objspec::ED4_objspec(ED4_properties static_prop_, ED4_level level_, ED4_level allowed_children_, ED4_level handled_level_, ED4_level restriction_level_)
147  : used_children(LEV_NONE),
148  possible_descendants(LEV_INVALID),
149  allowed_descendants(LEV_INVALID),
150  static_prop(static_prop_),
151  level(level_),
152  allowed_children(allowed_children_),
153  handled_level(handled_level_),
154  restriction_level(restriction_level_)
155 {
156  e4_assert(!object_specs_initialized); // specs must be instaciated before they are initialized
157 
159  case PROP_IS_MANAGER: // manager specific checks
160  e4_assert(static_prop & (PROP_HORIZONTAL|PROP_VERTICAL)); // each manager has to be vertical or horizontal
162  e4_assert(allowed_children != LEV_NONE); // managers need to allow children (what else should they manage)
163  break;
164 
165  case PROP_IS_TERMINAL: // terminal specific checks
166  e4_assert((static_prop & (PROP_HORIZONTAL|PROP_VERTICAL)) == 0); // terminals do not have orientation
167  e4_assert(allowed_children == LEV_NONE); // terminals cannot have children
168  break;
169 
170  default :
171  e4_assert(0);
172  break;
173  }
174 
176 }
177 
178 
179 // --------------------------------------------------------------------------------
180 
181 #ifdef UNIT_TESTS
182 #ifndef TEST_UNIT_H
183 #include <test_unit.h>
184 #endif
185 
186 
187 void TEST_objspec_registry() {
191  TEST_EXPECT_EQUAL(level2index(ED4_level(0x10000)), 16);
192 
193  for (int i = 0; i<SPECIFIED_OBJECT_TYPES; ++i) {
195  }
196 
197  ED4_objspec_registry& objspec_registry = get_objspec_registry();
198  TEST_EXPECT(objspec_registry.count_registered()>0);
200 
202 
204 
205  const ED4_objspec& multi_seq = objspec_registry.get_object_spec(LEV_MULTI_SEQUENCE);
206  const ED4_objspec& seq = objspec_registry.get_object_spec(LEV_SEQUENCE);
207 
210 
213 
215 
216  // simulate adding sth in the hierarchy
217  multi_seq.announce_added(LEV_SEQUENCE);
219 
222 
224 
225  // add more (checks refresh)
227 
229 }
230 
231 #endif // UNIT_TESTS
232 
233 // --------------------------------------------------------------------------------
#define MAX_POSSIBLE_SPECIFIED_OBJECT_TYPES
Definition: ED4_objspec.cxx:14
#define TEST_REJECT_ZERO(cond)
Definition: test_unit.h:1076
STATIC_ASSERT(SPECIFIED_OBJECT_TYPES<=MAX_POSSIBLE_SPECIFIED_OBJECT_TYPES)
ED4_properties static_prop
Definition: ed4_class.hxx:229
static class ED4_objspec_registry & get_objspec_registry()
Definition: ED4_objspec.cxx:90
int count_registered() const
Definition: ED4_objspec.cxx:59
ED4_level level
Definition: ed4_class.hxx:230
static void init_object_specs()
Definition: ED4_objspec.cxx:98
bool allowed_to_contain(ED4_level child_level) const
Definition: ed4_class.hxx:246
FILE * seq
Definition: rns.c:46
#define e4_assert(bed)
Definition: ed4_class.hxx:11
ED4_level
Definition: ed4_defs.hxx:120
static void recalc_descendants()
#define TEST_EXPECT(cond)
Definition: test_unit.h:1312
const ED4_objspec * get_object_spec_at_index(int index) const
Definition: ED4_objspec.cxx:63
bool has_manager_that_may_contain(ED4_level lev) const
Definition: ED4_objspec.cxx:69
ED4_level index2level(int index)
Definition: ED4_objspec.cxx:32
ED4_objspec(ED4_properties static_prop_, ED4_level level_, ED4_level allowed_children_, ED4_level handled_level_, ED4_level restriction_level_)
ED4_level get_possible_descendants() const
Definition: ed4_class.hxx:260
const ED4_objspec & get_object_spec(ED4_level lev) const
Definition: ED4_objspec.cxx:67
#define TEST_EXPECT_ZERO(cond)
Definition: test_unit.h:1074
void register_objspec(ED4_objspec *ospec)
Definition: ED4_objspec.cxx:48
int level2index(ED4_level lev)
Definition: ED4_objspec.cxx:18
friend ED4_objspec_registry & get_objspec_registry()
Definition: ED4_objspec.cxx:90
ED4_properties
Definition: ed4_defs.hxx:176
ED4_level allowed_children
Definition: ed4_class.hxx:231
#define NULp
Definition: cxxforward.h:97
ED4_level get_allowed_descendants() const
Definition: ed4_class.hxx:265
bool is_manager() const
Definition: ed4_class.hxx:243
void announce_added(ED4_level child_level) const
Definition: ed4_class.hxx:252
#define TEST_EXPECT_EQUAL(expr, want)
Definition: test_unit.h:1283
#define SPECIFIED_OBJECT_TYPES
Definition: ed4_class.hxx:216
static Score ** U
Definition: align.cxx:67