Update stdlib and concat to 6.1.0 both
[mirror/dsa-puppet.git] / 3rdparty / modules / stdlib / lib / puppet / parser / functions / range.rb
1 #
2 # range.rb
3 #
4 # TODO(Krzysztof Wilczynski): We probably need to approach numeric values differently ...
5 module Puppet::Parser::Functions
6   newfunction(:range, :type => :rvalue, :doc => <<-DOC
7     @summary
8       When given range in the form of (start, stop) it will extrapolate a range as
9       an array.
10
11     @return
12       the range is extrapolated as an array
13
14     @example **Usage**
15       range("0", "9")
16       Will return: [0,1,2,3,4,5,6,7,8,9]
17
18       range("00", "09")
19       Will return: [0,1,2,3,4,5,6,7,8,9]
20       (Zero padded strings are converted to integers automatically)
21
22       range("a", "c")
23       Will return: ["a","b","c"]
24
25       range("host01", "host10")
26       Will return: ["host01", "host02", ..., "host09", "host10"]
27
28       range("0", "9", "2")
29       Will return: [0,2,4,6,8]
30
31     NB Be explicit in including trailing zeros. Otherwise the underlying ruby function will fail.
32
33     > *Note:*
34       Passing a third argument will cause the generated range to step by that
35       interval, e.g.
36
37     The Puppet Language support Integer and Float ranges by using the type system. Those are suitable for
38     iterating a given number of times.
39
40     @see
41       the step() function in Puppet for skipping values.
42
43      Integer[0, 9].each |$x| { notice($x) } # notices 0, 1, 2, ... 9
44     DOC
45              ) do |arguments|
46
47     raise(Puppet::ParseError, 'range(): Wrong number of arguments given (0 for 1)') if arguments.empty?
48
49     if arguments.size > 1
50       start = arguments[0]
51       stop  = arguments[1]
52       step  = arguments[2].nil? ? 1 : arguments[2].to_i.abs
53
54       type = '..' # Use the simplest type of Range available in Ruby
55
56     else # arguments.size == 1
57       value = arguments[0]
58
59       m = value.match(%r{^(\w+)(\.\.\.?|\-)(\w+)$})
60       if m
61         start = m[1]
62         stop  = m[3]
63
64         type = m[2]
65         step = 1
66       elsif value =~ %r{^.+$}
67         raise(Puppet::ParseError, "range(): Unable to compute range from the value: #{value}")
68       else
69         raise(Puppet::ParseError, "range(): Unknown range format: #{value}")
70       end
71     end
72
73     # If we were given an integer, ensure we work with one
74     if start.to_s =~ %r{^\d+$}
75       start = start.to_i
76       stop  = stop.to_i
77     else
78       start = start.to_s
79       stop  = stop.to_s
80     end
81
82     range = case type
83             when %r{^(..|-)$} then (start..stop)
84             when '...' then (start...stop) # Exclusive of last element
85             end
86
87     result = range.step(step).first(1_000_000).to_a
88
89     return result
90   end
91 end
92
93 # vim: set ts=2 sw=2 et :