]> git.donarmstrong.com Git - lilypond.git/blob - flower/include/cons.hh
31fc4ede97033b0e00a6ad780474c3fb0849f1e3
[lilypond.git] / flower / include / cons.hh
1 /*
2   cons.hh -- declare LISP like datatypes
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1999--2005 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8
9 #ifndef CONS_HH
10 #define CONS_HH
11
12 #include <cassert>
13 using namespace std;
14
15 template<class T>
16 class Cons
17 {
18 public:
19   T *car_;
20   Cons *next_;
21   Cons ()
22   {
23     car_ = 0;
24     next_ = 0;
25   }
26   Cons (T *t, Cons<T> *c)
27   {
28     car_ = t;
29     next_ = c;
30   }
31   virtual ~Cons ()
32   {
33     delete next_;
34   }
35 };
36
37 template<class T>
38 class Killing_cons : public Cons<T>
39 {
40 public:
41   Killing_cons (T *t, Cons<T> *p)
42     : Cons<T> (t, p)
43   {
44   }
45   virtual ~Killing_cons ();
46 };
47
48 /// remove the link pointed to by *p.
49 template<class T>
50 Cons<T> *remove_cons (Cons<T> **pp)
51 {
52   Cons<T> *knip = *pp;
53   *pp = (*pp)->next_;
54   knip->next_ = 0;
55   return knip;
56 }
57
58 template<class T> int cons_list_size (Cons<T> *l)
59 {
60   int i = 0;
61   while (l)
62     {
63       l = l->next_;
64       i++;
65     }
66   return i;
67 }
68
69 template<class T>
70 Cons<T> *last_cons (Cons<T> *head)
71 {
72   while (head && head->next_)
73     head = head->next_;
74   return head;
75 }
76
77 /**
78
79 Invariants:
80
81 (*tail_) is either the head_ pointer, or a next_ pointer from the list.
82
83 **tail_ == NULL
84 */
85
86 template<class T>
87 class Cons_list
88 {
89 public:
90   Cons<T> *head_;
91   Cons<T> ** nil_pointer_address_;
92   Cons_list ()
93   {
94     init ();
95   }
96   void init ()
97   {
98     head_ = 0;
99     nil_pointer_address_ = &head_;
100   }
101   void append (T *c)
102   {
103     append (new Cons<T> (c, 0));
104   }
105   void append (Cons<T> *c)
106   {
107     assert (!c->next_);
108     *nil_pointer_address_ = c;
109     while (*nil_pointer_address_)
110       nil_pointer_address_ = &(*nil_pointer_address_)->next_;
111   }
112   /**
113      PRE: *pp should either be the head_ pointer, or the next_ pointer
114      from a list cell.
115   */
116   Cons<T> *remove_cons (Cons<T> **pp)
117   {
118     if (& (*pp)->next_ == nil_pointer_address_)
119       nil_pointer_address_ = pp;
120
121     return ::remove_cons (pp);
122   }
123
124   /// junk everything after the  first I elements.
125   void truncate (int i)
126   {
127     Cons<T> **p = &head_;
128     for (; *p && i; p = &((*p)->next_))
129       i--;
130
131     if (*p)
132       {
133         delete *p;
134         *p = 0;
135       }
136     nil_pointer_address_ = p;
137   }
138
139   void junk ()
140   {
141     delete head_;
142     head_ = 0;
143   }
144   ~Cons_list ()
145   {
146     junk ();
147   }
148   int size ()
149   {
150     return cons_list_size (head_);
151   }
152 };
153
154 template<class T>
155 void copy_killing_cons_list (Cons_list<T> &, Cons<T> *src);
156 template<class T>
157 void
158 clone_killing_cons_list (Cons_list<T> &, Cons<T> *src);
159
160 #endif /* CONS_HH */
161