Class: Icalendar::Parser

Inherits:
Base show all
Defined in:
lib/icalendar/parser.rb

Constant Summary collapse

NAME =

1*(ALPHA / DIGIT / “=”)

'[-a-z0-9]+'
QSTR =

<“> <Any character except CTLs, DQUOTE> <”>

'"[^"]*"'
PTEXT =

*<Any character except CTLs, DQUOTE, “;”, “:”, “,”>

'[^";:,]*'
PVALUE =

param-value = ptext / quoted-string

"#{PTEXT}|#{QSTR}"
LINE =

Contentline

"(#{NAME})([^:]*)\:(.*)"
PARAM =

param = name “=” param-value *(“,” param-value)

";(#{NAME})(=?)((?:#{PVALUE})(?:,#{PVALUE})*)"
DATE =

date = date-fullyear [“-”] date-month [“-”] date-mday date-fullyear = 4 DIGIT date-month = 2 DIGIT date-mday = 2 DIGIT

'(\d\d\d\d)-?(\d\d)-?(\d\d)'
TIME =

time = time-hour [“:”] time-minute [“:”] time-second [time-secfrac] [time-zone] time-hour = 2 DIGIT time-minute = 2 DIGIT time-second = 2 DIGIT time-secfrac = “,” 1*DIGIT time-zone = “Z” / time-numzone time-numzome = sign time-hour [“:”] time-minute

'(\d\d):?(\d\d):?(\d\d)(\.\d+)?(Z|[-+]\d\d:?\d\d)?'

Instance Method Summary collapse

Constructor Details

#initialize(src) ⇒ Parser

Returns a new instance of Parser.



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
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
# File 'lib/icalendar/parser.rb', line 48

def initialize(src)
  @@logger.debug("New Calendar Parser")

  # Setup the parser method hash table
  setup_parsers()

  # Define the next line method different depending on whether
  # this is a string or an IO object so we can be efficient about
  # parsing large files...

  # Just do the unfolding work in one shot if its a whole string
  if src.respond_to?(:split)
    unfolded = []

    # Split into an array of lines, then unfold those into a new array
    src.split(/\r?\n/).each do |line|

      # If it's a continuation line, add it to the last.
      # If it's an empty line, drop it from the input.
      if( line =~ /^[ \t]/ )
        unfolded << unfolded.pop + line[1, line.size-1]
      elsif( line =~ /^$/ )
      else
        unfolded << line
      end
    end

    @lines = unfolded
    @index = 0

    # Now that we are unfolded we can just iterate through the array.
    # Dynamically define next line for a string.
    def next_line
      if @index == @lines.size
        return nil
      else
        line = @lines[@index]
        @index += 1
        return line
      end
    end

    # If its a file we need to read and unfold on the go to save from reading
    # large amounts of data into memory.
  elsif src.respond_to?(:gets)
    @file = src
    @prev_line = src.gets
    if !@prev_line.nil?
      @prev_line.chomp!
    end

    # Dynamically define next line for an IO object
    def next_line
      line = @prev_line

      if line.nil? 
        return nil 
      end

      # Loop through until we get to a non-continuation line...
      loop do
        nextLine = @file.gets
        if !nextLine.nil?
          nextLine.chomp!
        end

        # If it's a continuation line, add it to the last.
        # If it's an empty line, drop it from the input.
        if( nextLine =~ /^[ \t]/ )
          line << nextLine[1, nextLine.size]
        elsif( nextLine =~ /^$/ )
        else
          @prev_line = nextLine
          break
        end
      end
      line
    end
  else
    raise ArgumentError, "CalendarParser.new cannot be called with a #{src.class} type!"
  end
end

Instance Method Details

#parseObject

Parse the calendar into an object representation



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/icalendar/parser.rb', line 132

def parse
  calendars = []

  # Outer loop for Calendar objects
  while (line = next_line)
    fields = parse_line(line)

    # Just iterate through until we find the beginning of a calendar object
    if fields[:name] == "BEGIN" and fields[:value] == "VCALENDAR"
      cal = parse_component
      calendars << cal
    end
  end

  calendars
end