diff --git a/camel.go b/camel.go index cd5a260..e433f87 100644 --- a/camel.go +++ b/camel.go @@ -43,8 +43,8 @@ func toCamelInitCase(s string, initCase bool) string { n.Grow(len(s)) capNext := initCase for i, v := range []byte(s) { - vIsCap := v >= 'A' && v <= 'Z' - vIsLow := v >= 'a' && v <= 'z' + vIsCap := capitalLetters.Contains(v) + vIsLow := smallLetters.Contains(v) if capNext { if vIsLow { v += 'A' @@ -59,11 +59,11 @@ func toCamelInitCase(s string, initCase bool) string { if vIsCap || vIsLow { n.WriteByte(v) capNext = false - } else if vIsNum := v >= '0' && v <= '9'; vIsNum { + } else if vIsNum := numbers.Contains(v); vIsNum { n.WriteByte(v) capNext = true } else { - capNext = v == '_' || v == ' ' || v == '-' || v == '.' + capNext = separators.Contains(v) } } return n.String() diff --git a/chars.go b/chars.go new file mode 100644 index 0000000..a4b5214 --- /dev/null +++ b/chars.go @@ -0,0 +1,33 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ian Coleman + * Copyright (c) 2018 Ma_124, + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, Subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or Substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package strcase + +import asciiset "github.com/elliotwutingfeng/asciiset" + +var numbers, _ = asciiset.MakeASCIISet("0123456789") +var smallLetters, _ = asciiset.MakeASCIISet("abcdefghijklmnopqrstuvwxyz") +var capitalLetters, _ = asciiset.MakeASCIISet("ABCDEFGHIJKLMNOPQRSTUVWXYZ") +var separators, _ = asciiset.MakeASCIISet(" _-.") diff --git a/go.mod b/go.mod index a6b5cb6..ae26dd3 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module github.com/iancoleman/strcase go 1.16 + +require github.com/elliotwutingfeng/asciiset v0.0.0-20230602005253-7f88bc28b13f diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..d1d39ee --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/elliotwutingfeng/asciiset v0.0.0-20230602005253-7f88bc28b13f h1:2zrq6AHwG5HdTmNunOU3tRNPQ0F+R9W8mIxgSJzGwkE= +github.com/elliotwutingfeng/asciiset v0.0.0-20230602005253-7f88bc28b13f/go.mod h1:GLo/8fDswSAniFG+BFIaiSPcK610jyzgEhWYPQwuQdw= diff --git a/snake.go b/snake.go index df018bc..1b2582b 100644 --- a/snake.go +++ b/snake.go @@ -68,8 +68,8 @@ func ToScreamingDelimited(s string, delimiter uint8, ignore string, screaming bo n := strings.Builder{} n.Grow(len(s) + 2) // nominal 2 bytes of extra space for inserted delimiters for i, v := range []byte(s) { - vIsCap := v >= 'A' && v <= 'Z' - vIsLow := v >= 'a' && v <= 'z' + vIsCap := capitalLetters.Contains(v) + vIsLow := smallLetters.Contains(v) if vIsLow && screaming { v += 'A' v -= 'a' @@ -81,16 +81,16 @@ func ToScreamingDelimited(s string, delimiter uint8, ignore string, screaming bo // treat acronyms as words, eg for JSONData -> JSON is a whole word if i+1 < len(s) { next := s[i+1] - vIsNum := v >= '0' && v <= '9' - nextIsCap := next >= 'A' && next <= 'Z' - nextIsLow := next >= 'a' && next <= 'z' - nextIsNum := next >= '0' && next <= '9' + vIsNum := numbers.Contains(v) + nextIsCap := capitalLetters.Contains(next) + nextIsLow := smallLetters.Contains(next) + nextIsNum := numbers.Contains(next) // add underscore if next letter case type is changed if (vIsCap && (nextIsLow || nextIsNum)) || (vIsLow && (nextIsCap || nextIsNum)) || (vIsNum && (nextIsCap || nextIsLow)) { - prevIgnore := ignore != "" && i > 0 && strings.ContainsAny(string(s[i-1]), ignore) + prevIgnore := ignore != "" && i > 0 && strings.IndexByte(ignore, s[i-1]) != -1 if !prevIgnore { if vIsCap && nextIsLow { - if prevIsCap := i > 0 && s[i-1] >= 'A' && s[i-1] <= 'Z'; prevIsCap { + if prevIsCap := i > 0 && capitalLetters.Contains(s[i-1]); prevIsCap { n.WriteByte(delimiter) } } @@ -103,7 +103,7 @@ func ToScreamingDelimited(s string, delimiter uint8, ignore string, screaming bo } } - if (v == ' ' || v == '_' || v == '-' || v == '.') && !strings.ContainsAny(string(v), ignore) { + if separators.Contains(v) && strings.IndexByte(ignore, v) == -1 { // replace space/underscore/hyphen/dot with delimiter n.WriteByte(delimiter) } else {