forked from goadesign/gorma
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathident.go
156 lines (137 loc) · 3.39 KB
/
ident.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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package gorma
import (
"encoding"
"strings"
"unicode"
"unicode/utf8"
)
// Ident represents the string and it's parts
type Ident struct {
Original string
Parts []string
}
// String implements fmt.Stringer and returns the original string
func (i Ident) String() string {
return i.Original
}
// New creates a new Ident from the string
func New(s string) Ident {
i := Ident{
Original: s,
Parts: toParts(s),
}
return i
}
func toParts(s string) []string {
parts := []string{}
s = strings.TrimSpace(s)
if len(s) == 0 {
return parts
}
if _, ok := baseAcronyms[strings.ToUpper(s)]; ok {
return []string{strings.ToUpper(s)}
}
var prev rune
var x strings.Builder
x.Grow(len(s))
for _, c := range s {
// fmt.Println("### cs ->", cs)
// fmt.Println("### unicode.IsControl(c) ->", unicode.IsControl(c))
// fmt.Println("### unicode.IsDigit(c) ->", unicode.IsDigit(c))
// fmt.Println("### unicode.IsGraphic(c) ->", unicode.IsGraphic(c))
// fmt.Println("### unicode.IsLetter(c) ->", unicode.IsLetter(c))
// fmt.Println("### unicode.IsLower(c) ->", unicode.IsLower(c))
// fmt.Println("### unicode.IsMark(c) ->", unicode.IsMark(c))
// fmt.Println("### unicode.IsPrint(c) ->", unicode.IsPrint(c))
// fmt.Println("### unicode.IsPunct(c) ->", unicode.IsPunct(c))
// fmt.Println("### unicode.IsSpace(c) ->", unicode.IsSpace(c))
// fmt.Println("### unicode.IsTitle(c) ->", unicode.IsTitle(c))
// fmt.Println("### unicode.IsUpper(c) ->", unicode.IsUpper(c))
if !utf8.ValidRune(c) {
continue
}
if isSpace(c) {
parts = xappend(parts, x.String())
x.Reset()
x.WriteRune(c)
prev = c
continue
}
if unicode.IsUpper(c) && !unicode.IsUpper(prev) {
parts = xappend(parts, x.String())
x.Reset()
x.WriteRune(c)
prev = c
continue
}
if unicode.IsUpper(c) && baseAcronyms[strings.ToUpper(x.String())] {
parts = xappend(parts, x.String())
x.Reset()
x.WriteRune(c)
prev = c
continue
}
if unicode.IsLetter(c) || unicode.IsDigit(c) || unicode.IsPunct(c) || c == '`' {
prev = c
x.WriteRune(c)
continue
}
parts = xappend(parts, x.String())
x.Reset()
prev = c
}
parts = xappend(parts, x.String())
return parts
}
var _ encoding.TextUnmarshaler = &Ident{}
var _ encoding.TextMarshaler = &Ident{}
// LastPart returns the last part/word of the original string
func (i *Ident) LastPart() string {
if len(i.Parts) == 0 {
return ""
}
return i.Parts[len(i.Parts)-1]
}
// ReplaceSuffix creates a new Ident with the original suffix replaced by new
func (i Ident) ReplaceSuffix(orig, new string) Ident {
return New(strings.TrimSuffix(i.Original, orig) + new)
}
//UnmarshalText unmarshalls byte array into the Ident
func (i *Ident) UnmarshalText(data []byte) error {
(*i) = New(string(data))
return nil
}
//MarshalText marshals Ident into byte array
func (i Ident) MarshalText() ([]byte, error) {
return []byte(i.Original), nil
}
var spaces = []rune{'_', ' ', ':', '-', '/'}
func isSpace(c rune) bool {
for _, r := range spaces {
if r == c {
return true
}
}
return unicode.IsSpace(c)
}
func xappend(a []string, ss ...string) []string {
for _, s := range ss {
s = strings.TrimSpace(s)
for _, x := range spaces {
s = strings.Trim(s, string(x))
}
if _, ok := baseAcronyms[strings.ToUpper(s)]; ok {
s = strings.ToUpper(s)
}
if s != "" {
a = append(a, s)
}
}
return a
}
func abs(x int) int {
if x < 0 {
return -x
}
return x
}