podman
394 строки · 9.1 Кб
1// Copyright 2015 go-swagger maintainers
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package swag
16
17import (
18"reflect"
19"strings"
20"unicode"
21)
22
23// commonInitialisms are common acronyms that are kept as whole uppercased words.
24var commonInitialisms *indexOfInitialisms
25
26// initialisms is a slice of sorted initialisms
27var initialisms []string
28
29var isInitialism func(string) bool
30
31// GoNamePrefixFunc sets an optional rule to prefix go names
32// which do not start with a letter.
33//
34// e.g. to help convert "123" into "{prefix}123"
35//
36// The default is to prefix with "X"
37var GoNamePrefixFunc func(string) string
38
39func init() {
40// Taken from https://github.com/golang/lint/blob/3390df4df2787994aea98de825b964ac7944b817/lint.go#L732-L769
41var configuredInitialisms = map[string]bool{
42"ACL": true,
43"API": true,
44"ASCII": true,
45"CPU": true,
46"CSS": true,
47"DNS": true,
48"EOF": true,
49"GUID": true,
50"HTML": true,
51"HTTPS": true,
52"HTTP": true,
53"ID": true,
54"IP": true,
55"IPv4": true,
56"IPv6": true,
57"JSON": true,
58"LHS": true,
59"OAI": true,
60"QPS": true,
61"RAM": true,
62"RHS": true,
63"RPC": true,
64"SLA": true,
65"SMTP": true,
66"SQL": true,
67"SSH": true,
68"TCP": true,
69"TLS": true,
70"TTL": true,
71"UDP": true,
72"UI": true,
73"UID": true,
74"UUID": true,
75"URI": true,
76"URL": true,
77"UTF8": true,
78"VM": true,
79"XML": true,
80"XMPP": true,
81"XSRF": true,
82"XSS": true,
83}
84
85// a thread-safe index of initialisms
86commonInitialisms = newIndexOfInitialisms().load(configuredInitialisms)
87initialisms = commonInitialisms.sorted()
88
89// a test function
90isInitialism = commonInitialisms.isInitialism
91}
92
93const (
94// collectionFormatComma = "csv"
95collectionFormatSpace = "ssv"
96collectionFormatTab = "tsv"
97collectionFormatPipe = "pipes"
98collectionFormatMulti = "multi"
99)
100
101// JoinByFormat joins a string array by a known format (e.g. swagger's collectionFormat attribute):
102//
103// ssv: space separated value
104// tsv: tab separated value
105// pipes: pipe (|) separated value
106// csv: comma separated value (default)
107func JoinByFormat(data []string, format string) []string {
108if len(data) == 0 {
109return data
110}
111var sep string
112switch format {
113case collectionFormatSpace:
114sep = " "
115case collectionFormatTab:
116sep = "\t"
117case collectionFormatPipe:
118sep = "|"
119case collectionFormatMulti:
120return data
121default:
122sep = ","
123}
124return []string{strings.Join(data, sep)}
125}
126
127// SplitByFormat splits a string by a known format:
128//
129// ssv: space separated value
130// tsv: tab separated value
131// pipes: pipe (|) separated value
132// csv: comma separated value (default)
133func SplitByFormat(data, format string) []string {
134if data == "" {
135return nil
136}
137var sep string
138switch format {
139case collectionFormatSpace:
140sep = " "
141case collectionFormatTab:
142sep = "\t"
143case collectionFormatPipe:
144sep = "|"
145case collectionFormatMulti:
146return nil
147default:
148sep = ","
149}
150var result []string
151for _, s := range strings.Split(data, sep) {
152if ts := strings.TrimSpace(s); ts != "" {
153result = append(result, ts)
154}
155}
156return result
157}
158
159type byInitialism []string
160
161func (s byInitialism) Len() int {
162return len(s)
163}
164func (s byInitialism) Swap(i, j int) {
165s[i], s[j] = s[j], s[i]
166}
167func (s byInitialism) Less(i, j int) bool {
168if len(s[i]) != len(s[j]) {
169return len(s[i]) < len(s[j])
170}
171
172return strings.Compare(s[i], s[j]) > 0
173}
174
175// Removes leading whitespaces
176func trim(str string) string {
177return strings.Trim(str, " ")
178}
179
180// Shortcut to strings.ToUpper()
181func upper(str string) string {
182return strings.ToUpper(trim(str))
183}
184
185// Shortcut to strings.ToLower()
186func lower(str string) string {
187return strings.ToLower(trim(str))
188}
189
190// Camelize an uppercased word
191func Camelize(word string) (camelized string) {
192for pos, ru := range []rune(word) {
193if pos > 0 {
194camelized += string(unicode.ToLower(ru))
195} else {
196camelized += string(unicode.ToUpper(ru))
197}
198}
199return
200}
201
202// ToFileName lowercases and underscores a go type name
203func ToFileName(name string) string {
204in := split(name)
205out := make([]string, 0, len(in))
206
207for _, w := range in {
208out = append(out, lower(w))
209}
210
211return strings.Join(out, "_")
212}
213
214// ToCommandName lowercases and underscores a go type name
215func ToCommandName(name string) string {
216in := split(name)
217out := make([]string, 0, len(in))
218
219for _, w := range in {
220out = append(out, lower(w))
221}
222return strings.Join(out, "-")
223}
224
225// ToHumanNameLower represents a code name as a human series of words
226func ToHumanNameLower(name string) string {
227in := newSplitter(withPostSplitInitialismCheck).split(name)
228out := make([]string, 0, len(in))
229
230for _, w := range in {
231if !w.IsInitialism() {
232out = append(out, lower(w.GetOriginal()))
233} else {
234out = append(out, w.GetOriginal())
235}
236}
237
238return strings.Join(out, " ")
239}
240
241// ToHumanNameTitle represents a code name as a human series of words with the first letters titleized
242func ToHumanNameTitle(name string) string {
243in := newSplitter(withPostSplitInitialismCheck).split(name)
244
245out := make([]string, 0, len(in))
246for _, w := range in {
247original := w.GetOriginal()
248if !w.IsInitialism() {
249out = append(out, Camelize(original))
250} else {
251out = append(out, original)
252}
253}
254return strings.Join(out, " ")
255}
256
257// ToJSONName camelcases a name which can be underscored or pascal cased
258func ToJSONName(name string) string {
259in := split(name)
260out := make([]string, 0, len(in))
261
262for i, w := range in {
263if i == 0 {
264out = append(out, lower(w))
265continue
266}
267out = append(out, Camelize(w))
268}
269return strings.Join(out, "")
270}
271
272// ToVarName camelcases a name which can be underscored or pascal cased
273func ToVarName(name string) string {
274res := ToGoName(name)
275if isInitialism(res) {
276return lower(res)
277}
278if len(res) <= 1 {
279return lower(res)
280}
281return lower(res[:1]) + res[1:]
282}
283
284// ToGoName translates a swagger name which can be underscored or camel cased to a name that golint likes
285func ToGoName(name string) string {
286lexems := newSplitter(withPostSplitInitialismCheck).split(name)
287
288result := ""
289for _, lexem := range lexems {
290goName := lexem.GetUnsafeGoName()
291
292// to support old behavior
293if lexem.IsInitialism() {
294goName = upper(goName)
295}
296result += goName
297}
298
299if len(result) > 0 {
300// Only prefix with X when the first character isn't an ascii letter
301first := []rune(result)[0]
302if !unicode.IsLetter(first) || (first > unicode.MaxASCII && !unicode.IsUpper(first)) {
303if GoNamePrefixFunc == nil {
304return "X" + result
305}
306result = GoNamePrefixFunc(name) + result
307}
308first = []rune(result)[0]
309if unicode.IsLetter(first) && !unicode.IsUpper(first) {
310result = string(append([]rune{unicode.ToUpper(first)}, []rune(result)[1:]...))
311}
312}
313
314return result
315}
316
317// ContainsStrings searches a slice of strings for a case-sensitive match
318func ContainsStrings(coll []string, item string) bool {
319for _, a := range coll {
320if a == item {
321return true
322}
323}
324return false
325}
326
327// ContainsStringsCI searches a slice of strings for a case-insensitive match
328func ContainsStringsCI(coll []string, item string) bool {
329for _, a := range coll {
330if strings.EqualFold(a, item) {
331return true
332}
333}
334return false
335}
336
337type zeroable interface {
338IsZero() bool
339}
340
341// IsZero returns true when the value passed into the function is a zero value.
342// This allows for safer checking of interface values.
343func IsZero(data interface{}) bool {
344v := reflect.ValueOf(data)
345// check for nil data
346switch v.Kind() {
347case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
348if v.IsNil() {
349return true
350}
351}
352
353// check for things that have an IsZero method instead
354if vv, ok := data.(zeroable); ok {
355return vv.IsZero()
356}
357
358// continue with slightly more complex reflection
359switch v.Kind() {
360case reflect.String:
361return v.Len() == 0
362case reflect.Bool:
363return !v.Bool()
364case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
365return v.Int() == 0
366case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
367return v.Uint() == 0
368case reflect.Float32, reflect.Float64:
369return v.Float() == 0
370case reflect.Struct, reflect.Array:
371return reflect.DeepEqual(data, reflect.Zero(v.Type()).Interface())
372case reflect.Invalid:
373return true
374default:
375return false
376}
377}
378
379// AddInitialisms add additional initialisms
380func AddInitialisms(words ...string) {
381for _, word := range words {
382// commonInitialisms[upper(word)] = true
383commonInitialisms.add(upper(word))
384}
385// sort again
386initialisms = commonInitialisms.sorted()
387}
388
389// CommandLineOptionsGroup represents a group of user-defined command line options
390type CommandLineOptionsGroup struct {
391ShortDescription string
392LongDescription string
393Options interface{}
394}
395