class Puppet::Pops::Types::StringConverter::Format

Format represents one format specification that is textually represented by %<flags><width>.<precision><format> Format parses and makes the individual parts available when an instance is created.

@api private

Constants

DELIMITERS
DELIMITER_MAP
FMT_PATTERN
FMT_PATTERN_STR

Attributes

alt[R]

Boolean, alternate form (varies in meaning)

alt?[R]

Boolean, alternate form (varies in meaning)

container_string_formats[RW]

Map of type to format for elements contained in an object this format applies to

delimiters[R]

Delimiters for containers, a “left” char representing the pair <[{(

format[R]

One char symbol denoting the format

left[R]

Boolean, left adjust in given width or not

orig_fmt[R]
plus[R]

Symbol, :space, :plus, :ignore

prec[R]

Nil or Integer precisions

separator[RW]

Separator string inserted between elements in a container

separator2[RW]

Separator string inserted between sub elements in a container

width[R]

Nil or Integer with width of field > 0

zero_pad[R]

Boolean left_pad with zero instead of space

Public Class Methods

merge(lower, higher) click to toggle source

Merges two formats where the `higher` format overrides the `lower`. Produces a new `Format` @param [Format] lower @param [Format] higher @returns [Format] the merged result

    # File lib/puppet/pops/types/string_converter.rb
153 def self.merge(lower, higher)
154   unless lower && higher
155     return lower || higher
156   end
157   lower.merge(higher)
158 end
merge_string_formats(lower, higher) click to toggle source

Merges a type => format association and returns a new merged and sorted association. @param [Format] lower @param [Format] higher @returns [Hash] the merged type => format result

    # File lib/puppet/pops/types/string_converter.rb
165 def self.merge_string_formats(lower, higher)
166   unless lower && higher
167     return lower || higher
168   end
169 
170   # drop all formats in lower than is more generic in higher. Lower must never
171   # override higher
172   lower = lower.reject { |lk, _| higher.keys.any? { |hk| hk != lk && hk.assignable?(lk) }}
173 
174   merged = (lower.keys + higher.keys).uniq.map do |k|
175     [k, merge(lower[k], higher[k])]
176   end
177   sort_formats(merged)
178 end
new(fmt) click to toggle source
    # File lib/puppet/pops/types/string_converter.rb
102 def initialize(fmt)
103   @orig_fmt = fmt
104   match = FMT_PATTERN.match(fmt)
105   unless match
106     raise ArgumentError, "The format '#{fmt}' is not a valid format on the form '%<flags><width>.<prec><format>'"
107   end
108 
109   @format = match[4]
110   unless @format.is_a?(String) && @format.length == 1
111     raise ArgumentError, "The format must be a one letter format specifier, got '#{@format}'"
112   end
113   @format = @format.to_sym
114   flags  = match[1].split('') || []
115   unless flags.uniq.size == flags.size
116     raise ArgumentError, "The same flag can only be used once, got '#{fmt}'"
117   end
118   @left  = flags.include?('-')
119   @alt   = flags.include?('#')
120   @plus  = (flags.include?(' ') ? :space : (flags.include?('+') ? :plus : :ignore))
121   @zero_pad = flags.include?('0')
122 
123   @delimiters = nil
124   DELIMITERS.each do |d|
125     next unless flags.include?(d)
126       if !@delimiters.nil?
127         raise ArgumentError, "Only one of the delimiters [ { ( < | can be given in the format flags, got '#{fmt}'"
128       end
129       @delimiters = d
130   end
131 
132   @width = match[2] ? match[2].to_i : nil
133   @prec  = match[3] ? match[3].to_i : nil
134 end
sort_formats(format_map) click to toggle source

Sorts format based on generality of types - most specific types before general

    # File lib/puppet/pops/types/string_converter.rb
182 def self.sort_formats(format_map)
183   format_map = format_map.sort do |(a,_),(b,_)|
184     ab = b.assignable?(a)
185     ba = a.assignable?(b)
186     if a == b
187       0
188     elsif ab && !ba
189       -1
190     elsif !ab && ba
191       1
192     else
193       # arbitrary order if disjunct (based on name of type)
194       rank_a = type_rank(a)
195       rank_b = type_rank(b)
196       if rank_a == 0 || rank_b == 0
197         a.to_s <=> b.to_s
198       else
199         rank_a <=> rank_b
200       end
201     end
202   end
203   Hash[format_map]
204 end
type_rank(t) click to toggle source

Ranks type on specificity where it matters lower number means more specific

    # File lib/puppet/pops/types/string_converter.rb
208 def self.type_rank(t)
209   case t
210   when PStructType
211     1
212   when PHashType
213     2
214   when PTupleType
215     3
216   when PArrayType
217     4
218   when PPatternType
219     10
220   when PEnumType
221     11
222   when PStringType
223     12
224   else
225     0
226   end
227 end

Public Instance Methods

delimiter_pair(default = StringConverter::DEFAULT_ARRAY_DELIMITERS) click to toggle source

Returns an array with a delimiter pair derived from the format. If format does not contain a delimiter specification the given default is returned

@param [Array<String>] the default delimiters @returns [Array<String>] a tuple with left, right delimiters

    # File lib/puppet/pops/types/string_converter.rb
234 def delimiter_pair(default = StringConverter::DEFAULT_ARRAY_DELIMITERS)
235   DELIMITER_MAP[ @delimiters || @plus ] || default
236 end
merge(other) click to toggle source

Merges one format into this and returns a new `Format`. The `other` format overrides this. @param [Format] other @returns [Format] a merged format

    # File lib/puppet/pops/types/string_converter.rb
140 def merge(other)
141   result = Format.new(other.orig_fmt)
142   result.separator = other.separator || separator
143   result.separator2 = other.separator2 || separator2
144   result.container_string_formats = Format.merge_string_formats(container_string_formats, other.container_string_formats)
145   result
146 end
to_s() click to toggle source
    # File lib/puppet/pops/types/string_converter.rb
238 def to_s
239   "%#{@flags}#{@width}.#{@prec}#{@format}"
240 end