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