Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/tools/build/v2/util/container.jam @ 12

Last change on this file since 12 was 12, checked in by landauf, 17 years ago

added boost

File size: 8.0 KB
Line 
1# (C) Copyright Rene Rivera, 2002.
2#
3# See accompanying license for terms and conditions of use.
4#
5
6# Various container classes.
7
8import "class" : * ;
9
10# Base for container objects. This lets us construct recursive structures.
11# That is containers with containers in them, specifically so we can tell
12# literal values from node values.
13#
14class node
15{
16    rule __init__ (
17      value ? # Optional value to set node to initially.
18    )
19    {
20        self.value = $(value) ;
21    }
22       
23    # Set the value of this node, passing nothing will clear it.
24    #
25    rule set ( value * )
26    {
27        self.value = $(value) ;
28    }
29   
30    # Get the value of this node.
31    #
32    rule get ( )
33    {
34        return $(self.value) ;
35    }
36}
37
38
39# A simple vector. Interface mimics the C++ std::vector and std::list,
40# with the exception that indices are one (1) based to follow Jam standard.
41#
42# TODO: Possibly add assertion checks.
43#
44class vector : node
45{
46    import numbers : range ;
47    import utility ;
48    import sequence ;
49       
50    rule __init__ (
51      values * # Initial contents of vector.
52    )
53    {
54        node.__init__ ;
55        self.value = $(values) ;
56    }   
57   
58    # Get the value of the first element.
59    #
60    rule front ( )
61    {
62        return $(self.value[1]) ;
63    }
64   
65    # Get the value of the last element.
66    #
67    rule back ( )
68    {
69        return $(self.value[-1]) ;
70    }
71   
72    # Get the value of the element at the given index, one based.
73    # Access to elements of recursive structures is supported directly.
74    # Specifying additional index values recursively accesses the elements as
75    # containers. For example: [ $(v).at 1 : 2 ] would retrieve the second element
76    # of our first element. This assuming the first element is a container.
77    #
78    rule at (
79        index # The element index, one based.
80        : * # Additional indices to access recursively.
81        )
82    {
83        local r = $(self.value[$(index)]) ;
84        if $(2)
85        {
86            r = [ $(r).at $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ] ;
87        }
88        return $(r) ;
89    }
90   
91    # Get the value contained in the given element. This has the same
92    # functionality and interface as "at" but in addition gets the value
93    # of the referenced element, assuming it's a "node".
94    #
95    rule get-at (
96        index # The element index, one based.
97        : * # Additional indices to access recursively.
98        )
99    {
100        local r = $(self.value[$(index)]) ;
101        if $(2)
102        {
103            r = [ $(r).at $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ] ;
104        }
105        return [ $(r).get ] ;
106    }
107   
108    # Insert the given value into the front of the vector pushing the
109    # rest of the elements back.
110    #
111    rule push-front (
112        value # Value to become first element.
113        )
114    {
115        self.value = $(value) $(self.value) ;
116    }
117   
118    # Remove the front element from the vector. Does not return the value.
119    # No effect if vector is empty.
120    #
121    rule pop-front ( )
122    {
123        self.value = $(self.value[2-]) ;
124    }
125   
126    # Add the given value at the end of the vector.
127    #
128    rule push-back (
129        value # Value to become back element.
130        )
131    {
132        self.value += $(value) ;
133    }
134   
135    # Remove the back element from the vector. Does not return the value.
136    # No effect if vector is empty.
137    #
138    rule pop-back ( )
139    {
140        self.value = $(self.value[1--2]) ;
141    }
142   
143    # Insert the given value at the given index, one based. The values
144    # at and to the right of the of the index are push back to make room
145    # for the new value.
146    #
147    rule insert (
148        index # The index to insert at, one based.
149        : value # The value to insert.
150        )
151    {
152        local left = $(self.value[1-$(index)]) ;
153        left = $(left[1--2]) ;
154        local right = $(self.value[$(index)-]) ;
155        self.value = $(left) $(value) $(right) ;
156    }
157   
158    # Remove one or more elements from the vector. The range is inclusive,
159    # and not specifying an end is equivalent to the [start,start] range.
160    #
161    rule erase (
162        start # Index of first element ro remove.
163        end ? # Optional, index of last element to remove.
164        )
165    {
166        end ?= $(start) ;
167        local left = $(self.value[1-$(start)]) ;
168        left = $(left[1--2]) ;
169        local right = $(self.value[$(end)-]) ;
170        right = $(right[2-]) ;
171        self.value = $(left) $(right) ;
172    }
173   
174    # Remove all elements from the vector.
175    #
176    rule clear ( )
177    {
178        self.value = ;
179    }
180   
181    # The number of elements in the vector.
182    #
183    rule size ( )
184    {
185        return [ sequence.length $(self.value) ] ;
186    }
187   
188    # Returns "true" if there are NO elements in the vector, empty
189    # otherwise.
190    #
191    rule empty ( )
192    {
193        if ! $(self.value)
194        {
195            return true ;
196        }
197    }
198
199    # Returns the list of all valid indices for this vector.
200    rule indices ( )
201    {
202        if ! [ empty ]
203        {
204            local size = [ size ] ;
205            return [ range 1 : $(size) ] $(size) ;
206        }     
207    }
208
209    # Returns the textual representation of content.
210    rule str ( )
211    {
212        return "[" [ sequence.transform utility.str : $(self.value) ] "]" ;
213    }
214
215    # Sorts the vector inplace, calling 'utility.less' for
216    # comparisons.
217    # NOTE: this rule is unused at the moment.
218    rule sort ( )
219    {
220        self.value =
221            [ sequence.insertion-sort $(self.value) : utility.less ] ;
222    }
223
224    # Returns true if content is equal to the content of other vector.
225    # Uses 'utility.equal' for comparison.
226    rule equal ( another )
227    {       
228        local mismatch ;
229        if [ size ] = [ $(another).size ]
230        {
231            for local i in [ indices ]
232            {
233                if ! [ utility.equal [ at $(i) ] [ $(another).at $(i) ] ]
234                {
235                    mismatch = true ;
236                }
237            }
238        }
239        else
240        {
241            mismatch = true ;
242        }
243                       
244        if ! $(mismatch)
245        {
246            return true ;
247        }
248    }
249}
250
251local rule __test__ ( )
252{
253    import assert ;
254    import "class" : new ;
255   
256    local l = [ new vector ] ;
257    assert.result 0 : $(l).size ;
258    assert.result : $(l).indices ;
259    assert.result "[" "]" : $(l).str ;
260    $(l).push-back b ;
261    $(l).push-front a ;
262    assert.result 1 2 : $(l).indices ;
263    assert.result "[" a b "]" : $(l).str ;
264    assert.result a : $(l).front ;
265    assert.result b : $(l).back ;
266    $(l).insert 2 : d ;
267    $(l).insert 2 : c ;
268    $(l).insert 4 : f ;
269    $(l).insert 4 : e ;
270    $(l).pop-back ;
271    assert.result 5 : $(l).size ;
272    assert.result d : $(l).at 3 ;
273    $(l).pop-front ;
274    assert.result c : $(l).front ;
275    assert.false $(l).empty ;
276    $(l).erase 3 4 ;
277    assert.result 2 : $(l).size ;
278   
279    local l2 = [ new vector q w e r t y ] ;
280    assert.result 6 : $(l2).size ;
281    $(l).push-back $(l2) ;
282    assert.result 3 : $(l).size ;
283    local l2-alias = [ $(l).back ] ;
284    assert.result e : $(l2-alias).at 3 ;
285    $(l).clear ;
286    assert.true $(l).empty ;
287    assert.false $(l2-alias).empty ;
288    $(l2).pop-back ;
289    assert.result t : $(l2-alias).back ;
290   
291    local l3 = [ new vector ] ;
292    $(l3).push-back [ new vector 1 2 3 4 5 ] ;
293    $(l3).push-back [ new vector a b c ] ;
294    assert.result "[" "[" 1 2 3 4 5 "]" "[" a b c "]" "]" : $(l3).str ;
295    $(l3).push-back [ new vector [ new vector x y z ] [ new vector 7 8 9 ] ] ;
296    assert.result 1 : $(l3).at 1 : 1 ;
297    assert.result b : $(l3).at 2 : 2 ;
298    assert.result a b c : $(l3).get-at 2 ;
299    assert.result 7 8 9 : $(l3).get-at 3 : 2 ;
300
301    local l4 = [ new vector 4 3 6 ] ;
302    $(l4).sort ;
303    assert.result 3 4 6 : $(l4).get ;
304
305    assert.false $(l4).equal $(l3) ;
306    local l5 = [ new vector 3 4 6 ] ;
307    assert.true $(l4).equal $(l5) ;
308    # Check that vectors of different sizes are considered non-equal
309    $(l5).pop-back ;   
310    assert.false $(l4).equal $(l5) ;
311    local l6 = [ new vector [ new vector 1 2 3 ] ] ;
312    assert.true $(l6).equal [ new vector [ new vector 1 2 3 ] ] ;
313}
Note: See TracBrowser for help on using the repository browser.