module Puppet::Pops::Lookup::SubLookup

Constants

SPECIAL

Public Instance Methods

split_key(key) { |'Syntax error'| ... } click to toggle source

Split key into segments. A segment may be a quoted string (both single and double quotes can be used) and the segment separator is the '.' character. Whitespace will be trimmed off on both sides of each segment. Whitespace within quotes are not trimmed.

If the key cannot be parsed, this method will yield a string describing the problem to a one parameter block. The block must return an exception instance.

@param key [String] the string to split @return [Array<String>] the array of segments @yieldparam problem [String] the problem, i.e. 'Syntax error' @yieldreturn [Exception] the exception to raise

@api public

   # File lib/puppet/pops/lookup/sub_lookup.rb
19 def split_key(key)
20   return [key] if key.match(SPECIAL).nil?
21   segments = key.split(/(\s*"[^"]+"\s*|\s*'[^']+'\s*|[^'".]+)/)
22   if segments.empty?
23     # Only happens if the original key was an empty string
24     raise yield('Syntax error')
25   elsif segments.shift == ''
26     count = segments.size
27     raise yield('Syntax error') unless count > 0
28 
29     segments.keep_if { |seg| seg != '.' }
30     raise yield('Syntax error') unless segments.size * 2 == count + 1
31     segments.map! do |segment|
32       segment.strip!
33       if segment.start_with?('"', "'")
34         segment[1..-2]
35       elsif segment =~ /^(:?[+-]?[0-9]+)$/
36         segment.to_i
37       else
38         segment
39       end
40     end
41   else
42     raise yield('Syntax error')
43   end
44 end
sub_lookup(key, context, segments, value) click to toggle source

Perform a sub-lookup using the given segments to access the given value. Each segment must be a string. A string consisting entirely of digits will be treated as an indexed lookup which means that the value that it is applied to must be an array. Other types of segments will expect that the given value is something other than a String that implements the '#[]' method.

@param key [String] the original key (only used for error messages) @param context [Context] The current lookup context @param segments [Array<String>] the segments to use for lookup @param value [Object] the value to access using the segments @return [Object] the value obtained when accessing the value

@api public

   # File lib/puppet/pops/lookup/sub_lookup.rb
58 def sub_lookup(key, context, segments, value)
59   lookup_invocation = context.is_a?(Invocation) ? context : context.invocation
60   lookup_invocation.with(:sub_lookup, segments) do
61     segments.each do |segment|
62       lookup_invocation.with(:segment, segment) do
63         if value.nil?
64           lookup_invocation.report_not_found(segment)
65           throw :no_such_key
66         end
67         if segment.is_a?(Integer) && value.instance_of?(Array)
68           unless segment >= 0 && segment < value.size
69             lookup_invocation.report_not_found(segment)
70             throw :no_such_key
71           end
72         else
73           unless value.respond_to?(:'[]') && !(value.is_a?(Array) || value.instance_of?(String))
74             raise Puppet::DataBinding::LookupError,
75               _("Data Provider type mismatch: Got %{klass} when a hash-like object was expected to access value using '%{segment}' from key '%{key}'") %
76                 { klass: value.class.name, segment: segment, key: key }
77           end
78           unless value.include?(segment)
79             lookup_invocation.report_not_found(segment)
80             throw :no_such_key
81           end
82         end
83         value = value[segment]
84         lookup_invocation.report_found(segment, value)
85       end
86     end
87     value
88   end
89 end