|
- // Copyright 2015 go-swagger maintainers
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
-
- package swag
-
- import (
- "reflect"
- "strings"
- "unicode"
- )
-
- // commonInitialisms are common acronyms that are kept as whole uppercased words.
- var commonInitialisms *indexOfInitialisms
-
- // initialisms is a slice of sorted initialisms
- var initialisms []string
-
- var isInitialism func(string) bool
-
- // GoNamePrefixFunc sets an optional rule to prefix go names
- // which do not start with a letter.
- //
- // e.g. to help converting "123" into "{prefix}123"
- //
- // The default is to prefix with "X"
- var GoNamePrefixFunc func(string) string
-
- func init() {
- // Taken from https://github.com/golang/lint/blob/3390df4df2787994aea98de825b964ac7944b817/lint.go#L732-L769
- var configuredInitialisms = map[string]bool{
- "ACL": true,
- "API": true,
- "ASCII": true,
- "CPU": true,
- "CSS": true,
- "DNS": true,
- "EOF": true,
- "GUID": true,
- "HTML": true,
- "HTTPS": true,
- "HTTP": true,
- "ID": true,
- "IP": true,
- "IPv4": true,
- "IPv6": true,
- "JSON": true,
- "LHS": true,
- "OAI": true,
- "QPS": true,
- "RAM": true,
- "RHS": true,
- "RPC": true,
- "SLA": true,
- "SMTP": true,
- "SQL": true,
- "SSH": true,
- "TCP": true,
- "TLS": true,
- "TTL": true,
- "UDP": true,
- "UI": true,
- "UID": true,
- "UUID": true,
- "URI": true,
- "URL": true,
- "UTF8": true,
- "VM": true,
- "XML": true,
- "XMPP": true,
- "XSRF": true,
- "XSS": true,
- }
-
- // a thread-safe index of initialisms
- commonInitialisms = newIndexOfInitialisms().load(configuredInitialisms)
- initialisms = commonInitialisms.sorted()
-
- // a test function
- isInitialism = commonInitialisms.isInitialism
- }
-
- const (
- //collectionFormatComma = "csv"
- collectionFormatSpace = "ssv"
- collectionFormatTab = "tsv"
- collectionFormatPipe = "pipes"
- collectionFormatMulti = "multi"
- )
-
- // JoinByFormat joins a string array by a known format (e.g. swagger's collectionFormat attribute):
- // ssv: space separated value
- // tsv: tab separated value
- // pipes: pipe (|) separated value
- // csv: comma separated value (default)
- func JoinByFormat(data []string, format string) []string {
- if len(data) == 0 {
- return data
- }
- var sep string
- switch format {
- case collectionFormatSpace:
- sep = " "
- case collectionFormatTab:
- sep = "\t"
- case collectionFormatPipe:
- sep = "|"
- case collectionFormatMulti:
- return data
- default:
- sep = ","
- }
- return []string{strings.Join(data, sep)}
- }
-
- // SplitByFormat splits a string by a known format:
- // ssv: space separated value
- // tsv: tab separated value
- // pipes: pipe (|) separated value
- // csv: comma separated value (default)
- //
- func SplitByFormat(data, format string) []string {
- if data == "" {
- return nil
- }
- var sep string
- switch format {
- case collectionFormatSpace:
- sep = " "
- case collectionFormatTab:
- sep = "\t"
- case collectionFormatPipe:
- sep = "|"
- case collectionFormatMulti:
- return nil
- default:
- sep = ","
- }
- var result []string
- for _, s := range strings.Split(data, sep) {
- if ts := strings.TrimSpace(s); ts != "" {
- result = append(result, ts)
- }
- }
- return result
- }
-
- type byInitialism []string
-
- func (s byInitialism) Len() int {
- return len(s)
- }
- func (s byInitialism) Swap(i, j int) {
- s[i], s[j] = s[j], s[i]
- }
- func (s byInitialism) Less(i, j int) bool {
- if len(s[i]) != len(s[j]) {
- return len(s[i]) < len(s[j])
- }
-
- return strings.Compare(s[i], s[j]) > 0
- }
-
- // Removes leading whitespaces
- func trim(str string) string {
- return strings.Trim(str, " ")
- }
-
- // Shortcut to strings.ToUpper()
- func upper(str string) string {
- return strings.ToUpper(trim(str))
- }
-
- // Shortcut to strings.ToLower()
- func lower(str string) string {
- return strings.ToLower(trim(str))
- }
-
- // Camelize an uppercased word
- func Camelize(word string) (camelized string) {
- for pos, ru := range []rune(word) {
- if pos > 0 {
- camelized += string(unicode.ToLower(ru))
- } else {
- camelized += string(unicode.ToUpper(ru))
- }
- }
- return
- }
-
- // ToFileName lowercases and underscores a go type name
- func ToFileName(name string) string {
- in := split(name)
- out := make([]string, 0, len(in))
-
- for _, w := range in {
- out = append(out, lower(w))
- }
-
- return strings.Join(out, "_")
- }
-
- // ToCommandName lowercases and underscores a go type name
- func ToCommandName(name string) string {
- in := split(name)
- out := make([]string, 0, len(in))
-
- for _, w := range in {
- out = append(out, lower(w))
- }
- return strings.Join(out, "-")
- }
-
- // ToHumanNameLower represents a code name as a human series of words
- func ToHumanNameLower(name string) string {
- in := newSplitter(withPostSplitInitialismCheck).split(name)
- out := make([]string, 0, len(in))
-
- for _, w := range in {
- if !w.IsInitialism() {
- out = append(out, lower(w.GetOriginal()))
- } else {
- out = append(out, w.GetOriginal())
- }
- }
-
- return strings.Join(out, " ")
- }
-
- // ToHumanNameTitle represents a code name as a human series of words with the first letters titleized
- func ToHumanNameTitle(name string) string {
- in := newSplitter(withPostSplitInitialismCheck).split(name)
-
- out := make([]string, 0, len(in))
- for _, w := range in {
- original := w.GetOriginal()
- if !w.IsInitialism() {
- out = append(out, Camelize(original))
- } else {
- out = append(out, original)
- }
- }
- return strings.Join(out, " ")
- }
-
- // ToJSONName camelcases a name which can be underscored or pascal cased
- func ToJSONName(name string) string {
- in := split(name)
- out := make([]string, 0, len(in))
-
- for i, w := range in {
- if i == 0 {
- out = append(out, lower(w))
- continue
- }
- out = append(out, Camelize(w))
- }
- return strings.Join(out, "")
- }
-
- // ToVarName camelcases a name which can be underscored or pascal cased
- func ToVarName(name string) string {
- res := ToGoName(name)
- if isInitialism(res) {
- return lower(res)
- }
- if len(res) <= 1 {
- return lower(res)
- }
- return lower(res[:1]) + res[1:]
- }
-
- // ToGoName translates a swagger name which can be underscored or camel cased to a name that golint likes
- func ToGoName(name string) string {
- lexems := newSplitter(withPostSplitInitialismCheck).split(name)
-
- result := ""
- for _, lexem := range lexems {
- goName := lexem.GetUnsafeGoName()
-
- // to support old behavior
- if lexem.IsInitialism() {
- goName = upper(goName)
- }
- result += goName
- }
-
- if len(result) > 0 {
- // Only prefix with X when the first character isn't an ascii letter
- first := []rune(result)[0]
- if !unicode.IsLetter(first) || (first > unicode.MaxASCII && !unicode.IsUpper(first)) {
- if GoNamePrefixFunc == nil {
- return "X" + result
- }
- result = GoNamePrefixFunc(name) + result
- }
- first = []rune(result)[0]
- if unicode.IsLetter(first) && !unicode.IsUpper(first) {
- result = string(append([]rune{unicode.ToUpper(first)}, []rune(result)[1:]...))
- }
- }
-
- return result
- }
-
- // ContainsStrings searches a slice of strings for a case-sensitive match
- func ContainsStrings(coll []string, item string) bool {
- for _, a := range coll {
- if a == item {
- return true
- }
- }
- return false
- }
-
- // ContainsStringsCI searches a slice of strings for a case-insensitive match
- func ContainsStringsCI(coll []string, item string) bool {
- for _, a := range coll {
- if strings.EqualFold(a, item) {
- return true
- }
- }
- return false
- }
-
- type zeroable interface {
- IsZero() bool
- }
-
- // IsZero returns true when the value passed into the function is a zero value.
- // This allows for safer checking of interface values.
- func IsZero(data interface{}) bool {
- // check for things that have an IsZero method instead
- if vv, ok := data.(zeroable); ok {
- return vv.IsZero()
- }
- // continue with slightly more complex reflection
- v := reflect.ValueOf(data)
- switch v.Kind() {
- case reflect.String:
- return v.Len() == 0
- case reflect.Bool:
- return !v.Bool()
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- return v.Int() == 0
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- return v.Uint() == 0
- case reflect.Float32, reflect.Float64:
- return v.Float() == 0
- case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
- return v.IsNil()
- case reflect.Struct, reflect.Array:
- return reflect.DeepEqual(data, reflect.Zero(v.Type()).Interface())
- case reflect.Invalid:
- return true
- }
- return false
- }
-
- // AddInitialisms add additional initialisms
- func AddInitialisms(words ...string) {
- for _, word := range words {
- //commonInitialisms[upper(word)] = true
- commonInitialisms.add(upper(word))
- }
- // sort again
- initialisms = commonInitialisms.sorted()
- }
-
- // CommandLineOptionsGroup represents a group of user-defined command line options
- type CommandLineOptionsGroup struct {
- ShortDescription string
- LongDescription string
- Options interface{}
- }
|