forked from piranha/gostatic
/
header.go
101 lines (87 loc) · 1.99 KB
/
header.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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
// (c) 2012 Alexander Solovyov
// under terms of ISC license
package main
import (
"fmt"
"reflect"
"strings"
"time"
)
type PageHeader struct {
Title string
Tags []string
Date time.Time
Other map[string]string
}
var DATEFORMATS = []string{
"2006-01-02 15:04:05 -07",
"2006-01-02 15:04:05",
"2006-01-02 15:04",
"2006-01-02 15",
"2006-01-02",
"06-01-02",
}
func NewPageHeader() *PageHeader {
return &PageHeader{Other: make(map[string]string)}
}
func (cfg *PageHeader) ParseLine(line string, s *reflect.Value) {
// Skip empty lines and comments
line = strings.SplitN(line, "//", 2)[0]
line = strings.TrimSpace(line)
if len(line) == 0 {
return
}
// Split line in actual name and value
parts := strings.SplitN(line, ":", 2)
key := strings.ToUpper(parts[0][0:1]) + strings.TrimSpace(parts[0][1:])
value := strings.TrimSpace(parts[1])
cfg.SetValue(key, value, s)
}
func (cfg *PageHeader) SetValue(key string, value string, s *reflect.Value) {
// put unknown fields into a map
if _, ok := s.Type().FieldByName(key); !ok {
cfg.Other[key] = strings.TrimSpace(value)
return
}
// Set value
f := s.FieldByName(key)
switch f.Interface().(type) {
default:
errhandle(fmt.Errorf("Unknown type of field %s", key))
case string:
f.SetString(value)
case []string:
values := strings.Split(value, ",")
for i, v := range values {
values[i] = strings.TrimSpace(v)
}
f.Set(reflect.ValueOf(values))
case time.Time:
var t time.Time
var err error
for _, fmt := range DATEFORMATS {
t, err = time.Parse(fmt, value)
if err == nil {
break
}
}
errhandle(err)
f.Set(reflect.ValueOf(t))
}
}
func ParseHeader(source string) *PageHeader {
cfg := NewPageHeader()
s := reflect.ValueOf(cfg).Elem()
// Set default values
t := s.Type()
for i := 0; i < s.NumField(); i++ {
def := t.Field(i).Tag.Get("default")
if len(def) != 0 {
cfg.SetValue(t.Field(i).Name, def, &s)
}
}
for _, line := range strings.Split(source, "\n") {
cfg.ParseLine(line, &s)
}
return cfg
}