diff options
-rw-r--r-- | .gitignore | 4 | ||||
-rw-r--r-- | src/example.go | 31 | ||||
-rw-r--r-- | src/vparse/vparse.go | 69 | ||||
-rw-r--r-- | vcal.ics | 12 | ||||
-rw-r--r-- | vcard.vcs | 16 |
5 files changed, 132 insertions, 0 deletions
@@ -22,3 +22,7 @@ _testmain.go | |||
22 | *.exe | 22 | *.exe |
23 | *.test | 23 | *.test |
24 | *.prof | 24 | *.prof |
25 | |||
26 | # IDEA | ||
27 | .idea | ||
28 | *.iml | ||
diff --git a/src/example.go b/src/example.go new file mode 100644 index 0000000..9196336 --- /dev/null +++ b/src/example.go | |||
@@ -0,0 +1,31 @@ | |||
1 | package main | ||
2 | |||
3 | import ( | ||
4 | "encoding/json" | ||
5 | "fmt" | ||
6 | "os" | ||
7 | "vparse" | ||
8 | ) | ||
9 | |||
10 | func check(err error) { | ||
11 | if err != nil { | ||
12 | panic(err) | ||
13 | } | ||
14 | } | ||
15 | |||
16 | func vToJson(filename string) string { | ||
17 | f, err := os.Open(filename) | ||
18 | check(err) | ||
19 | |||
20 | parsed := vparse.Parse(f) | ||
21 | |||
22 | jsonEncoded, err := json.MarshalIndent(parsed, "", "\t") | ||
23 | check(err) | ||
24 | |||
25 | return string(jsonEncoded) | ||
26 | } | ||
27 | |||
28 | func main() { | ||
29 | fmt.Println(vToJson("vcal.ics")) | ||
30 | fmt.Println(vToJson("vcard.vcs")) | ||
31 | } | ||
diff --git a/src/vparse/vparse.go b/src/vparse/vparse.go new file mode 100644 index 0000000..624d0a5 --- /dev/null +++ b/src/vparse/vparse.go | |||
@@ -0,0 +1,69 @@ | |||
1 | package vparse | ||
2 | |||
3 | import ( | ||
4 | "bufio" | ||
5 | "io" | ||
6 | "strings" | ||
7 | ) | ||
8 | |||
9 | type Node struct { | ||
10 | Type string | ||
11 | Properties map[string]string | ||
12 | Children []Node | ||
13 | } | ||
14 | |||
15 | func parseNode(scanner *bufio.Scanner, nodeType string) Node { | ||
16 | node := Node{nodeType, make(map[string]string), make([]Node, 0)} | ||
17 | |||
18 | var lastProperty string | ||
19 | var expectColon bool = false | ||
20 | |||
21 | SC: | ||
22 | for scanner.Scan() { | ||
23 | |||
24 | line := scanner.Text() | ||
25 | |||
26 | if strings.HasPrefix(line, " ") { | ||
27 | value := line[1:] | ||
28 | if expectColon { | ||
29 | value = strings.SplitN(value, ":", 2)[1] | ||
30 | } | ||
31 | |||
32 | node.Properties[lastProperty] += value | ||
33 | |||
34 | expectColon = false | ||
35 | continue | ||
36 | } | ||
37 | |||
38 | if !strings.Contains(line, ":") { | ||
39 | lastProperty = line | ||
40 | expectColon = true | ||
41 | continue | ||
42 | } | ||
43 | |||
44 | splitLine := strings.SplitN(line, ":", 2) | ||
45 | |||
46 | switch splitLine[0] { | ||
47 | |||
48 | case "END": | ||
49 | break SC | ||
50 | |||
51 | case "BEGIN": | ||
52 | node.Children = append(node.Children, parseNode(scanner, splitLine[1])) | ||
53 | break | ||
54 | |||
55 | default: | ||
56 | node.Properties[splitLine[0]] = splitLine[1] | ||
57 | lastProperty = splitLine[0] | ||
58 | |||
59 | } | ||
60 | |||
61 | } | ||
62 | |||
63 | return node | ||
64 | } | ||
65 | |||
66 | func Parse(reader io.Reader) []Node { | ||
67 | scanner := bufio.NewScanner(reader) | ||
68 | return parseNode(scanner, "").Children | ||
69 | } | ||
diff --git a/vcal.ics b/vcal.ics new file mode 100644 index 0000000..46df067 --- /dev/null +++ b/vcal.ics | |||
@@ -0,0 +1,12 @@ | |||
1 | BEGIN:VCALENDAR | ||
2 | VERSION:2.0 | ||
3 | PRODID:-//hacksw/handcal//NONSGML v1.0//EN | ||
4 | BEGIN:VEVENT | ||
5 | UID:uid1@example.com | ||
6 | DTSTAMP:19970714T170000Z | ||
7 | ORGANIZER;CN=John Doe:MAILTO:john.doe@example.com | ||
8 | DTSTART:19970714T170000Z | ||
9 | DTEND:19970715T035959Z | ||
10 | SUMMARY:Bastille Day Party | ||
11 | END:VEVENT | ||
12 | END:VCALENDAR | ||
diff --git a/vcard.vcs b/vcard.vcs new file mode 100644 index 0000000..55ee959 --- /dev/null +++ b/vcard.vcs | |||
@@ -0,0 +1,16 @@ | |||
1 | BEGIN:VCARD | ||
2 | VERSION:4.0 | ||
3 | N:Gump;Forrest;;; | ||
4 | FN:Forrest Gump | ||
5 | ORG:Bubba Gump Shrimp Co. | ||
6 | TITLE:Shrimp Man | ||
7 | PHOTO;MEDIATYPE=image/gif:http://www.example.com/dir_photos/my_photo.gif | ||
8 | TEL;TYPE=work,voice;VALUE=uri:tel:+1-111-555-1212 | ||
9 | TEL;TYPE=home,voice;VALUE=uri:tel:+1-404-555-1212 | ||
10 | ADR;TYPE=work;LABEL="100 Waters Edge\nBaytown, LA 30314\nUnited States of America" | ||
11 | :;;100 Waters Edge;Baytown;LA;30314;United States of America | ||
12 | ADR;TYPE=home;LABEL="42 Plantation St.\nBaytown, LA 30314\nUnited States of America" | ||
13 | :;;42 Plantation St.;Baytown;LA;30314;United States of America | ||
14 | EMAIL:forrestgump@example.com | ||
15 | REV:20080424T195243Z | ||
16 | END:VCARD | ||