~ubuntu-branches/ubuntu/intrepid/ruby1.8/intrepid-updates

« back to all changes in this revision

Viewing changes to lib/yaml/basenode.rb

  • Committer: Bazaar Package Importer
  • Author(s): akira yamada
  • Date: 2007-03-13 22:11:58 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20070313221158-h3oql37brlaf2go2
Tags: 1.8.6-1
* new upstream version, 1.8.6.
* libruby1.8 conflicts with libopenssl-ruby1.8 (< 1.8.6) (closes: #410018)
* changed packaging style to cdbs from dbs.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#
 
2
# YAML::BaseNode class
 
3
#
 
4
require 'yaml/ypath'
 
5
 
 
6
module YAML
 
7
 
 
8
    #
 
9
    # YAML Generic Model container
 
10
    #
 
11
    module BaseNode
 
12
 
 
13
        #
 
14
        # Search for YPath entry and return
 
15
        # qualified nodes.
 
16
        #
 
17
        def select( ypath_str )
 
18
            matches = match_path( ypath_str )
 
19
 
 
20
            #
 
21
            # Create a new generic view of the elements selected
 
22
            #
 
23
            if matches
 
24
                result = []
 
25
                matches.each { |m|
 
26
                    result.push m.last
 
27
                }
 
28
                YAML.transfer( 'seq', result )
 
29
            end
 
30
        end
 
31
 
 
32
        #
 
33
        # Search for YPath entry and return
 
34
        # transformed nodes.
 
35
        #
 
36
        def select!( ypath_str )
 
37
            matches = match_path( ypath_str )
 
38
 
 
39
            #
 
40
            # Create a new generic view of the elements selected
 
41
            #
 
42
            if matches
 
43
                result = []
 
44
                matches.each { |m|
 
45
                    result.push m.last.transform
 
46
                }
 
47
                result
 
48
            end
 
49
        end
 
50
 
 
51
        #
 
52
        # Search for YPath entry and return a list of
 
53
        # qualified paths.
 
54
        #
 
55
        def search( ypath_str )
 
56
            matches = match_path( ypath_str )
 
57
 
 
58
            if matches
 
59
                matches.collect { |m|
 
60
                    path = []
 
61
                    m.each_index { |i|
 
62
                        path.push m[i] if ( i % 2 ).zero?
 
63
                    }
 
64
                    "/" + path.compact.join( "/" )
 
65
                }
 
66
            end
 
67
        end
 
68
 
 
69
        def at( seg )
 
70
            if Hash === @value
 
71
                self[seg]
 
72
            elsif Array === @value and seg =~ /\A\d+\Z/ and @value[seg.to_i]
 
73
                @value[seg.to_i]
 
74
            end
 
75
        end
 
76
 
 
77
        #
 
78
        # YPath search returning a complete depth array
 
79
        #
 
80
        def match_path( ypath_str )
 
81
            depth = 0
 
82
            matches = []
 
83
            YPath.each_path( ypath_str ) do |ypath|
 
84
                seg = match_segment( ypath, 0 )
 
85
                matches += seg if seg
 
86
            end
 
87
            matches.uniq
 
88
        end
 
89
 
 
90
        #
 
91
        # Search a node for a single YPath segment
 
92
        #
 
93
        def match_segment( ypath, depth )
 
94
            deep_nodes = []
 
95
            seg = ypath.segments[ depth ]
 
96
            if seg == "/"
 
97
                unless String === @value
 
98
                    idx = -1
 
99
                    @value.collect { |v|
 
100
                        idx += 1
 
101
                        if Hash === @value
 
102
                            match_init = [v[0].transform, v[1]]
 
103
                            match_deep = v[1].match_segment( ypath, depth )
 
104
                        else
 
105
                            match_init = [idx, v]
 
106
                            match_deep = v.match_segment( ypath, depth )
 
107
                        end
 
108
                        if match_deep
 
109
                            match_deep.each { |m|
 
110
                                deep_nodes.push( match_init + m )
 
111
                            }
 
112
                        end
 
113
                    }
 
114
                end
 
115
                depth += 1
 
116
                seg = ypath.segments[ depth ]
 
117
            end
 
118
            match_nodes =
 
119
                case seg
 
120
                when "."
 
121
                    [[nil, self]]
 
122
                when ".."
 
123
                    [["..", nil]]
 
124
                when "*"
 
125
                    if @value.is_a? Enumerable
 
126
                        idx = -1
 
127
                        @value.collect { |h|
 
128
                            idx += 1
 
129
                            if Hash === @value
 
130
                                [h[0].transform, h[1]]
 
131
                            else
 
132
                                [idx, h]
 
133
                            end
 
134
                        }
 
135
                    end
 
136
                else
 
137
                    if seg =~ /^"(.*)"$/
 
138
                        seg = $1
 
139
                    elsif seg =~ /^'(.*)'$/
 
140
                        seg = $1
 
141
                    end
 
142
                    if ( v = at( seg ) )
 
143
                        [[ seg, v ]]
 
144
                    end
 
145
                end
 
146
            return deep_nodes unless match_nodes
 
147
            pred = ypath.predicates[ depth ]
 
148
            if pred
 
149
                case pred
 
150
                when /^\.=/
 
151
                    pred = $'   # '
 
152
                    match_nodes.reject! { |n|
 
153
                        n.last.value != pred
 
154
                    }
 
155
                else
 
156
                    match_nodes.reject! { |n|
 
157
                        n.last.at( pred ).nil?
 
158
                    }
 
159
                end
 
160
            end
 
161
            return match_nodes + deep_nodes unless ypath.segments.length > depth + 1
 
162
 
 
163
            #puts "DEPTH: #{depth + 1}"
 
164
            deep_nodes = []
 
165
            match_nodes.each { |n|
 
166
                if n[1].is_a? BaseNode
 
167
                    match_deep = n[1].match_segment( ypath, depth + 1 )
 
168
                    if match_deep
 
169
                        match_deep.each { |m|
 
170
                            deep_nodes.push( n + m )
 
171
                        }
 
172
                    end
 
173
                else
 
174
                    deep_nodes = []
 
175
                end
 
176
            }
 
177
            deep_nodes = nil if deep_nodes.length == 0
 
178
            deep_nodes
 
179
        end
 
180
 
 
181
        #
 
182
        # We want the node to act like as Hash
 
183
        # if it is.
 
184
        #
 
185
        def []( *key )
 
186
            if Hash === @value
 
187
                v = @value.detect { |k,v| k.transform == key.first }
 
188
                v[1] if v
 
189
            elsif Array === @value
 
190
                @value.[]( *key )
 
191
            end
 
192
        end
 
193
 
 
194
        def children
 
195
            if Hash === @value
 
196
                @value.values.collect { |c| c[1] }
 
197
            elsif Array === @value
 
198
                @value
 
199
            end
 
200
        end
 
201
 
 
202
        def children_with_index
 
203
            if Hash === @value
 
204
                @value.keys.collect { |i| [self[i], i] }
 
205
            elsif Array === @value
 
206
                i = -1; @value.collect { |v| i += 1; [v, i] }
 
207
            end
 
208
        end
 
209
 
 
210
        def emit
 
211
            transform.to_yaml
 
212
        end
 
213
    end
 
214
 
 
215
end
 
216