1package ini
 2
 3import (
 4	"strings"
 5)
 6
 7func trimProfileComment(s string) string {
 8	r, _, _ := strings.Cut(s, "#")
 9	r, _, _ = strings.Cut(r, ";")
10	return r
11}
12
13func trimPropertyComment(s string) string {
14	r, _, _ := strings.Cut(s, " #")
15	r, _, _ = strings.Cut(r, " ;")
16	r, _, _ = strings.Cut(r, "\t#")
17	r, _, _ = strings.Cut(r, "\t;")
18	return r
19}
20
21// assumes no surrounding comment
22func splitProperty(s string) (string, string, bool) {
23	equalsi := strings.Index(s, "=")
24	coloni := strings.Index(s, ":") // LEGACY: also supported for property assignment
25	sep := "="
26	if equalsi == -1 || coloni != -1 && coloni < equalsi {
27		sep = ":"
28	}
29
30	k, v, ok := strings.Cut(s, sep)
31	if !ok {
32		return "", "", false
33	}
34	return strings.TrimSpace(k), strings.TrimSpace(v), true
35}
36
37// assumes no surrounding comment, whitespace, or profile brackets
38func splitProfile(s string) (string, string) {
39	var first int
40	for i, r := range s {
41		if isLineSpace(r) {
42			if first == 0 {
43				first = i
44			}
45		} else {
46			if first != 0 {
47				return s[:first], s[i:]
48			}
49		}
50	}
51	if first == 0 {
52		return "", s // type component is effectively blank
53	}
54	return "", ""
55}
56
57func isLineSpace(r rune) bool {
58	return r == ' ' || r == '\t'
59}
60
61func unquote(s string) string {
62	if isSingleQuoted(s) || isDoubleQuoted(s) {
63		return s[1 : len(s)-1]
64	}
65	return s
66}
67
68// applies various legacy conversions to property values:
69//   - remote wrapping single/doublequotes
70func legacyStrconv(s string) string {
71	s = unquote(s)
72	return s
73}
74
75func isSingleQuoted(s string) bool {
76	return hasAffixes(s, "'", "'")
77}
78
79func isDoubleQuoted(s string) bool {
80	return hasAffixes(s, `"`, `"`)
81}
82
83func isBracketed(s string) bool {
84	return hasAffixes(s, "[", "]")
85}
86
87func hasAffixes(s, left, right string) bool {
88	return strings.HasPrefix(s, left) && strings.HasSuffix(s, right)
89}