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:
76 77 78 |
# File 'lib/ri_cal/parser.rb', line 76 def initialize(io = StringIO.new("")) #:nodoc: @io = io end |
Class Method Details
.params_and_value(string, optional_initial_semi = false) ⇒ Object
:nodoc:
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/ri_cal/parser.rb', line 35 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:
80 81 82 |
# File 'lib/ri_cal/parser.rb', line 80 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 |
# 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 result[m[1]] = m[2] result } else nil end end |
Instance Method Details
#buffer_or_line ⇒ Object
:nodoc:
72 73 74 |
# File 'lib/ri_cal/parser.rb', line 72 def buffer_or_line #:nodoc: @buffer ||= @io.readline.chomp end |
#invalid ⇒ Object
:nodoc:
84 85 86 |
# File 'lib/ri_cal/parser.rb', line 84 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:
67 68 69 70 |
# File 'lib/ri_cal/parser.rb', line 67 def next_separated_line #:nodoc: line = next_line line ? separate_line(line) : nil end |
#parse ⇒ Object
:nodoc:
93 94 95 96 97 98 99 100 |
# File 'lib/ri_cal/parser.rb', line 93 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)
103 104 105 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 |
# File 'lib/ri_cal/parser.rb', line 103 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:
56 57 58 59 60 61 62 63 64 65 |
# File 'lib/ri_cal/parser.rb', line 56 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:
88 89 90 91 |
# File 'lib/ri_cal/parser.rb', line 88 def still_in(component, separated_line) #:nodoc: invalid unless separated_line separated_line[:value] != component || separated_line[:name] != "END" end |