forked from piranha/gostatic
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathheader.go
99 lines (85 loc) · 1.89 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
// (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
line = strings.TrimSpace(line)
if len(line) == 0 {
return
}
// Split line in actual name and value
bits := TrimSplitN(line, ":", 2)
key := strings.ToUpper(bits[0][0:1]) + bits[0][1:]
cfg.SetValue(key, bits[1], 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[Capitalize(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
}