class Puppet::Pops::Types::StringConverter

Converts Puppet runtime objects to String under the control of a Format. Use from Puppet Language is via the function `new`.

@api private

Constants

DEFAULT_ARRAY_DELIMITERS
DEFAULT_ARRAY_FORMAT
DEFAULT_CONTAINER_FORMATS

format used by default for values in a container (basically strings are quoted since they may contain a ','))

DEFAULT_HASH_DELIMITERS
DEFAULT_HASH_FORMAT
DEFAULT_INDENTATION
DEFAULT_PARAMETER_FORMAT
DEFAULT_STRING_FORMATS
FMT_KEYS

Public Class Methods

convert(value, string_formats = :default) click to toggle source

@api public

    # File lib/puppet/pops/types/string_converter.rb
247 def self.convert(value, string_formats = :default)
248   singleton.convert(value, string_formats)
249 end
new() click to toggle source

@api private

    # File lib/puppet/pops/types/string_converter.rb
253 def initialize
254   @string_visitor = Visitor.new(self, "string", 3, 3)
255 end

Public Instance Methods

convert(value, string_formats = :default) click to toggle source

Converts the given value to a String, under the direction of formatting rules per type.

When converting to string it is possible to use a set of built in conversion rules.

A format is specified on the form:

´´´ %[Flags][.Precision]Format ´´´

`Width` is the number of characters into which the value should be fitted. This allocated space is padded if value is shorter. By default it is space padded, and the flag 0 will cause padding with 0 for numerical formats.

`Precision` is the number of fractional digits to show for floating point, and the maximum characters included in a string format.

Note that all data type supports the formats `s` and `p` with the meaning “default to-string” and “default-programmatic to-string”.

### Integer

| Format | Integer Formats | —— | ————— | d | Decimal, negative values produces leading '-' | x X | Hexadecimal in lower or upper case. Uses ..f/..F for negative values unless # is also used | o | Octal. Uses ..0 for negative values unless # is also used | b B | Binary with prefix 'b' or 'B'. Uses ..1/..1 for negative values unless # is also used | c | numeric value representing a Unicode value, result is a one unicode character string, quoted if alternative flag # is used | s | same as d, or d in quotes if alternative flag # is used | p | same as d | eEfgGaA | converts integer to float and formats using the floating point rules

Defaults to `d`

### Float

| Format | Float formats | —— | ————- | f | floating point in non exponential notation | e E | exponential notation with 'e' or 'E' | g G | conditional exponential with 'e' or 'E' if exponent < -4 or >= the precision | a A | hexadecimal exponential form, using 'x'/'X' as prefix and 'p'/'P' before exponent | s | converted to string using format p, then applying string formatting rule, alternate form # quotes result | p | f format with minimum significant number of fractional digits, prec has no effect | dxXobBc | converts float to integer and formats using the integer rules

Defaults to `p`

### String

| Format | String | —— | —— | s | unquoted string, verbatim output of control chars | p | programmatic representation - strings are quoted, interior quotes and control chars are escaped

| C | each

name segment capitalized, quoted if alternative flag # is used

| c | capitalized string, quoted if alternative flag # is used | d | downcased string, quoted if alternative flag # is used | u | upcased string, quoted if alternative flag # is used | t | trims leading and trailing whitespace from the string, quoted if alternative flag # is used

Defaults to `s` at top level and `p` inside array or hash.

### Boolean

| Format | Boolean Formats | —- | ——————- | t T | 'true'/'false' or 'True'/'False' , first char if alternate form is used (i.e. 't'/'f' or 'T'/'F'). | y Y | 'yes'/'no', 'Yes'/'No', 'y'/'n' or 'Y'/'N' if alternative flag # is used | dxXobB | numeric value 0/1 in accordance with the given format which must be valid integer format | eEfgGaA | numeric value 0.0/1.0 in accordance with the given float format and flags | s | 'true' / 'false' | p | 'true' / 'false'

### Regexp

| Format | Regexp Formats (%/) | —- | —————— | s | / / delimiters, alternate flag replaces / delimiters with quotes | p | / / delimiters

### Undef

| Format | Undef formats | —— | ————- | s | empty string, or quoted empty string if alternative flag # is used | p | 'undef', or quoted '“undef”' if alternative flag # is used | n | 'nil', or 'null' if alternative flag # is used | dxXobB | 'NaN' | eEfgGaA | 'NaN' | v | 'n/a' | V | 'N/A' | u | 'undef', or 'undefined' if alternative # flag is used

### Default (value)

| Format | Default formats | —— | ————— | d D | 'default' or 'Default', alternative form # causes value to be quoted | s | same as d | p | same as d

### Binary (value)

| Format | Default formats | —— | ————— | s | binary as unquoted characters | p | 'Binary(“<base64strict>”)' | b | '<base64>' - base64 string with newlines inserted | B | '<base64strict>' - base64 strict string (without newlines inserted) | u | '<base64urlsafe>' - base64 urlsafe string | t | 'Binary' - outputs the name of the type only | T | 'BINARY' - output the name of the type in all caps only

The alternate form flag `#` will quote the binary or base64 text output The width and precision values are applied to the text part only in `%p` format.

### Array & Tuple

| Format | Array/Tuple Formats | —— | ————- | a | formats with `[ ]` delimiters and `,`, alternate form `#` indents nested arrays/hashes | s | same as a | p | same as a

See “Flags” `<[({|` for formatting of delimiters, and “Additional parameters for containers; Array and Hash” for more information about options.

The alternate form flag `#` will cause indentation of nested array or hash containers. If width is also set it is taken as the maximum allowed length of a sequence of elements (not including delimiters). If this max length is exceeded, each element will be indented.

### Hash & Struct

| Format | Hash/Struct Formats | —— | ————- | h | formats with `{ }` delimiters, `,` element separator and ` => ` inner element separator unless overridden by flags | s | same as h | p | same as h | a | converts the hash to an array of [k,v] tuples and formats it using array rule(s)

See “Flags” `<[({|` for formatting of delimiters, and “Additional parameters for containers; Array and Hash” for more information about options.

The alternate form flag `#` will format each hash key/value entry indented on a separate line.

### Type

| Format | Array/Tuple Formats | —— | ————- | s | The same as p, quoted if alternative flag # is used | p | Outputs the type in string form as specified by the Puppet Language

### Flags

| Flag | Effect | —— | —— | (space) | space instead of + for numeric output (- is shown), for containers skips delimiters | # | alternate format; prefix 0x/0x, 0 (octal) and 0b/0B for binary, Floats force decimal '.'. For g/G keep trailing 0. | + | show sign +/- depending on value's sign, changes x,X, o,b, B format to not use 2's complement form | - | left justify the value in the given width | 0 | pad with 0 instead of space for widths larger than value | <[({| | defines an enclosing pair <> [] () {} or | | when used with a container type

### Additional parameters for containers; Array and Hash

For containers (Array and Hash), the format is specified by a hash where the following keys can be set:

  • `'format'` - the format specifier for the container itself

  • `'separator'` - the separator string to use between elements, should not contain padding space at the end

  • `'separator2'` - the separator string to use between association of hash entries key/value

  • `'string_formats'´ - a map of type to format for elements contained in the container

Note that the top level format applies to Array and Hash objects contained/nested in an Array or a Hash.

Given format mappings are merged with (default) formats and a format specified for a narrower type wins over a broader.

@param mode [String, Symbol] :strict or :extended (or :default which is the same as :strict) @param string_formats [String, Hash] format tring, or a hash mapping type to a format string, and for Array and Hash types map to hash of details

    # File lib/puppet/pops/types/string_converter.rb
480 def convert(value, string_formats = :default)
481   options = DEFAULT_STRING_FORMATS
482 
483   value_type = TypeCalculator.infer_set(value)
484   if string_formats.is_a?(String)
485     # For Array and Hash, the format is given as a Hash where 'format' key is the format for the collection itself
486     if Puppet::Pops::Types::PArrayType::DEFAULT.assignable?(value_type)
487       # add the format given for the exact type
488       string_formats = { Puppet::Pops::Types::PArrayType::DEFAULT => {'format' => string_formats }}
489     elsif Puppet::Pops::Types::PHashType::DEFAULT.assignable?(value_type)
490         # add the format given for the exact type
491         string_formats = { Puppet::Pops::Types::PHashType::DEFAULT => {'format' => string_formats }}
492     else
493       # add the format given for the exact type
494       string_formats = { value_type => string_formats }
495     end
496   end
497 
498   case string_formats
499   when :default
500    # do nothing, use default formats
501 
502   when Hash
503     # Convert and validate user input
504     string_formats = validate_input(string_formats)
505     # Merge user given with defaults such that user options wins, merge is deep and format specific
506     options = Format.merge_string_formats(DEFAULT_STRING_FORMATS, string_formats)
507   else
508     raise ArgumentError, "string conversion expects a Default value or a Hash of type to format mappings, got a '#{string_formats.class}'"
509   end
510 
511   _convert(value_type, value, options, DEFAULT_INDENTATION)
512 end
is_a_or_h?(x) click to toggle source
     # File lib/puppet/pops/types/string_converter.rb
1010 def is_a_or_h?(x)
1011   x.is_a?(Array) || x.is_a?(Hash)
1012 end
is_container?(t) click to toggle source
     # File lib/puppet/pops/types/string_converter.rb
1014 def is_container?(t)
1015   case t
1016   when PArrayType, PHashType, PStructType, PTupleType, PObjectType
1017     true
1018   else
1019     false
1020   end
1021 end
puppet_double_quote(str) click to toggle source
    # File lib/puppet/pops/types/string_converter.rb
886 def puppet_double_quote(str)
887   bld = String.new('"')
888   str.each_codepoint do |codepoint|
889     case codepoint
890     when 0x09
891       bld << '\\t'
892     when 0x0a
893       bld << '\\n'
894     when 0x0d
895       bld << '\\r'
896     when 0x22
897       bld << '\\"'
898     when 0x24
899       bld << '\\$'
900     when 0x5c
901       bld << '\\\\'
902     else
903       if codepoint < 0x20
904         bld << sprintf('\\u{%X}', codepoint)
905       elsif codepoint <= 0x7f
906         bld << codepoint
907       else
908         bld << [codepoint].pack('U')
909       end
910     end
911   end
912   bld << '"'
913   bld
914 end
puppet_quote(str, enforce_double_quotes = false) click to toggle source

Performs a '%p' formatting of the given str such that the output conforms to Puppet syntax. An ascii string without control characters, dollar, single-qoute, or backslash, will be quoted using single quotes. All other strings will be quoted using double quotes.

@param [String] str the string that should be formatted @param [Boolean] enforce_double_quotes if true the result will be double quoted (even if single quotes would be possible) @return [String] the formatted string

@api public

    # File lib/puppet/pops/types/string_converter.rb
850 def puppet_quote(str, enforce_double_quotes = false)
851   if enforce_double_quotes
852     return puppet_double_quote(str)
853   end
854 
855   # Assume that the string can be single quoted
856   bld = String.new('\'')
857   bld.force_encoding(str.encoding)
858   escaped = false
859   str.each_codepoint do |codepoint|
860     # Control characters and non-ascii characters cannot be present in a single quoted string
861     return puppet_double_quote(str) if codepoint < 0x20
862 
863     if escaped
864       bld << 0x5c << codepoint
865       escaped = false
866     else
867       if codepoint == 0x27
868         bld << 0x5c << codepoint
869       elsif codepoint == 0x5c
870         escaped = true
871       elsif codepoint <= 0x7f
872         bld << codepoint
873       else
874         bld << [codepoint].pack('U')
875       end
876     end
877   end
878 
879   # If string ended with a backslash, then that backslash must be escaped
880   bld << 0x5c if escaped
881 
882   bld << '\''
883   bld
884 end
string_PAnyType(val_type, val, format_map, _) click to toggle source

Basically string_PAnyType converts the value to a String and then formats it according to the resulting type

@api private

    # File lib/puppet/pops/types/string_converter.rb
614 def string_PAnyType(val_type, val, format_map, _)
615   f = get_format(val_type, format_map)
616   Kernel.format(f.orig_fmt, val)
617 end
string_PArrayType(val_type, val, format_map, indentation) click to toggle source
     # File lib/puppet/pops/types/string_converter.rb
 932 def string_PArrayType(val_type, val, format_map, indentation)
 933   format         = get_format(val_type, format_map)
 934   sep            = format.separator || DEFAULT_ARRAY_FORMAT.separator
 935   string_formats = format.container_string_formats || DEFAULT_CONTAINER_FORMATS
 936   delims         = format.delimiter_pair(DEFAULT_ARRAY_DELIMITERS)
 937 
 938   # Make indentation active, if array is in alternative format, or if nested in indenting
 939   indentation = indentation.indenting(format.alt? || indentation.is_indenting?)
 940 
 941   case format.format
 942   when :a, :s, :p
 943     buf = String.new
 944     if indentation.breaks?
 945       buf << "\n"
 946       buf << indentation.padding
 947     end
 948     buf << delims[0]
 949 
 950     # Make a first pass to format each element
 951     children_indentation = indentation.increase(format.alt?) # tell children they are expected to indent
 952     mapped = val.map do |v|
 953       if children_indentation.first?
 954         children_indentation = children_indentation.subsequent
 955       end
 956       val_t = TypeCalculator.infer_set(v)
 957       _convert(val_t, v, is_container?(val_t) ? format_map : string_formats, children_indentation)
 958     end
 959 
 960     # compute widest run in the array, skip nested arrays and hashes
 961     # then if size > width, set flag if a break on each element should be performed
 962     if format.alt? && format.width
 963       widest = val.each_with_index.reduce([0]) do | memo, v_i |
 964         # array or hash breaks
 965         if is_a_or_h?(v_i[0])
 966           memo << 0
 967         else
 968           memo[-1] += mapped[v_i[1]].length
 969         end
 970         memo
 971       end
 972       widest = widest.max
 973       sz_break = widest > (format.width || Float::INFINITY)
 974     else
 975       sz_break = false
 976     end
 977 
 978     # output each element with breaks and padding
 979     children_indentation = indentation.increase(format.alt?)
 980     val.each_with_index do |v, i|
 981       str_val = mapped[i]
 982       if children_indentation.first?
 983         children_indentation = children_indentation.subsequent
 984         # if breaking, indent first element by one
 985         if sz_break && !is_a_or_h?(v)
 986           buf << ' '
 987         end
 988       else
 989         buf << sep
 990         # if break on each (and breaking will not occur because next is an array or hash)
 991         # or, if indenting, and previous was an array or hash, then break and continue on next line
 992         # indented.
 993         if (sz_break && !is_a_or_h?(v)) || (format.alt? && i > 0 && is_a_or_h?(val[i-1]) && !is_a_or_h?(v))
 994           buf.rstrip! unless buf[-1] == "\n"
 995           buf << "\n"
 996           buf << children_indentation.padding
 997         end
 998       end
 999       # remove trailing space added by separator if followed by break
1000       buf.rstrip! if buf[-1] == ' ' && str_val[0] == "\n"
1001       buf << str_val
1002     end
1003     buf << delims[1]
1004     buf
1005   else
1006     raise FormatError.new('Array', format.format, 'asp')
1007   end
1008 end
string_PBinaryType(val_type, val, format_map, _) click to toggle source

@api private

    # File lib/puppet/pops/types/string_converter.rb
761 def string_PBinaryType(val_type, val, format_map, _)
762   f = get_format(val_type, format_map)
763   substitute = f.alt? ? 'p' : 's'
764   case f.format
765   when :s
766     val_to_convert = val.binary_buffer
767     if !f.alt?
768       # Assume it is valid UTF-8
769       val_to_convert = val_to_convert.dup.force_encoding('UTF-8')
770       # If it isn't
771       unless val_to_convert.valid_encoding?
772         # try to convert and fail with details about what is wrong
773         val_to_convert = val.binary_buffer.encode('UTF-8')
774       end
775     else
776       val_to_convert = val.binary_buffer
777     end
778     Kernel.format(f.orig_fmt.gsub('s', substitute), val_to_convert)
779 
780   when :p
781     # width & precision applied to string, not the the name of the type
782     "Binary(\"#{Kernel.format(f.orig_fmt.tr('p', 's'), val.to_s)}\")"
783 
784   when :b
785     Kernel.format(f.orig_fmt.gsub('b', substitute), val.relaxed_to_s)
786 
787   when :B
788     Kernel.format(f.orig_fmt.gsub('B', substitute), val.to_s)
789 
790   when :u
791     Kernel.format(f.orig_fmt.gsub('u', substitute), val.urlsafe_to_s)
792 
793   when :t
794     # Output as the type without any data
795     Kernel.format(f.orig_fmt.gsub('t', substitute), 'Binary')
796 
797   when :T
798     # Output as the type without any data in all caps
799     Kernel.format(f.orig_fmt.gsub('T', substitute), 'BINARY')
800 
801   else
802     raise FormatError.new('Binary', f.format, 'bButTsp')
803   end
804 end
string_PBooleanType(val_type, val, format_map, indentation) click to toggle source

@api private

    # File lib/puppet/pops/types/string_converter.rb
655 def string_PBooleanType(val_type, val, format_map, indentation)
656   f = get_format(val_type, format_map)
657   case f.format
658   when :t
659     # 'true'/'false' or 't'/'f' if in alt mode
660     str_bool = val.to_s
661     apply_string_flags(f, f.alt? ? str_bool[0] : str_bool)
662 
663   when :T
664     # 'True'/'False' or 'T'/'F' if in alt mode
665     str_bool = val.to_s.capitalize
666     apply_string_flags(f, f.alt? ? str_bool[0] : str_bool)
667 
668   when :y
669     # 'yes'/'no' or 'y'/'n' if in alt mode
670     str_bool = val ? 'yes' : 'no'
671     apply_string_flags(f, f.alt? ? str_bool[0] : str_bool)
672 
673   when :Y
674     # 'Yes'/'No' or 'Y'/'N' if in alt mode
675     str_bool = val ? 'Yes' : 'No'
676     apply_string_flags(f, f.alt? ? str_bool[0] : str_bool)
677 
678   when :d, :x, :X, :o, :b, :B
679     # Boolean in numeric form, formated by integer rule
680     numeric_bool = val ? 1 : 0
681     string_formats = { Puppet::Pops::Types::PIntegerType::DEFAULT => f}
682     _convert(TypeCalculator.infer_set(numeric_bool), numeric_bool, string_formats, indentation)
683 
684   when :e, :E, :f, :g, :G, :a, :A
685     # Boolean in numeric form, formated by float rule
686     numeric_bool = val ? 1.0 : 0.0
687     string_formats = { Puppet::Pops::Types::PFloatType::DEFAULT => f}
688     _convert(TypeCalculator.infer_set(numeric_bool), numeric_bool, string_formats, indentation)
689 
690   when :s
691     apply_string_flags(f, val.to_s)
692 
693   when :p
694     apply_string_flags(f, val.inspect)
695 
696   else
697     raise FormatError.new('Boolean', f.format, 'tTyYdxXobBeEfgGaAsp')
698   end
699 end
string_PDefaultType(val_type, val, format_map, _) click to toggle source
    # File lib/puppet/pops/types/string_converter.rb
619 def string_PDefaultType(val_type, val, format_map, _)
620   f = get_format(val_type, format_map)
621   apply_string_flags(f, case f.format
622   when :d, :s, :p
623     f.alt? ? '"default"' : 'default'
624   when :D
625     f.alt? ? '"Default"' : 'Default'
626   else
627     raise FormatError.new('Default', f.format, 'dDsp')
628   end)
629 end
string_PFloatType(val_type, val, format_map, _) click to toggle source

@api private

    # File lib/puppet/pops/types/string_converter.rb
742 def string_PFloatType(val_type, val, format_map, _)
743   f = get_format(val_type, format_map)
744   case f.format
745   when :d, :x, :X, :o, :b, :B
746     Kernel.format(f.orig_fmt, val.to_i)
747 
748   when :e, :E, :f, :g, :G, :a, :A, :p
749     Kernel.format(f.orig_fmt, val)
750 
751   when :s
752     float_str = f.alt? ? "\"#{Kernel.format('%p', val)}\"" : Kernel.format('%p', val)
753     Kernel.format(f.orig_fmt, float_str)
754 
755   else
756     raise FormatError.new('Float', f.format, 'dxXobBeEfgGaAsp')
757   end
758 end
string_PHashType(val_type, val, format_map, indentation) click to toggle source

@api private

     # File lib/puppet/pops/types/string_converter.rb
1035 def string_PHashType(val_type, val, format_map, indentation)
1036   format         = get_format(val_type, format_map)
1037   sep            = format.separator  || DEFAULT_HASH_FORMAT.separator
1038   assoc          = format.separator2 || DEFAULT_HASH_FORMAT.separator2
1039   string_formats = format.container_string_formats || DEFAULT_CONTAINER_FORMATS
1040   delims         = format.delimiter_pair(DEFAULT_HASH_DELIMITERS)
1041 
1042   if format.alt? 
1043     sep = sep.rstrip unless sep[-1] == "\n"
1044     sep = "#{sep}\n"
1045   end
1046 
1047   cond_break     = ''
1048   padding        = ''
1049 
1050   case format.format
1051   when :a
1052     # Convert to array and use array rules
1053     array_hash = val.to_a
1054     _convert(TypeCalculator.infer_set(array_hash), array_hash, format_map, indentation)
1055 
1056   when :h, :s, :p
1057     indentation = indentation.indenting(format.alt? || indentation.is_indenting?)
1058     buf = String.new
1059     if indentation.breaks?
1060       buf << "\n"
1061       buf << indentation.padding
1062     end
1063 
1064     children_indentation = indentation.increase
1065     if format.alt?
1066       cond_break = "\n"
1067       padding = children_indentation.padding
1068     end
1069     buf << delims[0]
1070     buf << cond_break  # break after opening delimiter if pretty printing
1071     buf << val.map do |k,v|
1072       key_type = TypeCalculator.infer_set(k)
1073       val_type = TypeCalculator.infer_set(v)
1074       key = _convert(key_type, k, is_container?(key_type) ? format_map : string_formats, children_indentation)
1075       val = _convert(val_type, v, is_container?(val_type) ? format_map : string_formats, children_indentation)
1076       "#{padding}#{key}#{assoc}#{val}"
1077     end.join(sep)
1078     if format.alt?
1079       buf << cond_break
1080       buf << indentation.padding
1081     end
1082     buf << delims[1]
1083     buf
1084   else
1085     raise FormatError.new('Hash', format.format, 'hasp')
1086   end
1087 end
string_PIntegerType(val_type, val, format_map, _) click to toggle source

@api private

    # File lib/puppet/pops/types/string_converter.rb
717 def string_PIntegerType(val_type, val, format_map, _)
718   f = get_format(val_type, format_map)
719   case f.format
720   when :d, :x, :X, :o, :b, :B, :p
721     Kernel.format(f.orig_fmt, val)
722 
723   when :e, :E, :f, :g, :G, :a, :A
724     Kernel.format(f.orig_fmt, val.to_f)
725 
726   when :c
727     char = [val].pack("U")
728     char = f.alt? ? "\"#{char}\"" : char
729     Kernel.format(f.orig_fmt.tr('c','s'), char)
730 
731   when :s
732     fmt = f.alt? ? 'p' : 's'
733     int_str = Kernel.format('%d', val)
734     Kernel.format(f.orig_fmt.gsub('s', fmt), int_str)
735 
736   else
737     raise FormatError.new('Integer', f.format, 'dxXobBeEfgGaAspc')
738   end
739 end
string_PIteratorType(val_type, val, format_map, indentation) click to toggle source

@api private

     # File lib/puppet/pops/types/string_converter.rb
1029 def string_PIteratorType(val_type, val, format_map, indentation)
1030   v = val.to_a
1031   _convert(TypeCalculator.infer_set(v), v, format_map, indentation)
1032 end
string_PObjectType(val_type, val, format_map, indentation) click to toggle source
    # File lib/puppet/pops/types/string_converter.rb
562 def string_PObjectType(val_type, val, format_map, indentation)
563   f = get_format(val_type, format_map)
564   case f.format
565   when :p
566     fmt = TypeFormatter.singleton
567     indentation = indentation.indenting(f.alt? || indentation.is_indenting?)
568     fmt = fmt.indented(indentation.level, 2) if indentation.is_indenting?
569     fmt.string(val)
570   when :s
571     val.to_s
572   when :q
573     val.inspect
574   else
575     raise FormatError.new('Object', f.format, 'spq')
576   end
577 end
string_PObjectTypeExtension(val_type, val, format_map, indentation) click to toggle source
    # File lib/puppet/pops/types/string_converter.rb
579 def string_PObjectTypeExtension(val_type, val, format_map, indentation)
580   string_PObjectType(val_type.base_type, val, format_map, indentation)
581 end
string_PRegexpType(val_type, val, format_map, _) click to toggle source

@api private

    # File lib/puppet/pops/types/string_converter.rb
917 def string_PRegexpType(val_type, val, format_map, _)
918   f = get_format(val_type, format_map)
919   case f.format
920   when :p
921     str_regexp = PRegexpType.regexp_to_s_with_delimiters(val)
922     f.orig_fmt == '%p' ? str_regexp : Kernel.format(f.orig_fmt.tr('p', 's'), str_regexp)
923   when :s
924     str_regexp = PRegexpType.regexp_to_s(val)
925     str_regexp = puppet_quote(str_regexp) if f.alt?
926     f.orig_fmt == '%s' ? str_regexp : Kernel.format(f.orig_fmt, str_regexp)
927   else
928     raise FormatError.new('Regexp', f.format, 'sp')
929   end
930 end
string_PRuntimeType(val_type, val, format_map, indent) click to toggle source
    # File lib/puppet/pops/types/string_converter.rb
583 def string_PRuntimeType(val_type, val, format_map, indent)
584   # Before giving up on this, and use a string representation of the unknown
585   # object, a check is made to see if the object can present itself as
586   # a hash or an array. If it can, then that representation is used instead.
587   if val.is_a?(Hash)
588     hash = val.to_hash
589     # Ensure that the returned value isn't derived from Hash
590     return string_PHashType(val_type, hash, format_map, indent) if hash.instance_of?(Hash)
591   elsif val.is_a?(Array)
592     array = val.to_a
593     # Ensure that the returned value isn't derived from Array
594     return string_PArrayType(val_type, array, format_map, indent) if array.instance_of?(Array)
595   end
596 
597   f = get_format(val_type, format_map)
598   case f.format
599   when :s
600     val.to_s
601   when :p
602     puppet_quote(val.to_s)
603   when :q
604     val.inspect
605   else
606     raise FormatError.new('Runtime', f.format, 'spq')
607   end
608 end
string_PStringType(val_type, val, format_map, _) click to toggle source

@api private

    # File lib/puppet/pops/types/string_converter.rb
807 def string_PStringType(val_type, val, format_map, _)
808   f = get_format(val_type, format_map)
809   case f.format
810   when :s
811     Kernel.format(f.orig_fmt, val)
812 
813   when :p
814     apply_string_flags(f, puppet_quote(val, f.alt?))
815 
816   when :c
817     c_val = val.capitalize
818     f.alt? ? apply_string_flags(f, puppet_quote(c_val)) :  Kernel.format(f.orig_fmt.tr('c', 's'), c_val)
819 
820   when :C
821     c_val = val.split('::').map {|s| s.capitalize }.join('::')
822     f.alt? ? apply_string_flags(f, puppet_quote(c_val)) :  Kernel.format(f.orig_fmt.tr('C', 's'), c_val)
823 
824   when :u
825     c_val = val.upcase
826     f.alt? ? apply_string_flags(f, puppet_quote(c_val)) :  Kernel.format(f.orig_fmt.tr('u', 's'), c_val)
827 
828   when :d
829     c_val = val.downcase
830     f.alt? ? apply_string_flags(f, puppet_quote(c_val)) :  Kernel.format(f.orig_fmt.tr('d', 's'), c_val)
831 
832   when :t  # trim
833     c_val = val.strip
834     f.alt? ? apply_string_flags(f, puppet_quote(c_val)) :  Kernel.format(f.orig_fmt.tr('t', 's'), c_val)
835 
836   else
837     raise FormatError.new('String', f.format, 'cCudspt')
838   end
839 end
string_PStructType(val_type, val, format_map, indentation) click to toggle source

@api private

     # File lib/puppet/pops/types/string_converter.rb
1090 def string_PStructType(val_type, val, format_map, indentation)
1091   string_PHashType(val_type, val, format_map, indentation)
1092 end
string_PTupleType(val_type, val, format_map, indentation) click to toggle source

@api private

     # File lib/puppet/pops/types/string_converter.rb
1024 def string_PTupleType(val_type, val, format_map, indentation)
1025   string_PArrayType(val_type, val, format_map, indentation)
1026 end
string_PTypeType(val_type, val, format_map, _) click to toggle source

@api private

     # File lib/puppet/pops/types/string_converter.rb
1095 def string_PTypeType(val_type, val, format_map, _)
1096   f = get_format(val_type, format_map)
1097   case f.format
1098   when :s
1099     str_val = f.alt? ? "\"#{val}\"" : val.to_s
1100     Kernel.format(f.orig_fmt, str_val)
1101   when :p
1102     Kernel.format(f.orig_fmt.tr('p', 's'), val.to_s)
1103   else
1104     raise FormatError.new('Type', f.format, 'sp')
1105   end
1106 end
string_PURIType(val_type, val, format_map, indentation) click to toggle source

@api private

     # File lib/puppet/pops/types/string_converter.rb
1109 def string_PURIType(val_type, val, format_map, indentation)
1110   f = get_format(val_type, format_map)
1111   case f.format
1112   when :p
1113     fmt = TypeFormatter.singleton
1114     indentation = indentation.indenting(f.alt? || indentation.is_indenting?)
1115     fmt = fmt.indented(indentation.level, 2) if indentation.is_indenting?
1116     fmt.string(val)
1117   when :s
1118     str_val = val.to_s
1119     Kernel.format(f.orig_fmt, f.alt? ? puppet_quote(str_val) : str_val)
1120   else
1121     raise FormatError.new('URI', f.format, 'sp')
1122   end
1123 end
string_PUndefType(val_type, val, format_map, _) click to toggle source

@api private

    # File lib/puppet/pops/types/string_converter.rb
632 def string_PUndefType(val_type, val, format_map, _)
633   f = get_format(val_type, format_map)
634   apply_string_flags(f, case f.format
635   when :n
636     f.alt? ? 'null' : 'nil'
637   when :u
638     f.alt? ? 'undefined' : 'undef'
639   when :d, :x, :X, :o, :b, :B, :e, :E, :f, :g, :G, :a, :A
640     'NaN'
641   when :v
642     'n/a'
643   when :V
644     'N/A'
645   when :s
646     f.alt? ? '""' : ''
647   when :p
648     f.alt? ? '"undef"' : 'undef'
649   else
650     raise FormatError.new('Undef', f.format, 'nudxXobBeEfgGaAvVsp')
651   end)
652 end

Private Instance Methods

_convert(val_type, value, format_map, indentation) click to toggle source

# A method only used for manual debugging as the default output of the formatting rules is # very hard to read otherwise. # # @api private def dump_string_formats(f, indent = 1)

return f.to_s unless f.is_a?(Hash)
"{#{f.map {|k,v| "#{k.to_s} => #{dump_string_formats(v,indent+1)}"}.join(",\n#{'  '*indent}  ")}}"

end

    # File lib/puppet/pops/types/string_converter.rb
523 def _convert(val_type, value, format_map, indentation)
524   @string_visitor.visit_this_3(self, val_type, value, format_map, indentation)
525 end
apply_string_flags(f, literal_str) click to toggle source

Performs post-processing of literals to apply width and precision flags

    # File lib/puppet/pops/types/string_converter.rb
702 def apply_string_flags(f, literal_str)
703   if f.left || f.width || f.prec
704     fmt = String.new('%')
705     fmt << '-' if f.left
706     fmt << f.width.to_s if f.width
707     fmt << '.' << f.prec.to_s if f.prec
708     fmt << 's'
709     Kernel.format(fmt, literal_str)
710   else
711     literal_str
712   end
713 end
get_format(val_t, format_options) click to toggle source

Maps the inferred type of o to a formatting rule

     # File lib/puppet/pops/types/string_converter.rb
1126 def get_format(val_t, format_options)
1127   fmt = format_options.find {|k,_| k.assignable?(val_t) }
1128   return fmt[1] unless fmt.nil?
1129   return Format.new("%s")
1130 end
validate_container_input(fmt) click to toggle source
    # File lib/puppet/pops/types/string_converter.rb
550 def validate_container_input(fmt)
551   if (fmt.keys - FMT_KEYS).size > 0
552     raise ArgumentError, "only #{FMT_KEYS.map {|k| "'#{k}'"}.join(', ')} are allowed in a container format, got #{fmt}"
553   end
554   result                          = Format.new(fmt['format'])
555   result.separator                = fmt['separator']
556   result.separator2               = fmt['separator2']
557   result.container_string_formats = validate_input(fmt['string_formats'])
558   result
559 end
validate_input(fmt) click to toggle source
    # File lib/puppet/pops/types/string_converter.rb
528 def validate_input(fmt)
529   return nil if fmt.nil?
530   unless fmt.is_a?(Hash)
531     raise ArgumentError, "expected a hash with type to format mappings, got instance of '#{fmt.class}'"
532   end
533   fmt.reduce({}) do | result, entry|
534     key, value = entry
535     unless key.is_a?(Types::PAnyType)
536       raise ArgumentError, "top level keys in the format hash must be data types, got instance of '#{key.class}'"
537     end
538     if value.is_a?(Hash)
539       result[key] = validate_container_input(value)
540     else
541       result[key] = Format.new(value)
542     end
543     result
544   end
545 end