split the report into lines
[opensuse:apport-opensuse-crashdb.git] / lib / crash_log.rb
1 class CrashLog < Hash
2   class ParseError < Exception; end
3   attr_reader :log_text
4
5   def initialize(log_string)
6     super()
7     @debug = Object.const_defined?(:CRASHLOG_DEBUG) ? CRASHLOG_DEBUG : false
8     @log_text = log_string
9     @position = Hash.new
10     parse_log @log_text
11   end
12
13   def position(key)
14     @position[key]
15   end
16
17   def to_s
18     a = []
19     self.each do |key, value|
20       a << "#{key}: #{value}"
21     end
22     a.join("\n")
23   end
24
25   private
26   def parse_log(log_string)
27     current_position = 0
28     is_multiline = false
29     multiline_value = String.new
30     multiline_key = String.new
31
32     log_string.split(/\n/).each do |line|
33       if is_multiline
34         if line =~ /^ (.*)$/
35           debug_print "multiline val: #{$1.inspect}"
36           multiline_value += "\n " + $1
37         else
38           is_multiline = false
39           @position[multiline_key] = current_position
40           current_position += 1
41           self[multiline_key] = multiline_value
42           multiline_value = String.new
43           redo
44         end
45       else
46         if line =~ /^(\w+): (.+)$/
47           if $2 == "base64"
48             debug_print "multiline base64 key: #{$1.inspect}"
49             multiline_key = $1
50             is_multiline = true
51             multiline_value = "base64"
52           else
53             debug_print "single line: key #{$1.inspect} | val #{$2.inspect}"
54             self[$1] = $2
55             @position[$1] = current_position
56             current_position += 1
57           end
58         elsif line =~ /^(\w+):\s*$/
59           debug_print "multiline key: #{$1.inspect}"
60           multiline_key = $1
61           is_multiline = true
62         else
63           raise ParseError, "invalid line: #{line.inspect}"
64         end
65       end
66     end
67     if is_multiline and not multiline_value.blank?
68       debug_print "pending multiline key"
69       is_multiline = false
70       self[multiline_key] = multiline_value
71       @position[multiline_key] = current_position
72       current_position += 1
73     end
74   end
75
76   def debug_print(str)
77     STDERR.puts str if @debug
78   end
79
80 end