Merge the recent changes from HEAD onto the branch
[beagle.git] / Util / ICalParser.cs
blob4ecf22251bf4abc0fc9a2b30b2d55e2bb341f337
1 //
2 // ICalParser.cs
3 //
4 // Copyright (C) 2006 Novell, Inc.
5 //
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in all
16 // copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 // SOFTWARE.
27 using System;
28 using System.IO;
29 using System.Text;
30 using System.Collections;
32 namespace Beagle.Util
34 public class ICalParser : IEnumerator
36 public static string KabcMimeType = "text/x-kabc-directory";
37 public static string KnotesMimeType = "text/x-knotes-calendar";
39 private ParserState state = ParserState.ParsingProperty;
40 private StringBuilder buffer = new StringBuilder ();
42 private Token current;
43 private TextReader reader;
45 public ICalParser (TextReader reader)
47 this.reader = new UnfoldingTextReader (reader);
50 public object Current
52 get { return current; }
55 public bool MoveNext ()
57 string data;
58 char stop;
60 switch (state) {
61 case ParserState.ParsingProperty:
62 data = Read (new char [] { ':', ';' }, out stop);
64 if (data == null)
65 return false;
67 switch (stop) {
68 case ':':
69 state = ParserState.ParsingPropertyValue;
70 break;
71 case ';':
72 state = ParserState.ParsingPropertyParameter;
73 break;
76 current = new Token (TokenType.Property, data.Trim ());
77 break;
78 case ParserState.ParsingPropertyValue:
79 data = Read (new char[] { '\n'}, out stop);
81 if (data == null)
82 return false;
84 switch (stop) {
85 case '\n':
86 state = ParserState.ParsingProperty;
87 break;
88 case ',':
89 state = ParserState.ParsingPropertyValue;
90 break;
93 current = new Token (TokenType.PropertyValue, data.Trim ());
94 break;
95 case ParserState.ParsingPropertyParameter:
96 data = Read (new char[] { '\n', '=', ';', ','}, out stop);
98 if (data == null)
99 return false;
101 switch (stop) {
102 case '=':
103 state = ParserState.ParsingPropertyParameterValue;
104 break;
105 case '\n':
106 state = ParserState.ParsingProperty;
107 break;
108 case ';':
109 case ',':
110 break;
113 current = new Token (TokenType.PropertyParameter, data.Trim ());
114 break;
115 case ParserState.ParsingPropertyParameterValue:
116 data = Read (new char[] { ',', ':', ';' }, out stop);
118 switch (stop) {
119 case ';':
120 state = ParserState.ParsingPropertyParameter;
121 break;
122 case ':':
123 state = ParserState.ParsingPropertyValue;
124 break;
125 case ',':
126 break;
129 current = new Token (TokenType.PropertyParameterValue, data.Trim ());
130 break;
133 return true;
136 public void Reset()
138 throw new NotImplementedException ();
141 public void Dispose()
146 private string Read (char[] stops, out char stop)
148 stop = (char) 0;
150 lock (buffer) {
151 int i;
152 buffer.Length = 0;
154 while ((i = reader.Read ()) != -1) {
155 if (Array.IndexOf (stops, (char) i) != -1) {
156 stop = (char) i;
157 break;
160 buffer.Append((char)i);
163 return (buffer.Length == 0) ? null : buffer.ToString ();
167 public class Token
169 private TokenType type;
170 private string value;
172 public TokenType Type
174 get { return type; }
177 public string Value
179 get { return value; }
182 public Token (TokenType type, string value)
184 this.type = type;
185 this.value = value;
188 public override string ToString ()
190 return String.Format ("{0} ({1})", type, value);
194 public enum TokenType
196 Property,
197 PropertyValue,
198 PropertyParameter,
199 PropertyParameterValue,
202 private enum ParserState
204 ParsingProperty,
205 ParsingPropertyValue,
206 ParsingPropertyParameter,
207 ParsingPropertyParameterValue
210 private class UnfoldingTextReader : TextReader
212 private TextReader reader;
214 public UnfoldingTextReader(TextReader reader)
216 this.reader = reader;
219 public override int Read ()
221 int i = reader.Read ();
223 if (i == '\r')
224 i = reader.Read ();
226 if ((char) i == '\n' && (char) reader.Peek() == ' ') {
227 do {
228 i = reader.Read ();
230 if ((char) i == '\r')
231 i = reader.Read ();
232 } while ((char) i == ' ' || (char) i == '\n');
234 return i;
239 #if false
240 class Driver
242 static void Main (string [] args)
244 ICalParser parser = new ICalParser (File.OpenText ("test.ical"));
246 while (parser.MoveNext()) {
247 ICalParser.Token token = (ICalParser.Token) parser.Current;
249 if (token.Type != ICalParser.TokenType.Property)
250 Console.Write ("\t");
252 if (token.Type == ICalParser.TokenType.PropertyParameterValue)
253 Console.Write ("\t");
255 Console.WriteLine (token);
259 #endif