source: tol/tolsh/tolsh.vfs/lib/tcllib1.10/struct/stack.tcl @ 8227d4c

1941-docker-image-to-testdevel
Last change on this file since 8227d4c was 8597867d, checked in by Jorge Pérez <josp.jorge@…>, 16 years ago

closes #976, se incluye tcllib1.10, base64 debe eliminarse del raiz de lib ya que esta incluido en tcllib

git-svn-id: ​https://www.tol-project.org/svn/tolp/trunk@2556 be4846ae-f051-483a-831f-b64e7d08527f

  • Property mode set to 100644
File size: 6.9 KB
Line 
1# stack.tcl --
2#
3#       Stack implementation for Tcl.
4#
5# Copyright (c) 1998-2000 by Ajuba Solutions.
6#
7# See the file "license.terms" for information on usage and redistribution
8# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
9#
10# RCS: @(#) $Id: stack.tcl,v 1.13 2005/10/03 17:52:22 andreas_kupries Exp $
11
12namespace eval ::struct {}
13
14namespace eval ::struct::stack {
15    # The stacks array holds all of the stacks you've made
16    variable stacks
17   
18    # counter is used to give a unique name for unnamed stacks
19    variable counter 0
20
21    # Only export one command, the one used to instantiate a new stack
22    namespace export stack
23}
24
25# ::struct::stack::stack --
26#
27#       Create a new stack with a given name; if no name is given, use
28#       stackX, where X is a number.
29#
30# Arguments:
31#       name    name of the stack; if null, generate one.
32#
33# Results:
34#       name    name of the stack created
35
36proc ::struct::stack::stack {args} {
37    variable stacks
38    variable counter
39   
40    switch -exact -- [llength [info level 0]] {
41        1 {
42            # Missing name, generate one.
43            incr counter
44            set name "stack${counter}"
45        }
46        2 {
47            # Standard call. New empty stack.
48            set name [lindex $args 0]
49        }
50        default {
51            # Error.
52            return -code error \
53                    "wrong # args: should be \"stack ?name?\""
54        }
55    }
56
57    # FIRST, qualify the name.
58    if {![string match "::*" $name]} {
59        # Get caller's namespace; append :: if not global namespace.
60        set ns [uplevel 1 [list namespace current]]
61        if {"::" != $ns} {
62            append ns "::"
63        }
64
65        set name "$ns$name"
66    }
67    if {[llength [info commands $name]]} {
68        return -code error \
69                "command \"$name\" already exists, unable to create stack"
70    }
71
72    set stacks($name) [list ]
73
74    # Create the command to manipulate the stack
75    interp alias {} $name {} ::struct::stack::StackProc $name
76
77    return $name
78}
79
80##########################
81# Private functions follow
82
83# ::struct::stack::StackProc --
84#
85#       Command that processes all stack object commands.
86#
87# Arguments:
88#       name    name of the stack object to manipulate.
89#       args    command name and args for the command
90#
91# Results:
92#       Varies based on command to perform
93
94proc ::struct::stack::StackProc {name cmd args} {
95    # Do minimal args checks here
96    if { [llength [info level 0]] == 2 } {
97        return -code error "wrong # args: should be \"$name option ?arg arg ...?\""
98    }
99
100    # Split the args into command and args components
101    set sub _$cmd
102    if { [llength [info commands ::struct::stack::$sub]] == 0 } {
103        set optlist [lsort [info commands ::struct::stack::_*]]
104        set xlist {}
105        foreach p $optlist {
106            set p [namespace tail $p]
107            lappend xlist [string range $p 1 end]
108        }
109        set optlist [linsert [join $xlist ", "] "end-1" "or"]
110        return -code error \
111                "bad option \"$cmd\": must be $optlist"
112    }
113
114    uplevel 1 [linsert $args 0 ::struct::stack::$sub $name]
115}
116
117# ::struct::stack::_clear --
118#
119#       Clear a stack.
120#
121# Arguments:
122#       name    name of the stack object.
123#
124# Results:
125#       None.
126
127proc ::struct::stack::_clear {name} {
128    set ::struct::stack::stacks($name) [list ]
129    return
130}
131
132# ::struct::stack::_destroy --
133#
134#       Destroy a stack object by removing it's storage space and
135#       eliminating it's proc.
136#
137# Arguments:
138#       name    name of the stack object.
139#
140# Results:
141#       None.
142
143proc ::struct::stack::_destroy {name} {
144    unset ::struct::stack::stacks($name)
145    interp alias {} $name {}
146    return
147}
148
149# ::struct::stack::_peek --
150#
151#       Retrieve the value of an item on the stack without popping it.
152#
153# Arguments:
154#       name    name of the stack object.
155#       count   number of items to pop; defaults to 1
156#
157# Results:
158#       items   top count items from the stack; if there are not enough items
159#               to fulfill the request, throws an error.
160
161proc ::struct::stack::_peek {name {count 1}} {
162    variable stacks
163    if { $count < 1 } {
164        error "invalid item count $count"
165    }
166
167    if { $count > [llength $stacks($name)] } {
168        error "insufficient items on stack to fill request"
169    }
170
171    if { $count == 1 } {
172        # Handle this as a special case, so single item pops aren't listified
173        set item [lindex $stacks($name) end]
174        return $item
175    }
176
177    # Otherwise, return a list of items
178    set result [list ]
179    for {set i 0} {$i < $count} {incr i} {
180        lappend result [lindex $stacks($name) "end-${i}"]
181    }
182    return $result
183}
184
185# ::struct::stack::_pop --
186#
187#       Pop an item off a stack.
188#
189# Arguments:
190#       name    name of the stack object.
191#       count   number of items to pop; defaults to 1
192#
193# Results:
194#       item    top count items from the stack; if the stack is empty,
195#               returns a list of count nulls.
196
197proc ::struct::stack::_pop {name {count 1}} {
198    variable stacks
199    if { $count > [llength $stacks($name)] } {
200        error "insufficient items on stack to fill request"
201    } elseif { $count < 1 } {
202        error "invalid item count $count"
203    }
204
205    if { $count == 1 } {
206        # Handle this as a special case, so single item pops aren't listified
207        set item [lindex $stacks($name) end]
208        set stacks($name) [lreplace $stacks($name) end end]
209        return $item
210    }
211
212    # Otherwise, return a list of items
213    set result [list ]
214    for {set i 0} {$i < $count} {incr i} {
215        lappend result [lindex $stacks($name) "end-${i}"]
216    }
217
218    # Remove these items from the stack
219    incr i -1
220    set stacks($name) [lreplace $stacks($name) "end-${i}" end]
221
222    return $result
223}
224
225# ::struct::stack::_push --
226#
227#       Push an item onto a stack.
228#
229# Arguments:
230#       name    name of the stack object
231#       args    items to push.
232#
233# Results:
234#       None.
235
236proc ::struct::stack::_push {name args} {
237    if { [llength $args] == 0 } {
238        error "wrong # args: should be \"$name push item ?item ...?\""
239    }
240    foreach item $args {
241        lappend ::struct::stack::stacks($name) $item
242    }
243}
244
245# ::struct::stack::_rotate --
246#
247#       Rotate the top count number of items by step number of steps.
248#
249# Arguments:
250#       name    name of the stack object.
251#       count   number of items to rotate.
252#       steps   number of steps to rotate.
253#
254# Results:
255#       None.
256
257proc ::struct::stack::_rotate {name count steps} {
258    variable stacks
259    set len [llength $stacks($name)]
260    if { $count > $len } {
261        error "insufficient items on stack to fill request"
262    }
263
264    # Rotation algorithm:
265    # do
266    #   Find the insertion point in the stack
267    #   Move the end item to the insertion point
268    # repeat $steps times
269
270    set start [expr {$len - $count}]
271    set steps [expr {$steps % $count}]
272    for {set i 0} {$i < $steps} {incr i} {
273        set item [lindex $stacks($name) end]
274        set stacks($name) [lreplace $stacks($name) end end]
275        set stacks($name) [linsert $stacks($name) $start $item]
276    }
277    return
278}
279
280# ::struct::stack::_size --
281#
282#       Return the number of objects on a stack.
283#
284# Arguments:
285#       name    name of the stack object.
286#
287# Results:
288#       count   number of items on the stack.
289
290proc ::struct::stack::_size {name} {
291    return [llength $::struct::stack::stacks($name)]
292}
293
294# ### ### ### ######### ######### #########
295## Ready
296
297namespace eval ::struct {
298    # Get 'stack::stack' into the general structure namespace.
299    namespace import -force stack::stack
300    namespace export stack
301}
302package provide struct::stack 1.3.1
Note: See TracBrowser for help on using the repository browser.