class TwitterCldr::Utils::YAML
Constants
- ESCAPE_SEQ
non-break characters
- ESCAPE_SEQ_LB
line breaks
- ESCAPE_SEQ_NS
non-breaking space
- ESCAPE_SEQ_WS
white spaces
- REX_ANY_LB
- REX_BOOL
regexps for language-Independent types for YAML1.1
- REX_CR
- REX_CRLF
- REX_FLOAT
- REX_INT
- REX_LF
regexps for line breaks
- REX_LS
- REX_MERGE
- REX_NEL
- REX_NORMAL_LB
- REX_NULL
- REX_PS
- REX_SYMBOL
- REX_TIMESTAMP
- REX_VALUE
- UCS_0X2028
- UCS_0X2029
- UCS_0X85
- UCS_0XA0
Public Class Methods
dump(obj, opts = {})
click to toggle source
# File lib/twitter_cldr/utils/yaml.rb, line 130 def dump(obj, opts = {}) @options = opts.dup @options[:indent_size] = 2 if @options[:indent_size].to_i <= 0 @options[:minimum_block_length] = 0 if @options[:minimum_block_length].to_i <= 0 @options.update( { printable_with_syck: true, escape_b_specific: true, escape_as_utf8: true, } ) if @options[:syck_compatible] "--- #{emit(obj, 1)}\n" rescue SystemStackError raise ArgumentError, "TwitterCLDR yaml dumper can't handle circular references" end
Private Class Methods
emit(obj, level)
click to toggle source
# File lib/twitter_cldr/utils/yaml.rb, line 149 def emit(obj, level) case obj when Array if (obj.length == 0) '[]' else indent = "\n#{s_indent(level - 1)}" obj.collect do |o| "#{indent}- #{emit(o, level + 1)}" end.join('') end when Hash if (obj.length == 0) '{}' else indent = "\n#{s_indent(level - 1)}" hash_order = @options[:hash_order] if (hash_order && level == 1) hash_keys = obj.keys.sort do |x, y| x_order = hash_order.index(x) ? hash_order.index(x) : Float::MAX y_order = hash_order.index(y) ? hash_order.index(y) : Float::MAX o = (x_order <=> y_order) (o != 0) ? o : (x.to_s <=> y.to_s) end elsif @options[:preserve_order] hash_keys = obj.keys else hash_keys = obj.keys.sort { |x, y| x.to_s <=> y.to_s } end hash_keys.collect do |k| key = emit(k, level + 1) if ( is_one_plain_line?(key) || key =~ /\A(#{REX_BOOL}|#{REX_FLOAT}|#{REX_INT}|#{REX_NULL}|#{REX_SYMBOL})\z/x ) "#{indent}#{key}: #{emit(obj[k], level + 1)}" else "#{indent}? #{key}#{indent}: #{emit(obj[k], level + 1)}" end end.join('') end when NilClass '~' when String emit_string(obj, level) when TrueClass, FalseClass obj.to_s when Integer, Float obj.to_s when Date obj.to_s when Time offset = obj.gmtoff off_hm = sprintf( '%+.2d:%.2d', (offset / 3600.0).to_i, (offset % 3600.0) / 60 ) u_sec = (obj.usec != 0) ? sprintf(".%.6d", obj.usec) : '' obj.strftime("%Y-%m-%d %H:%M:%S#{u_sec} #{off_hm}") when Symbol prefix = @options[:use_natural_symbols] && is_one_plain_line?(obj.to_s) ? ":" : "!ruby/symbol " "#{prefix}#{emit_string(obj, level)}" when Range '!ruby/range ' + obj.to_s when Regexp '!ruby/regexp ' + obj.inspect else case when obj.is_a?(Struct) struct_members = {} obj.each_pair { |k, v| struct_members[k.to_s] = v } "!ruby/struct:#{obj.class.to_s.sub(/^(Struct::(.+)|.*)$/, '\2')} #{emit(struct_members, level + 1)}" else # serialized as a generic object object_members = {} obj.instance_variables.each do |k, v| object_members[k.to_s.sub(/^@/, '')] = obj.instance_variable_get(k) end "!ruby/object:#{obj.class.to_s} #{emit(object_members, level + 1)}" end end end
emit_base64_binary(str, level)
click to toggle source
# File lib/twitter_cldr/utils/yaml.rb, line 297 def emit_base64_binary(str, level) indent = "\n#{s_indent(level)}" base64 = [str].pack('m') "!binary |#{indent}#{base64.gsub(/\n(?!\z)/, indent)}" end
emit_block_string(str, level)
click to toggle source
# File lib/twitter_cldr/utils/yaml.rb, line 261 def emit_block_string(str, level) str = normalize_line_break(str) indent = s_indent(level) indentation_indicator = (str =~ /\A /) ? indent.size.to_s : '' str =~ /(#{REX_NORMAL_LB}*)\z/ chomping_indicator = case $1.length when 0 '-' when 1 '' else '+' end str.chomp! str.gsub!(/#{REX_NORMAL_LB}/) { $1 + indent } "|#{indentation_indicator}#{chomping_indicator}\n#{indent}#{str}" end
emit_quoted_string(str, level)
click to toggle source
# File lib/twitter_cldr/utils/yaml.rb, line 281 def emit_quoted_string(str, level) str = yaml_escape(normalize_line_break(str)) if (str.length < @options[:minimum_block_length]) str.gsub!(/#{REX_NORMAL_LB}/) { ESCAPE_SEQ_LB[$1] } else str.gsub!(/#{REX_NORMAL_LB}$/) { ESCAPE_SEQ_LB[$1] } str.gsub!(/(#{REX_NORMAL_LB}+)(.)/) do trail_c = $3 $1 + trail_c.sub(/([\t ])/) { ESCAPE_SEQ_WS[$1] } end indent = s_indent(level) str.gsub!(/#{REX_NORMAL_LB}/) { "#{ESCAPE_SEQ_LB[$1]}\\\n#{indent}" } end %Q("#{str}") end
emit_simple_string(str, level)
click to toggle source
# File lib/twitter_cldr/utils/yaml.rb, line 257 def emit_simple_string(str, level) str end
emit_string(str, level)
click to toggle source
# File lib/twitter_cldr/utils/yaml.rb, line 233 def emit_string(str, level) if @options[:quote_all_strings] && !str.is_a?(Symbol) emit_quoted_string(str, level) else str = str.to_s (is_string, is_printable, is_one_line, is_one_plain_line) = string_type(str) if is_string if is_printable if is_one_plain_line emit_simple_string(str, level) else (is_one_line || str.length < @options[:minimum_block_length]) ? emit_quoted_string(str, level) : emit_block_string(str, level) end else emit_quoted_string(str, level) end else emit_base64_binary(str, level) end end end
is_one_line?(str)
click to toggle source
# File lib/twitter_cldr/utils/yaml.rb, line 340 def is_one_line?(str) str !~ /#{REX_ANY_LB}(?!\z)/ end
is_one_plain_line?(str)
click to toggle source
# File lib/twitter_cldr/utils/yaml.rb, line 344 def is_one_plain_line?(str) # YAML 1.1 / 4.6.11. str !~ /^([\-\?:,\[\]\{\}\#&\*!\|>'"%@`\s]|---|\.\.\.)/ && str !~ /[:\#\s\[\]\{\},]/ && str !~ /#{REX_ANY_LB}/ && str !~ /^(#{REX_BOOL}|#{REX_FLOAT}|#{REX_INT}|#{REX_MERGE} |#{REX_NULL}|#{REX_TIMESTAMP}|#{REX_VALUE})$/x end
is_printable?(ucs_code)
click to toggle source
# File lib/twitter_cldr/utils/yaml.rb, line 324 def is_printable?(ucs_code) # YAML 1.1 / 4.1.1. ( [0x09, 0x0a, 0x0d, 0x85].include?(ucs_code) || (ucs_code <= 0x7e && ucs_code >= 0x20) || (ucs_code <= 0xd7ff && ucs_code >= 0xa0) || (ucs_code <= 0xfffd && ucs_code >= 0xe000) || (ucs_code <= 0x10ffff && ucs_code >= 0x10000) ) && !( # treat LS/PS as non-printable characters @options[:escape_b_specific] && (ucs_code == 0x2028 || ucs_code == 0x2029) ) end
normalize_line_break(str)
click to toggle source
# File lib/twitter_cldr/utils/yaml.rb, line 358 def normalize_line_break(str) # YAML 1.1 / 4.1.4. str.gsub(/(#{REX_CRLF}|#{REX_CR}|#{REX_NEL})/, "\n") end
s_indent(level)
click to toggle source
# File lib/twitter_cldr/utils/yaml.rb, line 353 def s_indent(level) # YAML 1.1 / 4.2.2. ' ' * (level * @options[:indent_size]) end
string_type(str)
click to toggle source
# File lib/twitter_cldr/utils/yaml.rb, line 303 def string_type(str) if str.respond_to?(:encoding) && (!str.valid_encoding? || str.encoding == Encoding::ASCII_8BIT) return false, false, false, false end (ucs_codes = str.unpack('U*')) rescue ( # ArgumentError -> binary data return false, false, false, false ) if ( @options[:printable_with_syck] && str =~ /\A#{REX_ANY_LB}* | #{REX_ANY_LB}*\z|#{REX_ANY_LB}{2}\z/ ) # detour Syck bug return true, false, nil, false end ucs_codes.each {|ucs_code| return true, false, nil, false unless is_printable?(ucs_code) } return true, true, is_one_line?(str), is_one_plain_line?(str) end
yaml_escape(str)
click to toggle source
# File lib/twitter_cldr/utils/yaml.rb, line 363 def yaml_escape(str) # YAML 1.1 / 4.1.6. str.gsub(/[^a-zA-Z0-9]/u) do |c| ucs_code, = (c.unpack('U') rescue [??]) case when ESCAPE_SEQ[c] ESCAPE_SEQ[c] when is_printable?(ucs_code) c when @options[:escape_as_utf8] c.respond_to?(:bytes) ? c.bytes.collect { |b| '\\x%.2x' % b }.join : '\\x' + c.unpack('H2' * c.size).join('\\x') when ucs_code == 0x2028 || ucs_code == 0x2029 ESCAPE_SEQ_LB[c] when ucs_code <= 0x7f sprintf('\\x%.2x', ucs_code) when ucs_code <= 0xffff sprintf('\\u%.4x', ucs_code) else sprintf('\\U%.8x', ucs_code) end end end