Class: RiCal::Parser
Overview
-
©2009 Rick DeNatale
-
All rights reserved. Refer to the file README.txt for the license
Class Method Summary collapse
-
.params_and_value(string, optional_initial_semi = false) ⇒ Object
:nodoc:.
-
.parse(io = StringIO.new("")) ⇒ Object
:nodoc:.
-
.parse_params(string) ⇒ Object
:nodoc:.
Instance Method Summary collapse
-
#buffer_or_line ⇒ Object
:nodoc:.
-
#initialize(io = StringIO.new("")) ⇒ Parser
constructor
:nodoc:.
-
#invalid ⇒ Object
:nodoc:.
-
#next_line ⇒ Object
:nodoc:.
-
#next_separated_line ⇒ Object
:nodoc:.
-
#parse ⇒ Object
:nodoc:.
-
#parse_one(start, parent_component) ⇒ Object
TODO: Need to parse non-standard component types (iana-token or x-name).
-
#separate_line(string) ⇒ Object
:nodoc:.
-
#still_in(component, separated_line) ⇒ Object
:nodoc:.
Constructor Details
#initialize(io = StringIO.new("")) ⇒ Parser
:nodoc:
79 80 81 |
# File 'lib/ri_cal/parser.rb', line 79 def initialize(io = StringIO.new("")) #:nodoc: @io = io end |
Class Method Details
.params_and_value(string, optional_initial_semi = false) ⇒ Object
:nodoc:
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/ri_cal/parser.rb', line 38 def self.params_and_value(string, optional_initial_semi = false) #:nodoc: string = string.sub(/^:/,'') return [{}, string] unless optional_initial_semi || string.match(/^;/) segments = string.sub(';','').split(":") return [{}, string] if segments.length < 2 quote_count = 0 gathering_params = true params = [] values = [] segments.each do |segment| if gathering_params params << segment quote_count += segment.count("\"") gathering_params = (1 == quote_count % 2) else values << segment end end [parse_params(params.join(":")), values.join(":")] end |
.parse(io = StringIO.new("")) ⇒ Object
:nodoc:
83 84 85 |
# File 'lib/ri_cal/parser.rb', line 83 def self.parse(io = StringIO.new("")) #:nodoc: new(io).parse end |
.parse_params(string) ⇒ Object
:nodoc:
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/ri_cal/parser.rb', line 22 def self.parse_params(string) #:nodoc: if string string.split(";").inject({}) { |result, val| m = /^(.+)=(.+)$/.match(val) raise "Invalid parameter value #{val.inspect}" unless m #TODO - The gsub below is a simplest fix for http://rick_denatale.lighthouseapp.com/projects/30941/tickets/19 # it may need further examination if more pathological cases show up. param_val = m[2].sub(/^\"(.*)\"$/, '\1') result[m[1]] = param_val result } else nil end end |
Instance Method Details
#buffer_or_line ⇒ Object
:nodoc:
75 76 77 |
# File 'lib/ri_cal/parser.rb', line 75 def buffer_or_line #:nodoc: @buffer ||= @io.readline.chomp end |
#invalid ⇒ Object
:nodoc:
87 88 89 |
# File 'lib/ri_cal/parser.rb', line 87 def invalid #:nodoc: raise Exception.new("Invalid icalendar file") end |
#next_line ⇒ Object
:nodoc:
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# File 'lib/ri_cal/parser.rb', line 6 def next_line #:nodoc: result = nil begin result = buffer_or_line @buffer = nil while /^\s/ =~ buffer_or_line result = "#{result}#{@buffer[1..-1]}" @buffer = nil end rescue EOFError return nil ensure return result end end |
#next_separated_line ⇒ Object
:nodoc:
70 71 72 73 |
# File 'lib/ri_cal/parser.rb', line 70 def next_separated_line #:nodoc: line = next_line line ? separate_line(line) : nil end |
#parse ⇒ Object
:nodoc:
96 97 98 99 100 101 102 103 |
# File 'lib/ri_cal/parser.rb', line 96 def parse #:nodoc: result = [] while start_line = next_line @parent_stack = [] result << parse_one(start_line, nil) end result end |
#parse_one(start, parent_component) ⇒ Object
TODO: Need to parse non-standard component types (iana-token or x-name)
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/ri_cal/parser.rb', line 106 def parse_one(start, parent_component) #:nodoc: @parent_stack << parent_component if Hash === start first_line = start else first_line = separate_line(start) end invalid unless first_line[:name] == "BEGIN" result = case first_line[:value] when "VCALENDAR" RiCal::Component::Calendar.from_parser(self, parent_component) when "VEVENT" RiCal::Component::Event.from_parser(self, parent_component) when "VTODO" RiCal::Component::Todo.from_parser(self, parent_component) when "VJOURNAL" RiCal::Component::Journal.from_parser(self, parent_component) when "VFREEBUSY" RiCal::Component::Freebusy.from_parser(self, parent_component) when "VTIMEZONE" RiCal::Component::Timezone.from_parser(self, parent_component) when "VALARM" RiCal::Component::Alarm.from_parser(self, parent_component) when "DAYLIGHT" RiCal::Component::Timezone::DaylightPeriod.from_parser(self, parent_component) when "STANDARD" RiCal::Component::Timezone::StandardPeriod.from_parser(self, parent_component) else invalid end @parent_stack.pop result end |
#separate_line(string) ⇒ Object
:nodoc:
59 60 61 62 63 64 65 66 67 68 |
# File 'lib/ri_cal/parser.rb', line 59 def separate_line(string) #:nodoc: match = string.match(/^([^;:]*)(.*)$/) name = match[1] params, value = *Parser.params_and_value(match[2]) { :name => name, :params => params, :value => value } end |
#still_in(component, separated_line) ⇒ Object
:nodoc:
91 92 93 94 |
# File 'lib/ri_cal/parser.rb', line 91 def still_in(component, separated_line) #:nodoc: invalid unless separated_line separated_line[:value] != component || separated_line[:name] != "END" end |