| 1 | # tree.tcl -- |
|---|
| 2 | # |
|---|
| 3 | # Implementation of a tree data structure 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: tree.tcl,v 1.44 2007/06/17 01:22:18 andreas_kupries Exp $ |
|---|
| 11 | |
|---|
| 12 | # @mdgen EXCLUDE: tree_c.tcl |
|---|
| 13 | |
|---|
| 14 | package require Tcl 8.2 |
|---|
| 15 | package require struct::list |
|---|
| 16 | |
|---|
| 17 | namespace eval ::struct::tree {} |
|---|
| 18 | |
|---|
| 19 | # ### ### ### ######### ######### ######### |
|---|
| 20 | ## Management of tree implementations. |
|---|
| 21 | |
|---|
| 22 | # ::struct::tree::LoadAccelerator -- |
|---|
| 23 | # |
|---|
| 24 | # Loads a named implementation, if possible. |
|---|
| 25 | # |
|---|
| 26 | # Arguments: |
|---|
| 27 | # key Name of the implementation to load. |
|---|
| 28 | # |
|---|
| 29 | # Results: |
|---|
| 30 | # A boolean flag. True if the implementation |
|---|
| 31 | # was successfully loaded; and False otherwise. |
|---|
| 32 | |
|---|
| 33 | proc ::struct::tree::LoadAccelerator {key} { |
|---|
| 34 | variable accel |
|---|
| 35 | set r 0 |
|---|
| 36 | switch -exact -- $key { |
|---|
| 37 | critcl { |
|---|
| 38 | # Critcl implementation of tree requires Tcl 8.4. |
|---|
| 39 | if {![package vsatisfies [package provide Tcl] 8.4]} {return 0} |
|---|
| 40 | if {[catch {package require tcllibc}]} {return 0} |
|---|
| 41 | set r [llength [info commands ::struct::tree_critcl]] |
|---|
| 42 | } |
|---|
| 43 | tcl { |
|---|
| 44 | variable selfdir |
|---|
| 45 | source [file join $selfdir tree_tcl.tcl] |
|---|
| 46 | set r 1 |
|---|
| 47 | } |
|---|
| 48 | default { |
|---|
| 49 | return -code error "invalid accelerator/impl. package $key:\ |
|---|
| 50 | must be one of [join [KnownImplementations] {, }]" |
|---|
| 51 | } |
|---|
| 52 | } |
|---|
| 53 | set accel($key) $r |
|---|
| 54 | return $r |
|---|
| 55 | } |
|---|
| 56 | |
|---|
| 57 | # ::struct::tree::SwitchTo -- |
|---|
| 58 | # |
|---|
| 59 | # Activates a loaded named implementation. |
|---|
| 60 | # |
|---|
| 61 | # Arguments: |
|---|
| 62 | # key Name of the implementation to activate. |
|---|
| 63 | # |
|---|
| 64 | # Results: |
|---|
| 65 | # None. |
|---|
| 66 | |
|---|
| 67 | proc ::struct::tree::SwitchTo {key} { |
|---|
| 68 | variable accel |
|---|
| 69 | variable loaded |
|---|
| 70 | |
|---|
| 71 | if {[string equal $key $loaded]} { |
|---|
| 72 | # No change, nothing to do. |
|---|
| 73 | return |
|---|
| 74 | } elseif {![string equal $key ""]} { |
|---|
| 75 | # Validate the target implementation of the switch. |
|---|
| 76 | |
|---|
| 77 | if {![info exists accel($key)]} { |
|---|
| 78 | return -code error "Unable to activate unknown implementation \"$key\"" |
|---|
| 79 | } elseif {![info exists accel($key)] || !$accel($key)} { |
|---|
| 80 | return -code error "Unable to activate missing implementation \"$key\"" |
|---|
| 81 | } |
|---|
| 82 | } |
|---|
| 83 | |
|---|
| 84 | # Deactivate the previous implementation, if there was any. |
|---|
| 85 | |
|---|
| 86 | if {![string equal $loaded ""]} { |
|---|
| 87 | rename ::struct::tree ::struct::tree_$loaded |
|---|
| 88 | rename ::struct::tree::prune ::struct::tree::prune_$loaded |
|---|
| 89 | } |
|---|
| 90 | |
|---|
| 91 | # Activate the new implementation, if there is any. |
|---|
| 92 | |
|---|
| 93 | if {![string equal $key ""]} { |
|---|
| 94 | rename ::struct::tree_$key ::struct::tree |
|---|
| 95 | rename ::struct::tree::prune_$key ::struct::tree::prune |
|---|
| 96 | } |
|---|
| 97 | |
|---|
| 98 | # Remember the active implementation, for deactivation by future |
|---|
| 99 | # switches. |
|---|
| 100 | |
|---|
| 101 | set loaded $key |
|---|
| 102 | return |
|---|
| 103 | } |
|---|
| 104 | |
|---|
| 105 | # ::struct::tree::Implementations -- |
|---|
| 106 | # |
|---|
| 107 | # Determines which implementations are |
|---|
| 108 | # present, i.e. loaded. |
|---|
| 109 | # |
|---|
| 110 | # Arguments: |
|---|
| 111 | # None. |
|---|
| 112 | # |
|---|
| 113 | # Results: |
|---|
| 114 | # A list of implementation keys. |
|---|
| 115 | |
|---|
| 116 | proc ::struct::tree::Implementations {} { |
|---|
| 117 | variable accel |
|---|
| 118 | set res {} |
|---|
| 119 | foreach n [array names accel] { |
|---|
| 120 | if {!$accel($n)} continue |
|---|
| 121 | lappend res $n |
|---|
| 122 | } |
|---|
| 123 | return $res |
|---|
| 124 | } |
|---|
| 125 | |
|---|
| 126 | # ::struct::tree::KnownImplementations -- |
|---|
| 127 | # |
|---|
| 128 | # Determines which implementations are known |
|---|
| 129 | # as possible implementations. |
|---|
| 130 | # |
|---|
| 131 | # Arguments: |
|---|
| 132 | # None. |
|---|
| 133 | # |
|---|
| 134 | # Results: |
|---|
| 135 | # A list of implementation keys. In the order |
|---|
| 136 | # of preference, most prefered first. |
|---|
| 137 | |
|---|
| 138 | proc ::struct::tree::KnownImplementations {} { |
|---|
| 139 | return {critcl tcl} |
|---|
| 140 | } |
|---|
| 141 | |
|---|
| 142 | proc ::struct::tree::Names {} { |
|---|
| 143 | return { |
|---|
| 144 | critcl {tcllibc based} |
|---|
| 145 | tcl {pure Tcl} |
|---|
| 146 | } |
|---|
| 147 | } |
|---|
| 148 | |
|---|
| 149 | # ### ### ### ######### ######### ######### |
|---|
| 150 | ## Initialization: Data structures. |
|---|
| 151 | |
|---|
| 152 | namespace eval ::struct::tree { |
|---|
| 153 | variable selfdir [file dirname [info script]] |
|---|
| 154 | variable accel |
|---|
| 155 | array set accel {tcl 0 critcl 0} |
|---|
| 156 | variable loaded {} |
|---|
| 157 | } |
|---|
| 158 | |
|---|
| 159 | # ### ### ### ######### ######### ######### |
|---|
| 160 | ## Initialization: Choose an implementation, |
|---|
| 161 | ## most prefered first. Loads only one of the |
|---|
| 162 | ## possible implementations. And activates it. |
|---|
| 163 | |
|---|
| 164 | namespace eval ::struct::tree { |
|---|
| 165 | variable e |
|---|
| 166 | foreach e [KnownImplementations] { |
|---|
| 167 | if {[LoadAccelerator $e]} { |
|---|
| 168 | SwitchTo $e |
|---|
| 169 | break |
|---|
| 170 | } |
|---|
| 171 | } |
|---|
| 172 | unset e |
|---|
| 173 | } |
|---|
| 174 | |
|---|
| 175 | # ### ### ### ######### ######### ######### |
|---|
| 176 | ## Ready |
|---|
| 177 | |
|---|
| 178 | namespace eval ::struct { |
|---|
| 179 | # Export the constructor command. |
|---|
| 180 | namespace export tree |
|---|
| 181 | } |
|---|
| 182 | |
|---|
| 183 | package provide struct::tree 2.1.1 |
|---|