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
154 def self.merge(lower, higher)
155   unless lower && higher
156     return lower || higher
157   end
158   lower.merge(higher)
159 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
166 def self.merge_string_formats(lower, higher)
167   unless lower && higher
168     return lower || higher
169   end
170 
171   # drop all formats in lower than is more generic in higher. Lower must never
172   # override higher
173   lower = lower.reject { |lk, _| higher.keys.any? { |hk| hk != lk && hk.assignable?(lk) }}
174 
175   merged = (lower.keys + higher.keys).uniq.map do |k|
176     [k, merge(lower[k], higher[k])]
177   end
178   sort_formats(merged)
179 end
new(fmt) click to toggle source
    # File lib/puppet/pops/types/string_converter.rb
103 def initialize(fmt)
104   @orig_fmt = fmt
105   match = FMT_PATTERN.match(fmt)
106   unless match
107     raise ArgumentError, "The format '#{fmt}' is not a valid format on the form '%<flags><width>.<prec><format>'"
108   end
109 
110   @format = match[4]
111   unless @format.is_a?(String) && @format.length == 1
112     raise ArgumentError, "The format must be a one letter format specifier, got '#{@format}'"
113   end
114   @format = @format.to_sym
115   flags  = match[1].split('') || []
116   unless flags.uniq.size == flags.size
117     raise ArgumentError, "The same flag can only be used once, got '#{fmt}'"
118   end
119   @left  = flags.include?('-')
120   @alt   = flags.include?('#')
121   @plus  = (flags.include?(' ') ? :space : (flags.include?('+') ? :plus : :ignore))
122   @zero_pad = flags.include?('0')
123 
124   @delimiters = nil
125   DELIMITERS.each do |d|
126     next unless flags.include?(d)
127       if !@delimiters.nil?
128         raise ArgumentError, "Only one of the delimiters [ { ( < | can be given in the format flags, got '#{fmt}'"
129       end
130       @delimiters = d
131   end
132 
133   @width = match[2] ? match[2].to_i : nil
134   @prec  = match[3] ? match[3].to_i : nil
135 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
183 def self.sort_formats(format_map)
184   format_map = format_map.sort do |(a,_),(b,_)|
185     ab = b.assignable?(a)
186     ba = a.assignable?(b)
187     if a == b
188       0
189     elsif ab && !ba
190       -1
191     elsif !ab && ba
192       1
193     else
194       # arbitrary order if disjunct (based on name of type)
195       rank_a = type_rank(a)
196       rank_b = type_rank(b)
197       if rank_a == 0 || rank_b == 0
198         a.to_s <=> b.to_s
199       else
200         rank_a <=> rank_b
201       end
202     end
203   end
204   Hash[format_map]
205 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
209 def self.type_rank(t)
210   case t
211   when PStructType
212     1
213   when PHashType
214     2
215   when PTupleType
216     3
217   when PArrayType
218     4
219   when PPatternType
220     10
221   when PEnumType
222     11
223   when PStringType
224     12
225   else
226     0
227   end
228 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
235 def delimiter_pair(default = StringConverter::DEFAULT_ARRAY_DELIMITERS)
236   DELIMITER_MAP[ @delimiters || @plus ] || default
237 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
141 def merge(other)
142   result = Format.new(other.orig_fmt)
143   result.separator = other.separator || separator
144   result.separator2 = other.separator2 || separator2
145   result.container_string_formats = Format.merge_string_formats(container_string_formats, other.container_string_formats)
146   result
147 end
to_s() click to toggle source
    # File lib/puppet/pops/types/string_converter.rb
239 def to_s
240   "%#{@flags}#{@width}.#{@prec}#{@format}"
241 end