# File lib/fluent/config/literal_parser.rb, line 51 def initialize(strscan, eval_context) super(strscan) @eval_context = eval_context end
# File lib/fluent/config/literal_parser.rb, line 28 def self.unescape_char(c) case c when '"' '\"' when "'" "\\'" when '\' '\\' when "\r" '\r' when "\n" '\n' when "\t" '\t' when "\f" '\f' when "\b" '\b' else c end end
# File lib/fluent/config/literal_parser.rb, line 161 def eval_embedded_code(code) if @eval_context.nil? parse_error! "embedded code is not allowed in this file" end @eval_context.instance_eval(code) end
# File lib/fluent/config/literal_parser.rb, line 168 def eval_escape_char(c) case c when '"' '"' when "'" "'" when "r" "\r" when "n" "\n" when "t" "\t" when "f" "\f" when "b" "\b" when /[a-zA-Z0-9]/ parse_error! "unexpected back-slash escape character '#{c}'" else # symbols c end end
# File lib/fluent/config/literal_parser.rb, line 56 def parse_literal(string_boundary_charset = LINE_END) spacing_without_comment value = if skip(/\[/) scan_json(true) elsif skip(/\{/) scan_json(false) else scan_string(string_boundary_charset) end value end
# File lib/fluent/config/literal_parser.rb, line 79 def scan_double_quoted_string string = [] while true if skip(/\"/) return string.join elsif check(/[^"]#{LINE_END_WITHOUT_SPACING_AND_COMMENT}/) if s = check(/[^\]#{LINE_END_WITHOUT_SPACING_AND_COMMENT}/) string << s end skip(/[^"]#{LINE_END_WITHOUT_SPACING_AND_COMMENT}/) elsif s = scan(/\./) string << eval_escape_char(s[1,1]) elsif skip(/\#\{/) string << eval_embedded_code(scan_embedded_code) skip(/\}/) elsif s = scan(/./) string << s else parse_error! "unexpected end of file in a double quoted string" end end end
# File lib/fluent/config/literal_parser.rb, line 140 def scan_embedded_code rlex = RubyLex.new src = '"#{'+@ss.rest+"\n=end\n}" input = StringIO.new(src) input.define_singleton_method(:encoding) { external_encoding } rlex.set_input(input) tk = rlex.token code = src[3,tk.seek-3] if @ss.rest.length < code.length @ss.pos += @ss.rest.length parse_error! "expected end of embedded code but $end" end @ss.pos += code.length '"#{' + code + '}"' end
# File lib/fluent/config/literal_parser.rb, line 191 def scan_json(is_array) result = nil # Yajl does not raise ParseError for imcomplete json string, like '[1', '{"h"', '{"h":' or '{"h1":1' # This is the reason to use JSON module. buffer = (is_array ? "[" : "{") line_buffer = "" until result char = getch break if char.nil? if char == "#" # If this is out of json string literals, this object can be parsed correctly # '{"foo":"bar", #' -> '{"foo":"bar"}' (to check) parsed = nil begin parsed = JSON.parse(buffer + line_buffer.rstrip.sub(/,$/, '') + (is_array ? "]" : "}")) rescue JSON::ParserError => e # This '#' is in json string literals end if parsed # ignore chars as comment before newline while (char = getch) != "\n" # ignore comment char end buffer << line_buffer + "\n" line_buffer = "" else # '#' is a char in json string line_buffer << char end next # This char '#' MUST NOT terminate json object. end if char == "\n" buffer << line_buffer + "\n" line_buffer = "" next end line_buffer << char begin result = JSON.parse(buffer + line_buffer) rescue JSON::ParserError => e # Incomplete json string yet end end unless result parse_error! "got incomplete JSON #{is_array ? 'array' : 'hash'} configuration" end JSON.dump(result) end
# File lib/fluent/config/literal_parser.rb, line 119 def scan_nonquoted_string(boundary_charset = LINE_END) charset = /(?!#{boundary_charset})./ string = [] while true if s = scan(/\#/) string << '#' elsif s = scan(charset) string << s else break end end if string.empty? return nil end string.join end
# File lib/fluent/config/literal_parser.rb, line 102 def scan_single_quoted_string string = [] while true if skip(/\/) return string.join elsif s = scan(/\'/) string << "'" elsif s = scan(/\\/) string << "\\" elsif s = scan(/./) string << s else parse_error! "unexpected end of file in a signle quoted string" end end end
# File lib/fluent/config/literal_parser.rb, line 69 def scan_string(string_boundary_charset = LINE_END) if skip(/\"/) return scan_double_quoted_string elsif skip(/\/) return scan_single_quoted_string else return scan_nonquoted_string(string_boundary_charset) end end