1package ini
2
3import (
4 "strings"
5)
6
7func tokenize(lines []string) ([]lineToken, error) {
8 tokens := make([]lineToken, 0, len(lines))
9 for _, line := range lines {
10 if len(strings.TrimSpace(line)) == 0 || isLineComment(line) {
11 continue
12 }
13
14 if tok := asProfile(line); tok != nil {
15 tokens = append(tokens, tok)
16 } else if tok := asProperty(line); tok != nil {
17 tokens = append(tokens, tok)
18 } else if tok := asSubProperty(line); tok != nil {
19 tokens = append(tokens, tok)
20 } else if tok := asContinuation(line); tok != nil {
21 tokens = append(tokens, tok)
22 } // unrecognized tokens are effectively ignored
23 }
24 return tokens, nil
25}
26
27func isLineComment(line string) bool {
28 trimmed := strings.TrimLeft(line, " \t")
29 return strings.HasPrefix(trimmed, "#") || strings.HasPrefix(trimmed, ";")
30}
31
32func asProfile(line string) *lineTokenProfile { // " [ type name ] ; comment"
33 trimmed := strings.TrimSpace(trimProfileComment(line)) // "[ type name ]"
34 if !isBracketed(trimmed) {
35 return nil
36 }
37 trimmed = trimmed[1 : len(trimmed)-1] // " type name " (or just " name ")
38 trimmed = strings.TrimSpace(trimmed) // "type name" / "name"
39 typ, name := splitProfile(trimmed)
40 return &lineTokenProfile{
41 Type: typ,
42 Name: name,
43 }
44}
45
46func asProperty(line string) *lineTokenProperty {
47 if isLineSpace(rune(line[0])) {
48 return nil
49 }
50
51 trimmed := trimPropertyComment(line)
52 trimmed = strings.TrimRight(trimmed, " \t")
53 k, v, ok := splitProperty(trimmed)
54 if !ok {
55 return nil
56 }
57
58 return &lineTokenProperty{
59 Key: strings.ToLower(k), // LEGACY: normalize key case
60 Value: legacyStrconv(v), // LEGACY: see func docs
61 }
62}
63
64func asSubProperty(line string) *lineTokenSubProperty {
65 if !isLineSpace(rune(line[0])) {
66 return nil
67 }
68
69 // comments on sub-properties are included in the value
70 trimmed := strings.TrimLeft(line, " \t")
71 k, v, ok := splitProperty(trimmed)
72 if !ok {
73 return nil
74 }
75
76 return &lineTokenSubProperty{ // same LEGACY constraints as in normal property
77 Key: strings.ToLower(k),
78 Value: legacyStrconv(v),
79 }
80}
81
82func asContinuation(line string) *lineTokenContinuation {
83 if !isLineSpace(rune(line[0])) {
84 return nil
85 }
86
87 // includes comments like sub-properties
88 trimmed := strings.TrimLeft(line, " \t")
89 return &lineTokenContinuation{
90 Value: trimmed,
91 }
92}