| 1 | // =============================================================== // | 
|---|
| 2 | //                                                                 // | 
|---|
| 3 | //   File      : AP_buffer.hxx                                     // | 
|---|
| 4 | //   Purpose   :                                                   // | 
|---|
| 5 | //                                                                 // | 
|---|
| 6 | //   Institute of Microbiology (Technical University Munich)       // | 
|---|
| 7 | //   http://www.arb-home.de/                                       // | 
|---|
| 8 | //                                                                 // | 
|---|
| 9 | // =============================================================== // | 
|---|
| 10 |  | 
|---|
| 11 | #ifndef AP_BUFFER_HXX | 
|---|
| 12 | #define AP_BUFFER_HXX | 
|---|
| 13 |  | 
|---|
| 14 | #ifndef AP_SEQUENCE_HXX | 
|---|
| 15 | #include <AP_sequence.hxx> | 
|---|
| 16 | #endif | 
|---|
| 17 | #ifndef ARB_FORWARD_LIST_H | 
|---|
| 18 | #include <arb_forward_list.h> | 
|---|
| 19 | #endif | 
|---|
| 20 | #ifndef SMARTPTR_H | 
|---|
| 21 | #include <smartptr.h> | 
|---|
| 22 | #endif | 
|---|
| 23 | #ifndef _GLIBCXX_SET | 
|---|
| 24 | #include <set> | 
|---|
| 25 | #endif | 
|---|
| 26 |  | 
|---|
| 27 | /* AP_STACK        Stack container | 
|---|
| 28 | * | 
|---|
| 29 | * -- buffers | 
|---|
| 30 | * | 
|---|
| 31 | * NodeState  holds (partial) state of AP_tree_nlen | 
|---|
| 32 | * | 
|---|
| 33 | * -- used stacks | 
|---|
| 34 | * | 
|---|
| 35 | * StateStack      stack containing NodeState* (each AP_tree_nlen contains one) | 
|---|
| 36 | * NodeStack       stack containing AP_tree_nlen* (NodeStack of current frame is member of AP_main) | 
|---|
| 37 | * FrameStack      stack containing NodeStacks (member of AP_main, stores previous NodeStack frames) | 
|---|
| 38 | */ | 
|---|
| 39 |  | 
|---|
| 40 | template <typename ELEM> | 
|---|
| 41 | struct AP_STACK : public arb_forward_list<ELEM*> { | 
|---|
| 42 | typedef arb_forward_list<ELEM*>       BASE; | 
|---|
| 43 | typedef typename BASE::iterator       iterator; | 
|---|
| 44 | typedef typename BASE::const_iterator const_iterator; | 
|---|
| 45 |  | 
|---|
| 46 | void push(ELEM *element) { | 
|---|
| 47 | //! add 'element' to top of stack | 
|---|
| 48 | BASE::push_front(element); | 
|---|
| 49 | } | 
|---|
| 50 | void shift(ELEM *element) { | 
|---|
| 51 | //! add 'element' to bottom of stack | 
|---|
| 52 | #if defined(Cxx11) | 
|---|
| 53 | // uses forward_list | 
|---|
| 54 | if (BASE::empty()) { | 
|---|
| 55 | push(element); | 
|---|
| 56 | } | 
|---|
| 57 | else { | 
|---|
| 58 | iterator i = BASE::begin(); | 
|---|
| 59 | iterator n = i; | 
|---|
| 60 | while (true) { | 
|---|
| 61 | if (++n == BASE::end()) { | 
|---|
| 62 | BASE::insert_after(i, element); | 
|---|
| 63 | break; | 
|---|
| 64 | } | 
|---|
| 65 | i = n; | 
|---|
| 66 | } | 
|---|
| 67 | } | 
|---|
| 68 | #else | 
|---|
| 69 | // uses list | 
|---|
| 70 | BASE::push_back(element); | 
|---|
| 71 | #endif | 
|---|
| 72 | } | 
|---|
| 73 | ELEM *pop() { | 
|---|
| 74 | if (BASE::empty()) return NULp; | 
|---|
| 75 |  | 
|---|
| 76 | ELEM *result = top(); | 
|---|
| 77 | BASE::pop_front(); | 
|---|
| 78 | return result; | 
|---|
| 79 | } | 
|---|
| 80 |  | 
|---|
| 81 | ELEM *top() { | 
|---|
| 82 | ap_assert(!BASE::empty()); | 
|---|
| 83 | return BASE::front(); | 
|---|
| 84 | } | 
|---|
| 85 | const ELEM *top() const { | 
|---|
| 86 | ap_assert(!BASE::empty()); | 
|---|
| 87 | return BASE::front(); | 
|---|
| 88 | } | 
|---|
| 89 |  | 
|---|
| 90 | size_t count_elements() const { | 
|---|
| 91 | #if defined(Cxx11) | 
|---|
| 92 | size_t s = 0; | 
|---|
| 93 | for (const_iterator i = BASE::begin(); i != BASE::end(); ++i) ++s; | 
|---|
| 94 | return s; | 
|---|
| 95 | #else // !defined(Cxx11) | 
|---|
| 96 | return BASE::size(); | 
|---|
| 97 | #endif | 
|---|
| 98 | } | 
|---|
| 99 |  | 
|---|
| 100 | bool empty() const { return BASE::empty(); } | 
|---|
| 101 | }; | 
|---|
| 102 |  | 
|---|
| 103 | // ---------------------------------------------------------------- | 
|---|
| 104 | //      special buffer-structures for AP_tree and AP_tree_edge | 
|---|
| 105 |  | 
|---|
| 106 | #if defined(DEBUG) | 
|---|
| 107 | #define PROVIDE_PRINT | 
|---|
| 108 | #endif | 
|---|
| 109 |  | 
|---|
| 110 | #if defined(PROVIDE_PRINT) | 
|---|
| 111 | #include <ostream> | 
|---|
| 112 | #endif | 
|---|
| 113 |  | 
|---|
| 114 |  | 
|---|
| 115 | class AP_tree_edge; // defined in ap_tree_nlen.hxx | 
|---|
| 116 |  | 
|---|
| 117 | enum AP_STACK_MODE { | 
|---|
| 118 | NOTHING   = 0, // nothing to buffer in AP_tree node | 
|---|
| 119 | STRUCTURE = 1, // only structure | 
|---|
| 120 | SEQUENCE  = 2, // only sequence | 
|---|
| 121 | BOTH      = 3, // sequence & treestructure is buffered | 
|---|
| 122 | ROOT      = 7  // old root is buffered (includes BOTH) | 
|---|
| 123 | }; | 
|---|
| 124 |  | 
|---|
| 125 | class AP_tree_nlen; | 
|---|
| 126 | class AP_pars_root; | 
|---|
| 127 |  | 
|---|
| 128 | typedef unsigned long Level; | 
|---|
| 129 |  | 
|---|
| 130 | struct NodeState : virtual Noncopyable { // buffers previous states of AP_tree_nlen | 
|---|
| 131 | Level         frameNr;  // state of AP_tree_nlen::remembered_for_frame at creation time of NodeState | 
|---|
| 132 | AP_STACK_MODE mode;     // what has been stored? | 
|---|
| 133 |  | 
|---|
| 134 | // only defined if mode & SEQUENCE: | 
|---|
| 135 | AP_sequence *sequence;  // if set -> NodeState is owner! | 
|---|
| 136 | Mutations    mutations; | 
|---|
| 137 |  | 
|---|
| 138 | // only defined if mode & STRUCTURE: | 
|---|
| 139 | double        leftlen, rightlen; | 
|---|
| 140 | AP_tree_nlen *father; | 
|---|
| 141 | AP_tree_nlen *leftson; | 
|---|
| 142 | AP_tree_nlen *rightson; | 
|---|
| 143 | AP_pars_root *root; | 
|---|
| 144 | GBDATA       *gb_node; | 
|---|
| 145 | int           keelState; | 
|---|
| 146 | SmartCharPtr  remark; | 
|---|
| 147 | AP_tree_edge *edge[3]; | 
|---|
| 148 | int           edgeIndex[3]; | 
|---|
| 149 |  | 
|---|
| 150 | // defined/restored if mode & (SEQUENCE|STRUCTURE): | 
|---|
| 151 | unsigned mark_sum; | 
|---|
| 152 |  | 
|---|
| 153 | void move_info_to(NodeState& target, AP_STACK_MODE what); | 
|---|
| 154 |  | 
|---|
| 155 | #if defined(PROVIDE_PRINT) | 
|---|
| 156 | void print(std::ostream& out, int indentLevel = 0) const; | 
|---|
| 157 | #endif | 
|---|
| 158 |  | 
|---|
| 159 | explicit NodeState(Level frame_nr) : frameNr(frame_nr), mode(NOTHING), mutations(0) {} | 
|---|
| 160 | ~NodeState() { if (mode & SEQUENCE) delete sequence; } | 
|---|
| 161 | }; | 
|---|
| 162 |  | 
|---|
| 163 | struct StateStack : public AP_STACK<NodeState> { | 
|---|
| 164 | #if defined(PROVIDE_PRINT) | 
|---|
| 165 | void print(std::ostream& out, int indentLevel = 0) const; | 
|---|
| 166 | #endif | 
|---|
| 167 | }; | 
|---|
| 168 |  | 
|---|
| 169 | class AP_tree_nlen; | 
|---|
| 170 | class AP_tree_edge; | 
|---|
| 171 |  | 
|---|
| 172 | #if defined(ASSERTION_USED) | 
|---|
| 173 | #define CHECK_ROOT_POPS | 
|---|
| 174 | #endif | 
|---|
| 175 |  | 
|---|
| 176 | typedef std::set<AP_tree_nlen*> NodeSet; | 
|---|
| 177 | typedef std::set<AP_tree_edge*> EdgeSet; | 
|---|
| 178 |  | 
|---|
| 179 | class ResourceStack { | 
|---|
| 180 | // stores nodes and edges for resource management | 
|---|
| 181 | NodeSet nodes; | 
|---|
| 182 | EdgeSet edges; | 
|---|
| 183 | public: | 
|---|
| 184 | ResourceStack() {} | 
|---|
| 185 | ~ResourceStack() { | 
|---|
| 186 | ap_assert(nodes.empty()); | 
|---|
| 187 | ap_assert(edges.empty()); | 
|---|
| 188 | } | 
|---|
| 189 |  | 
|---|
| 190 | void extract_common(ResourceStack& stack1, ResourceStack& stack2); | 
|---|
| 191 |  | 
|---|
| 192 | void destroy_nodes(); | 
|---|
| 193 | void destroy_edges(); | 
|---|
| 194 | void forget_nodes(); | 
|---|
| 195 | void forget_edges(); | 
|---|
| 196 | void move_nodes(ResourceStack& target); | 
|---|
| 197 | void move_edges(ResourceStack& target); | 
|---|
| 198 |  | 
|---|
| 199 | AP_tree_nlen *put(AP_tree_nlen *node) { nodes.insert(node); return node; } | 
|---|
| 200 | AP_tree_edge *put(AP_tree_edge *edge) { edges.insert(edge); return edge; } | 
|---|
| 201 |  | 
|---|
| 202 | AP_tree_nlen *getNode() { ap_assert(!nodes.empty()); AP_tree_nlen *result = *nodes.begin(); nodes.erase(nodes.begin()); return result; } | 
|---|
| 203 | AP_tree_edge *getEdge() { ap_assert(!edges.empty()); AP_tree_edge *result = *edges.begin(); edges.erase(edges.begin()); return result; } | 
|---|
| 204 |  | 
|---|
| 205 | bool has_nodes() const { return !nodes.empty(); } | 
|---|
| 206 | bool has_edges() const { return !edges.empty(); } | 
|---|
| 207 |  | 
|---|
| 208 | bool has_node(AP_tree_nlen *node) const { return nodes.find(node) != nodes.end(); } | 
|---|
| 209 | }; | 
|---|
| 210 |  | 
|---|
| 211 | class StackFrameData : virtual Noncopyable { | 
|---|
| 212 | // data local to current stack frame | 
|---|
| 213 | // as well exists for stack frame = 0 (i.e. when nothing has been remember()ed yet) | 
|---|
| 214 |  | 
|---|
| 215 | ResourceStack created;   // nodes and edges created in the current stack frame | 
|---|
| 216 | ResourceStack destroyed; // same for destroyed | 
|---|
| 217 |  | 
|---|
| 218 | public: | 
|---|
| 219 | bool  root_pushed; // @@@ move into NodeStack | 
|---|
| 220 | StackFrameData() : root_pushed(false) {} | 
|---|
| 221 |  | 
|---|
| 222 | void revert_resources(StackFrameData *previous); | 
|---|
| 223 | void accept_resources(StackFrameData *previous, ResourceStack *common); | 
|---|
| 224 |  | 
|---|
| 225 | void extract_common_to(ResourceStack& common) { common.extract_common(created, destroyed); } | 
|---|
| 226 |  | 
|---|
| 227 | inline AP_tree_nlen *makeNode(AP_pars_root *proot); | 
|---|
| 228 | inline AP_tree_edge *makeEdge(AP_tree_nlen *n1, AP_tree_nlen *n2); | 
|---|
| 229 | inline void destroyNode(AP_tree_nlen *node); | 
|---|
| 230 | inline void destroyEdge(AP_tree_edge *edge); | 
|---|
| 231 | }; | 
|---|
| 232 |  | 
|---|
| 233 | #if defined(ASSERTION_USED) | 
|---|
| 234 | #define CHECK_STACK_RESOURCE_HANDLING | 
|---|
| 235 | #endif | 
|---|
| 236 |  | 
|---|
| 237 | class NodeStack : public AP_STACK<AP_tree_nlen> { // derived from Noncopyable | 
|---|
| 238 | StackFrameData *previous; | 
|---|
| 239 | #if defined(CHECK_STACK_RESOURCE_HANDLING) | 
|---|
| 240 | enum ResHandled { NO, ACCEPTED, REVERTED } resources_handled; | 
|---|
| 241 | #endif | 
|---|
| 242 |  | 
|---|
| 243 | public: | 
|---|
| 244 | explicit NodeStack(StackFrameData*& data) | 
|---|
| 245 | : previous(data) | 
|---|
| 246 | #if defined(CHECK_STACK_RESOURCE_HANDLING) | 
|---|
| 247 | , resources_handled(NO) | 
|---|
| 248 | #endif | 
|---|
| 249 | { | 
|---|
| 250 | data = NULp; // take ownership | 
|---|
| 251 | } | 
|---|
| 252 | ~NodeStack() { | 
|---|
| 253 | ap_assert(!previous); // forgot to use take_previous_frame_data() | 
|---|
| 254 | #if defined(CHECK_STACK_RESOURCE_HANDLING) | 
|---|
| 255 | ap_assert(resources_handled != NO); | 
|---|
| 256 | #endif | 
|---|
| 257 | } | 
|---|
| 258 |  | 
|---|
| 259 | StackFrameData *take_previous_frame_data() { | 
|---|
| 260 | StackFrameData *release = previous; | 
|---|
| 261 | previous = NULp;     // release ownership | 
|---|
| 262 | return release; | 
|---|
| 263 | } | 
|---|
| 264 |  | 
|---|
| 265 | void revert_resources(StackFrameData *current) { | 
|---|
| 266 | #if defined(CHECK_STACK_RESOURCE_HANDLING) | 
|---|
| 267 | ap_assert(resources_handled == NO); | 
|---|
| 268 | resources_handled = REVERTED; | 
|---|
| 269 | #endif | 
|---|
| 270 | current->revert_resources(previous); | 
|---|
| 271 | } | 
|---|
| 272 | void accept_resources(StackFrameData *current, ResourceStack *common) { | 
|---|
| 273 | #if defined(CHECK_STACK_RESOURCE_HANDLING) | 
|---|
| 274 | ap_assert(resources_handled == NO); | 
|---|
| 275 | resources_handled = ACCEPTED; | 
|---|
| 276 | #endif | 
|---|
| 277 | current->accept_resources(previous, common); | 
|---|
| 278 | } | 
|---|
| 279 |  | 
|---|
| 280 | #if defined(CHECK_ROOT_POPS) | 
|---|
| 281 | AP_tree_nlen *root_at_create; // root at creation time of stack | 
|---|
| 282 | #endif | 
|---|
| 283 | #if defined(PROVIDE_PRINT) | 
|---|
| 284 | void print(std::ostream& out, int indentLevel, Level frameNr) const; | 
|---|
| 285 | #endif | 
|---|
| 286 | }; | 
|---|
| 287 |  | 
|---|
| 288 | struct FrameStack : public AP_STACK<NodeStack> { | 
|---|
| 289 | #if defined(PROVIDE_PRINT) | 
|---|
| 290 | void print(std::ostream& out, int indentLevel = 0) const; | 
|---|
| 291 | #endif | 
|---|
| 292 | }; | 
|---|
| 293 |  | 
|---|
| 294 | #else | 
|---|
| 295 | #error AP_buffer.hxx included twice | 
|---|
| 296 | #endif // AP_BUFFER_HXX | 
|---|