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
@api public
# File lib/puppet/pops/types/string_converter.rb 246 def self.convert(value, string_formats = :default) 247 singleton.convert(value, string_formats) 248 end
@api private
# File lib/puppet/pops/types/string_converter.rb 252 def initialize 253 @string_visitor = Visitor.new(self, "string", 3, 3) 254 end
Public Instance Methods
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 479 def convert(value, string_formats = :default) 480 options = DEFAULT_STRING_FORMATS 481 482 value_type = TypeCalculator.infer_set(value) 483 if string_formats.is_a?(String) 484 # For Array and Hash, the format is given as a Hash where 'format' key is the format for the collection itself 485 if Puppet::Pops::Types::PArrayType::DEFAULT.assignable?(value_type) 486 # add the format given for the exact type 487 string_formats = { Puppet::Pops::Types::PArrayType::DEFAULT => {'format' => string_formats }} 488 elsif Puppet::Pops::Types::PHashType::DEFAULT.assignable?(value_type) 489 # add the format given for the exact type 490 string_formats = { Puppet::Pops::Types::PHashType::DEFAULT => {'format' => string_formats }} 491 else 492 # add the format given for the exact type 493 string_formats = { value_type => string_formats } 494 end 495 end 496 497 case string_formats 498 when :default 499 # do nothing, use default formats 500 501 when Hash 502 # Convert and validate user input 503 string_formats = validate_input(string_formats) 504 # Merge user given with defaults such that user options wins, merge is deep and format specific 505 options = Format.merge_string_formats(DEFAULT_STRING_FORMATS, string_formats) 506 else 507 raise ArgumentError, "string conversion expects a Default value or a Hash of type to format mappings, got a '#{string_formats.class}'" 508 end 509 510 _convert(value_type, value, options, DEFAULT_INDENTATION) 511 end
# File lib/puppet/pops/types/string_converter.rb 1009 def is_a_or_h?(x) 1010 x.is_a?(Array) || x.is_a?(Hash) 1011 end
# File lib/puppet/pops/types/string_converter.rb 1013 def is_container?(t) 1014 case t 1015 when PArrayType, PHashType, PStructType, PTupleType, PObjectType 1016 true 1017 else 1018 false 1019 end 1020 end
# File lib/puppet/pops/types/string_converter.rb 885 def puppet_double_quote(str) 886 bld = '"' 887 str.each_codepoint do |codepoint| 888 case codepoint 889 when 0x09 890 bld << '\\t' 891 when 0x0a 892 bld << '\\n' 893 when 0x0d 894 bld << '\\r' 895 when 0x22 896 bld << '\\"' 897 when 0x24 898 bld << '\\$' 899 when 0x5c 900 bld << '\\\\' 901 else 902 if codepoint < 0x20 903 bld << sprintf('\\u{%X}', codepoint) 904 elsif codepoint <= 0x7f 905 bld << codepoint 906 else 907 bld << [codepoint].pack('U') 908 end 909 end 910 end 911 bld << '"' 912 bld 913 end
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 849 def puppet_quote(str, enforce_double_quotes = false) 850 if enforce_double_quotes 851 return puppet_double_quote(str) 852 end 853 854 # Assume that the string can be single quoted 855 bld = '\'' 856 bld.force_encoding(str.encoding) 857 escaped = false 858 str.each_codepoint do |codepoint| 859 # Control characters and non-ascii characters cannot be present in a single quoted string 860 return puppet_double_quote(str) if codepoint < 0x20 861 862 if escaped 863 bld << 0x5c << codepoint 864 escaped = false 865 else 866 if codepoint == 0x27 867 bld << 0x5c << codepoint 868 elsif codepoint == 0x5c 869 escaped = true 870 elsif codepoint <= 0x7f 871 bld << codepoint 872 else 873 bld << [codepoint].pack('U') 874 end 875 end 876 end 877 878 # If string ended with a backslash, then that backslash must be escaped 879 bld << 0x5c if escaped 880 881 bld << '\'' 882 bld 883 end
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 613 def string_PAnyType(val_type, val, format_map, _) 614 f = get_format(val_type, format_map) 615 Kernel.format(f.orig_fmt, val) 616 end
# File lib/puppet/pops/types/string_converter.rb 931 def string_PArrayType(val_type, val, format_map, indentation) 932 format = get_format(val_type, format_map) 933 sep = format.separator || DEFAULT_ARRAY_FORMAT.separator 934 string_formats = format.container_string_formats || DEFAULT_CONTAINER_FORMATS 935 delims = format.delimiter_pair(DEFAULT_ARRAY_DELIMITERS) 936 937 # Make indentation active, if array is in alternative format, or if nested in indenting 938 indentation = indentation.indenting(format.alt? || indentation.is_indenting?) 939 940 case format.format 941 when :a, :s, :p 942 buf = '' 943 if indentation.breaks? 944 buf << "\n" 945 buf << indentation.padding 946 end 947 buf << delims[0] 948 949 # Make a first pass to format each element 950 children_indentation = indentation.increase(format.alt?) # tell children they are expected to indent 951 mapped = val.map do |v| 952 if children_indentation.first? 953 children_indentation = children_indentation.subsequent 954 end 955 val_t = TypeCalculator.infer_set(v) 956 _convert(val_t, v, is_container?(val_t) ? format_map : string_formats, children_indentation) 957 end 958 959 # compute widest run in the array, skip nested arrays and hashes 960 # then if size > width, set flag if a break on each element should be performed 961 if format.alt? && format.width 962 widest = val.each_with_index.reduce([0]) do | memo, v_i | 963 # array or hash breaks 964 if is_a_or_h?(v_i[0]) 965 memo << 0 966 else 967 memo[-1] += mapped[v_i[1]].length 968 end 969 memo 970 end 971 widest = widest.max 972 sz_break = widest > (format.width || Float::INFINITY) 973 else 974 sz_break = false 975 end 976 977 # output each element with breaks and padding 978 children_indentation = indentation.increase(format.alt?) 979 val.each_with_index do |v, i| 980 str_val = mapped[i] 981 if children_indentation.first? 982 children_indentation = children_indentation.subsequent 983 # if breaking, indent first element by one 984 if sz_break && !is_a_or_h?(v) 985 buf << ' ' 986 end 987 else 988 buf << sep 989 # if break on each (and breaking will not occur because next is an array or hash) 990 # or, if indenting, and previous was an array or hash, then break and continue on next line 991 # indented. 992 if (sz_break && !is_a_or_h?(v)) || (format.alt? && i > 0 && is_a_or_h?(val[i-1]) && !is_a_or_h?(v)) 993 buf.rstrip! unless buf[-1] == "\n" 994 buf << "\n" 995 buf << children_indentation.padding 996 end 997 end 998 # remove trailing space added by separator if followed by break 999 buf.rstrip! if buf[-1] == ' ' && str_val[0] == "\n" 1000 buf << str_val 1001 end 1002 buf << delims[1] 1003 buf 1004 else 1005 raise FormatError.new('Array', format.format, 'asp') 1006 end 1007 end
@api private
# File lib/puppet/pops/types/string_converter.rb 760 def string_PBinaryType(val_type, val, format_map, _) 761 f = get_format(val_type, format_map) 762 substitute = f.alt? ? 'p' : 's' 763 case f.format 764 when :s 765 val_to_convert = val.binary_buffer 766 if !f.alt? 767 # Assume it is valid UTF-8 768 val_to_convert = val_to_convert.dup.force_encoding('UTF-8') 769 # If it isn't 770 unless val_to_convert.valid_encoding? 771 # try to convert and fail with details about what is wrong 772 val_to_convert = val.binary_buffer.encode('UTF-8') 773 end 774 else 775 val_to_convert = val.binary_buffer 776 end 777 Kernel.format(f.orig_fmt.gsub('s', substitute), val_to_convert) 778 779 when :p 780 # width & precision applied to string, not the the name of the type 781 "Binary(\"#{Kernel.format(f.orig_fmt.tr('p', 's'), val.to_s)}\")" 782 783 when :b 784 Kernel.format(f.orig_fmt.gsub('b', substitute), val.relaxed_to_s) 785 786 when :B 787 Kernel.format(f.orig_fmt.gsub('B', substitute), val.to_s) 788 789 when :u 790 Kernel.format(f.orig_fmt.gsub('u', substitute), val.urlsafe_to_s) 791 792 when :t 793 # Output as the type without any data 794 Kernel.format(f.orig_fmt.gsub('t', substitute), 'Binary') 795 796 when :T 797 # Output as the type without any data in all caps 798 Kernel.format(f.orig_fmt.gsub('T', substitute), 'BINARY') 799 800 else 801 raise FormatError.new('Binary', f.format, 'bButTsp') 802 end 803 end
@api private
# File lib/puppet/pops/types/string_converter.rb 654 def string_PBooleanType(val_type, val, format_map, indentation) 655 f = get_format(val_type, format_map) 656 case f.format 657 when :t 658 # 'true'/'false' or 't'/'f' if in alt mode 659 str_bool = val.to_s 660 apply_string_flags(f, f.alt? ? str_bool[0] : str_bool) 661 662 when :T 663 # 'True'/'False' or 'T'/'F' if in alt mode 664 str_bool = val.to_s.capitalize 665 apply_string_flags(f, f.alt? ? str_bool[0] : str_bool) 666 667 when :y 668 # 'yes'/'no' or 'y'/'n' if in alt mode 669 str_bool = val ? 'yes' : 'no' 670 apply_string_flags(f, f.alt? ? str_bool[0] : str_bool) 671 672 when :Y 673 # 'Yes'/'No' or 'Y'/'N' if in alt mode 674 str_bool = val ? 'Yes' : 'No' 675 apply_string_flags(f, f.alt? ? str_bool[0] : str_bool) 676 677 when :d, :x, :X, :o, :b, :B 678 # Boolean in numeric form, formated by integer rule 679 numeric_bool = val ? 1 : 0 680 string_formats = { Puppet::Pops::Types::PIntegerType::DEFAULT => f} 681 _convert(TypeCalculator.infer_set(numeric_bool), numeric_bool, string_formats, indentation) 682 683 when :e, :E, :f, :g, :G, :a, :A 684 # Boolean in numeric form, formated by float rule 685 numeric_bool = val ? 1.0 : 0.0 686 string_formats = { Puppet::Pops::Types::PFloatType::DEFAULT => f} 687 _convert(TypeCalculator.infer_set(numeric_bool), numeric_bool, string_formats, indentation) 688 689 when :s 690 apply_string_flags(f, val.to_s) 691 692 when :p 693 apply_string_flags(f, val.inspect) 694 695 else 696 raise FormatError.new('Boolean', f.format, 'tTyYdxXobBeEfgGaAsp') 697 end 698 end
# File lib/puppet/pops/types/string_converter.rb 618 def string_PDefaultType(val_type, val, format_map, _) 619 f = get_format(val_type, format_map) 620 apply_string_flags(f, case f.format 621 when :d, :s, :p 622 f.alt? ? '"default"' : 'default' 623 when :D 624 f.alt? ? '"Default"' : 'Default' 625 else 626 raise FormatError.new('Default', f.format, 'dDsp') 627 end) 628 end
@api private
# File lib/puppet/pops/types/string_converter.rb 741 def string_PFloatType(val_type, val, format_map, _) 742 f = get_format(val_type, format_map) 743 case f.format 744 when :d, :x, :X, :o, :b, :B 745 Kernel.format(f.orig_fmt, val.to_i) 746 747 when :e, :E, :f, :g, :G, :a, :A, :p 748 Kernel.format(f.orig_fmt, val) 749 750 when :s 751 float_str = f.alt? ? "\"#{Kernel.format('%p', val)}\"" : Kernel.format('%p', val) 752 Kernel.format(f.orig_fmt, float_str) 753 754 else 755 raise FormatError.new('Float', f.format, 'dxXobBeEfgGaAsp') 756 end 757 end
@api private
# File lib/puppet/pops/types/string_converter.rb 1034 def string_PHashType(val_type, val, format_map, indentation) 1035 format = get_format(val_type, format_map) 1036 sep = format.separator || DEFAULT_HASH_FORMAT.separator 1037 assoc = format.separator2 || DEFAULT_HASH_FORMAT.separator2 1038 string_formats = format.container_string_formats || DEFAULT_CONTAINER_FORMATS 1039 delims = format.delimiter_pair(DEFAULT_HASH_DELIMITERS) 1040 1041 if format.alt? 1042 sep = sep.rstrip unless sep[-1] == "\n" 1043 sep = "#{sep}\n" 1044 end 1045 1046 cond_break = '' 1047 padding = '' 1048 1049 case format.format 1050 when :a 1051 # Convert to array and use array rules 1052 array_hash = val.to_a 1053 _convert(TypeCalculator.infer_set(array_hash), array_hash, format_map, indentation) 1054 1055 when :h, :s, :p 1056 indentation = indentation.indenting(format.alt? || indentation.is_indenting?) 1057 buf = '' 1058 if indentation.breaks? 1059 buf << "\n" 1060 buf << indentation.padding 1061 end 1062 1063 children_indentation = indentation.increase 1064 if format.alt? 1065 cond_break = "\n" 1066 padding = children_indentation.padding 1067 end 1068 buf << delims[0] 1069 buf << cond_break # break after opening delimiter if pretty printing 1070 buf << val.map do |k,v| 1071 key_type = TypeCalculator.infer_set(k) 1072 val_type = TypeCalculator.infer_set(v) 1073 key = _convert(key_type, k, is_container?(key_type) ? format_map : string_formats, children_indentation) 1074 val = _convert(val_type, v, is_container?(val_type) ? format_map : string_formats, children_indentation) 1075 "#{padding}#{key}#{assoc}#{val}" 1076 end.join(sep) 1077 if format.alt? 1078 buf << cond_break 1079 buf << indentation.padding 1080 end 1081 buf << delims[1] 1082 buf 1083 else 1084 raise FormatError.new('Hash', format.format, 'hasp') 1085 end 1086 end
@api private
# File lib/puppet/pops/types/string_converter.rb 716 def string_PIntegerType(val_type, val, format_map, _) 717 f = get_format(val_type, format_map) 718 case f.format 719 when :d, :x, :X, :o, :b, :B, :p 720 Kernel.format(f.orig_fmt, val) 721 722 when :e, :E, :f, :g, :G, :a, :A 723 Kernel.format(f.orig_fmt, val.to_f) 724 725 when :c 726 char = [val].pack("U") 727 char = f.alt? ? "\"#{char}\"" : char 728 Kernel.format(f.orig_fmt.tr('c','s'), char) 729 730 when :s 731 fmt = f.alt? ? 'p' : 's' 732 int_str = Kernel.format('%d', val) 733 Kernel.format(f.orig_fmt.gsub('s', fmt), int_str) 734 735 else 736 raise FormatError.new('Integer', f.format, 'dxXobBeEfgGaAspc') 737 end 738 end
@api private
# File lib/puppet/pops/types/string_converter.rb 1028 def string_PIteratorType(val_type, val, format_map, indentation) 1029 v = val.to_a 1030 _convert(TypeCalculator.infer_set(v), v, format_map, indentation) 1031 end
# File lib/puppet/pops/types/string_converter.rb 561 def string_PObjectType(val_type, val, format_map, indentation) 562 f = get_format(val_type, format_map) 563 case f.format 564 when :p 565 fmt = TypeFormatter.singleton 566 indentation = indentation.indenting(f.alt? || indentation.is_indenting?) 567 fmt = fmt.indented(indentation.level, 2) if indentation.is_indenting? 568 fmt.string(val) 569 when :s 570 val.to_s 571 when :q 572 val.inspect 573 else 574 raise FormatError.new('Object', f.format, 'spq') 575 end 576 end
# File lib/puppet/pops/types/string_converter.rb 578 def string_PObjectTypeExtension(val_type, val, format_map, indentation) 579 string_PObjectType(val_type.base_type, val, format_map, indentation) 580 end
@api private
# File lib/puppet/pops/types/string_converter.rb 916 def string_PRegexpType(val_type, val, format_map, _) 917 f = get_format(val_type, format_map) 918 case f.format 919 when :p 920 str_regexp = PRegexpType.regexp_to_s_with_delimiters(val) 921 f.orig_fmt == '%p' ? str_regexp : Kernel.format(f.orig_fmt.tr('p', 's'), str_regexp) 922 when :s 923 str_regexp = PRegexpType.regexp_to_s(val) 924 str_regexp = puppet_quote(str_regexp) if f.alt? 925 f.orig_fmt == '%s' ? str_regexp : Kernel.format(f.orig_fmt, str_regexp) 926 else 927 raise FormatError.new('Regexp', f.format, 'sp') 928 end 929 end
# File lib/puppet/pops/types/string_converter.rb 582 def string_PRuntimeType(val_type, val, format_map, indent) 583 # Before giving up on this, and use a string representation of the unknown 584 # object, a check is made to see if the object can present itself as 585 # a hash or an array. If it can, then that representation is used instead. 586 if val.is_a?(Hash) 587 hash = val.to_hash 588 # Ensure that the returned value isn't derived from Hash 589 return string_PHashType(val_type, hash, format_map, indent) if hash.instance_of?(Hash) 590 elsif val.is_a?(Array) 591 array = val.to_a 592 # Ensure that the returned value isn't derived from Array 593 return string_PArrayType(val_type, array, format_map, indent) if array.instance_of?(Array) 594 end 595 596 f = get_format(val_type, format_map) 597 case f.format 598 when :s 599 val.to_s 600 when :p 601 puppet_quote(val.to_s) 602 when :q 603 val.inspect 604 else 605 raise FormatError.new('Runtime', f.format, 'spq') 606 end 607 end
@api private
# File lib/puppet/pops/types/string_converter.rb 806 def string_PStringType(val_type, val, format_map, _) 807 f = get_format(val_type, format_map) 808 case f.format 809 when :s 810 Kernel.format(f.orig_fmt, val) 811 812 when :p 813 apply_string_flags(f, puppet_quote(val, f.alt?)) 814 815 when :c 816 c_val = val.capitalize 817 f.alt? ? apply_string_flags(f, puppet_quote(c_val)) : Kernel.format(f.orig_fmt.tr('c', 's'), c_val) 818 819 when :C 820 c_val = val.split('::').map {|s| s.capitalize }.join('::') 821 f.alt? ? apply_string_flags(f, puppet_quote(c_val)) : Kernel.format(f.orig_fmt.tr('C', 's'), c_val) 822 823 when :u 824 c_val = val.upcase 825 f.alt? ? apply_string_flags(f, puppet_quote(c_val)) : Kernel.format(f.orig_fmt.tr('u', 's'), c_val) 826 827 when :d 828 c_val = val.downcase 829 f.alt? ? apply_string_flags(f, puppet_quote(c_val)) : Kernel.format(f.orig_fmt.tr('d', 's'), c_val) 830 831 when :t # trim 832 c_val = val.strip 833 f.alt? ? apply_string_flags(f, puppet_quote(c_val)) : Kernel.format(f.orig_fmt.tr('t', 's'), c_val) 834 835 else 836 raise FormatError.new('String', f.format, 'cCudspt') 837 end 838 end
@api private
# File lib/puppet/pops/types/string_converter.rb 1089 def string_PStructType(val_type, val, format_map, indentation) 1090 string_PHashType(val_type, val, format_map, indentation) 1091 end
@api private
# File lib/puppet/pops/types/string_converter.rb 1023 def string_PTupleType(val_type, val, format_map, indentation) 1024 string_PArrayType(val_type, val, format_map, indentation) 1025 end
@api private
# File lib/puppet/pops/types/string_converter.rb 1094 def string_PTypeType(val_type, val, format_map, _) 1095 f = get_format(val_type, format_map) 1096 case f.format 1097 when :s 1098 str_val = f.alt? ? "\"#{val}\"" : val.to_s 1099 Kernel.format(f.orig_fmt, str_val) 1100 when :p 1101 Kernel.format(f.orig_fmt.tr('p', 's'), val.to_s) 1102 else 1103 raise FormatError.new('Type', f.format, 'sp') 1104 end 1105 end
@api private
# File lib/puppet/pops/types/string_converter.rb 1108 def string_PURIType(val_type, val, format_map, indentation) 1109 f = get_format(val_type, format_map) 1110 case f.format 1111 when :p 1112 fmt = TypeFormatter.singleton 1113 indentation = indentation.indenting(f.alt? || indentation.is_indenting?) 1114 fmt = fmt.indented(indentation.level, 2) if indentation.is_indenting? 1115 fmt.string(val) 1116 when :s 1117 str_val = val.to_s 1118 Kernel.format(f.orig_fmt, f.alt? ? puppet_quote(str_val) : str_val) 1119 else 1120 raise FormatError.new('URI', f.format, 'sp') 1121 end 1122 end
@api private
# File lib/puppet/pops/types/string_converter.rb 631 def string_PUndefType(val_type, val, format_map, _) 632 f = get_format(val_type, format_map) 633 apply_string_flags(f, case f.format 634 when :n 635 f.alt? ? 'null' : 'nil' 636 when :u 637 f.alt? ? 'undefined' : 'undef' 638 when :d, :x, :X, :o, :b, :B, :e, :E, :f, :g, :G, :a, :A 639 'NaN' 640 when :v 641 'n/a' 642 when :V 643 'N/A' 644 when :s 645 f.alt? ? '""' : '' 646 when :p 647 f.alt? ? '"undef"' : 'undef' 648 else 649 raise FormatError.new('Undef', f.format, 'nudxXobBeEfgGaAvVsp') 650 end) 651 end
Private Instance Methods
# 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 522 def _convert(val_type, value, format_map, indentation) 523 @string_visitor.visit_this_3(self, val_type, value, format_map, indentation) 524 end
Performs post-processing of literals to apply width and precision flags
# File lib/puppet/pops/types/string_converter.rb 701 def apply_string_flags(f, literal_str) 702 if f.left || f.width || f.prec 703 fmt = '%' 704 fmt << '-' if f.left 705 fmt << f.width.to_s if f.width 706 fmt << '.' << f.prec.to_s if f.prec 707 fmt << 's' 708 Kernel.format(fmt, literal_str) 709 else 710 literal_str 711 end 712 end
Maps the inferred type of o to a formatting rule
# File lib/puppet/pops/types/string_converter.rb 1125 def get_format(val_t, format_options) 1126 fmt = format_options.find {|k,_| k.assignable?(val_t) } 1127 return fmt[1] unless fmt.nil? 1128 return Format.new("%s") 1129 end
# File lib/puppet/pops/types/string_converter.rb 549 def validate_container_input(fmt) 550 if (fmt.keys - FMT_KEYS).size > 0 551 raise ArgumentError, "only #{FMT_KEYS.map {|k| "'#{k}'"}.join(', ')} are allowed in a container format, got #{fmt}" 552 end 553 result = Format.new(fmt['format']) 554 result.separator = fmt['separator'] 555 result.separator2 = fmt['separator2'] 556 result.container_string_formats = validate_input(fmt['string_formats']) 557 result 558 end
# File lib/puppet/pops/types/string_converter.rb 527 def validate_input(fmt) 528 return nil if fmt.nil? 529 unless fmt.is_a?(Hash) 530 raise ArgumentError, "expected a hash with type to format mappings, got instance of '#{fmt.class}'" 531 end 532 fmt.reduce({}) do | result, entry| 533 key, value = entry 534 unless key.is_a?(Types::PAnyType) 535 raise ArgumentError, "top level keys in the format hash must be data types, got instance of '#{key.class}'" 536 end 537 if value.is_a?(Hash) 538 result[key] = validate_container_input(value) 539 else 540 result[key] = Format.new(value) 541 end 542 result 543 end 544 end