summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/huandu/xstrings
diff options
context:
space:
mode:
authortechknowlogick <techknowlogick@gitea.io>2022-01-14 18:16:05 -0500
committerGitHub <noreply@github.com>2022-01-14 18:16:05 -0500
commit84145e45c50130922fae9055535ab5ea0378e1d4 (patch)
treefce077a5ae462840bb876ace79aca42abab29ed7 /vendor/github.com/huandu/xstrings
parent2b16ca7c773de278ba01f122dc6f9f43d7534c52 (diff)
downloadgitea-84145e45c50130922fae9055535ab5ea0378e1d4.tar.gz
gitea-84145e45c50130922fae9055535ab5ea0378e1d4.zip
Remove golang vendored directory (#18277)
* rm go vendor * fix drone yaml * add to gitignore
Diffstat (limited to 'vendor/github.com/huandu/xstrings')
-rw-r--r--vendor/github.com/huandu/xstrings/.gitignore24
-rw-r--r--vendor/github.com/huandu/xstrings/.travis.yml7
-rw-r--r--vendor/github.com/huandu/xstrings/CONTRIBUTING.md23
-rw-r--r--vendor/github.com/huandu/xstrings/LICENSE22
-rw-r--r--vendor/github.com/huandu/xstrings/README.md117
-rw-r--r--vendor/github.com/huandu/xstrings/common.go21
-rw-r--r--vendor/github.com/huandu/xstrings/convert.go590
-rw-r--r--vendor/github.com/huandu/xstrings/count.go120
-rw-r--r--vendor/github.com/huandu/xstrings/doc.go8
-rw-r--r--vendor/github.com/huandu/xstrings/format.go169
-rw-r--r--vendor/github.com/huandu/xstrings/go.mod3
-rw-r--r--vendor/github.com/huandu/xstrings/manipulate.go216
-rw-r--r--vendor/github.com/huandu/xstrings/stringbuilder.go7
-rw-r--r--vendor/github.com/huandu/xstrings/stringbuilder_go110.go9
-rw-r--r--vendor/github.com/huandu/xstrings/translate.go546
15 files changed, 0 insertions, 1882 deletions
diff --git a/vendor/github.com/huandu/xstrings/.gitignore b/vendor/github.com/huandu/xstrings/.gitignore
deleted file mode 100644
index daf913b1b3..0000000000
--- a/vendor/github.com/huandu/xstrings/.gitignore
+++ /dev/null
@@ -1,24 +0,0 @@
-# Compiled Object files, Static and Dynamic libs (Shared Objects)
-*.o
-*.a
-*.so
-
-# Folders
-_obj
-_test
-
-# Architecture specific extensions/prefixes
-*.[568vq]
-[568vq].out
-
-*.cgo1.go
-*.cgo2.c
-_cgo_defun.c
-_cgo_gotypes.go
-_cgo_export.*
-
-_testmain.go
-
-*.exe
-*.test
-*.prof
diff --git a/vendor/github.com/huandu/xstrings/.travis.yml b/vendor/github.com/huandu/xstrings/.travis.yml
deleted file mode 100644
index d6460be411..0000000000
--- a/vendor/github.com/huandu/xstrings/.travis.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-language: go
-install:
- - go get golang.org/x/tools/cmd/cover
- - go get github.com/mattn/goveralls
-script:
- - go test -v -covermode=count -coverprofile=coverage.out
- - 'if [ "$TRAVIS_PULL_REQUEST" = "false" ] && [ ! -z "$COVERALLS_TOKEN" ]; then $HOME/gopath/bin/goveralls -coverprofile=coverage.out -service=travis-ci -repotoken $COVERALLS_TOKEN; fi'
diff --git a/vendor/github.com/huandu/xstrings/CONTRIBUTING.md b/vendor/github.com/huandu/xstrings/CONTRIBUTING.md
deleted file mode 100644
index d7b4b8d584..0000000000
--- a/vendor/github.com/huandu/xstrings/CONTRIBUTING.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# Contributing #
-
-Thanks for your contribution in advance. No matter what you will contribute to this project, pull request or bug report or feature discussion, it's always highly appreciated.
-
-## New API or feature ##
-
-I want to speak more about how to add new functions to this package.
-
-Package `xstring` is a collection of useful string functions which should be implemented in Go. It's a bit subject to say which function should be included and which should not. I set up following rules in order to make it clear and as objective as possible.
-
-* Rule 1: Only string algorithm, which takes string as input, can be included.
-* Rule 2: If a function has been implemented in package `string`, it must not be included.
-* Rule 3: If a function is not language neutral, it must not be included.
-* Rule 4: If a function is a part of standard library in other languages, it can be included.
-* Rule 5: If a function is quite useful in some famous framework or library, it can be included.
-
-New function must be discussed in project issues before submitting any code. If a pull request with new functions is sent without any ref issue, it will be rejected.
-
-## Pull request ##
-
-Pull request is always welcome. Just make sure you have run `go fmt` and all test cases passed before submit.
-
-If the pull request is to add a new API or feature, don't forget to update README.md and add new API in function list.
diff --git a/vendor/github.com/huandu/xstrings/LICENSE b/vendor/github.com/huandu/xstrings/LICENSE
deleted file mode 100644
index 2701772593..0000000000
--- a/vendor/github.com/huandu/xstrings/LICENSE
+++ /dev/null
@@ -1,22 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2015 Huan Du
-
-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.
-
diff --git a/vendor/github.com/huandu/xstrings/README.md b/vendor/github.com/huandu/xstrings/README.md
deleted file mode 100644
index 292bf2f39e..0000000000
--- a/vendor/github.com/huandu/xstrings/README.md
+++ /dev/null
@@ -1,117 +0,0 @@
-# xstrings #
-
-[![Build Status](https://travis-ci.org/huandu/xstrings.svg?branch=master)](https://travis-ci.org/huandu/xstrings)
-[![GoDoc](https://godoc.org/github.com/huandu/xstrings?status.svg)](https://godoc.org/github.com/huandu/xstrings)
-[![Go Report](https://goreportcard.com/badge/github.com/huandu/xstrings)](https://goreportcard.com/report/github.com/huandu/xstrings)
-[![Coverage Status](https://coveralls.io/repos/github/huandu/xstrings/badge.svg?branch=master)](https://coveralls.io/github/huandu/xstrings?branch=master)
-
-Go package [xstrings](https://godoc.org/github.com/huandu/xstrings) is a collection of string functions, which are widely used in other languages but absent in Go package [strings](http://golang.org/pkg/strings).
-
-All functions are well tested and carefully tuned for performance.
-
-## Propose a new function ##
-
-Please review [contributing guideline](CONTRIBUTING.md) and [create new issue](https://github.com/huandu/xstrings/issues) to state why it should be included.
-
-## Install ##
-
-Use `go get` to install this library.
-
- go get github.com/huandu/xstrings
-
-## API document ##
-
-See [GoDoc](https://godoc.org/github.com/huandu/xstrings) for full document.
-
-## Function list ##
-
-Go functions have a unique naming style. One, who has experience in other language but new in Go, may have difficulties to find out right string function to use.
-
-Here is a list of functions in [strings](http://golang.org/pkg/strings) and [xstrings](https://godoc.org/github.com/huandu/xstrings) with enough extra information about how to map these functions to their friends in other languages. Hope this list could be helpful for fresh gophers.
-
-### Package `xstrings` functions ###
-
-*Keep this table sorted by Function in ascending order.*
-
-| Function | Friends | # |
-| -------- | ------- | --- |
-| [Center](https://godoc.org/github.com/huandu/xstrings#Center) | `str.center` in Python; `String#center` in Ruby | [#30](https://github.com/huandu/xstrings/issues/30) |
-| [Count](https://godoc.org/github.com/huandu/xstrings#Count) | `String#count` in Ruby | [#16](https://github.com/huandu/xstrings/issues/16) |
-| [Delete](https://godoc.org/github.com/huandu/xstrings#Delete) | `String#delete` in Ruby | [#17](https://github.com/huandu/xstrings/issues/17) |
-| [ExpandTabs](https://godoc.org/github.com/huandu/xstrings#ExpandTabs) | `str.expandtabs` in Python | [#27](https://github.com/huandu/xstrings/issues/27) |
-| [FirstRuneToLower](https://godoc.org/github.com/huandu/xstrings#FirstRuneToLower) | `lcfirst` in PHP or Perl | [#15](https://github.com/huandu/xstrings/issues/15) |
-| [FirstRuneToUpper](https://godoc.org/github.com/huandu/xstrings#FirstRuneToUpper) | `String#capitalize` in Ruby; `ucfirst` in PHP or Perl | [#15](https://github.com/huandu/xstrings/issues/15) |
-| [Insert](https://godoc.org/github.com/huandu/xstrings#Insert) | `String#insert` in Ruby | [#18](https://github.com/huandu/xstrings/issues/18) |
-| [LastPartition](https://godoc.org/github.com/huandu/xstrings#LastPartition) | `str.rpartition` in Python; `String#rpartition` in Ruby | [#19](https://github.com/huandu/xstrings/issues/19) |
-| [LeftJustify](https://godoc.org/github.com/huandu/xstrings#LeftJustify) | `str.ljust` in Python; `String#ljust` in Ruby | [#28](https://github.com/huandu/xstrings/issues/28) |
-| [Len](https://godoc.org/github.com/huandu/xstrings#Len) | `mb_strlen` in PHP | [#23](https://github.com/huandu/xstrings/issues/23) |
-| [Partition](https://godoc.org/github.com/huandu/xstrings#Partition) | `str.partition` in Python; `String#partition` in Ruby | [#10](https://github.com/huandu/xstrings/issues/10) |
-| [Reverse](https://godoc.org/github.com/huandu/xstrings#Reverse) | `String#reverse` in Ruby; `strrev` in PHP; `reverse` in Perl | [#7](https://github.com/huandu/xstrings/issues/7) |
-| [RightJustify](https://godoc.org/github.com/huandu/xstrings#RightJustify) | `str.rjust` in Python; `String#rjust` in Ruby | [#29](https://github.com/huandu/xstrings/issues/29) |
-| [RuneWidth](https://godoc.org/github.com/huandu/xstrings#RuneWidth) | - | [#27](https://github.com/huandu/xstrings/issues/27) |
-| [Scrub](https://godoc.org/github.com/huandu/xstrings#Scrub) | `String#scrub` in Ruby | [#20](https://github.com/huandu/xstrings/issues/20) |
-| [Shuffle](https://godoc.org/github.com/huandu/xstrings#Shuffle) | `str_shuffle` in PHP | [#13](https://github.com/huandu/xstrings/issues/13) |
-| [ShuffleSource](https://godoc.org/github.com/huandu/xstrings#ShuffleSource) | `str_shuffle` in PHP | [#13](https://github.com/huandu/xstrings/issues/13) |
-| [Slice](https://godoc.org/github.com/huandu/xstrings#Slice) | `mb_substr` in PHP | [#9](https://github.com/huandu/xstrings/issues/9) |
-| [Squeeze](https://godoc.org/github.com/huandu/xstrings#Squeeze) | `String#squeeze` in Ruby | [#11](https://github.com/huandu/xstrings/issues/11) |
-| [Successor](https://godoc.org/github.com/huandu/xstrings#Successor) | `String#succ` or `String#next` in Ruby | [#22](https://github.com/huandu/xstrings/issues/22) |
-| [SwapCase](https://godoc.org/github.com/huandu/xstrings#SwapCase) | `str.swapcase` in Python; `String#swapcase` in Ruby | [#12](https://github.com/huandu/xstrings/issues/12) |
-| [ToCamelCase](https://godoc.org/github.com/huandu/xstrings#ToCamelCase) | `String#camelize` in RoR | [#1](https://github.com/huandu/xstrings/issues/1) |
-| [ToKebab](https://godoc.org/github.com/huandu/xstrings#ToKebabCase) | - | [#41](https://github.com/huandu/xstrings/issues/41) |
-| [ToSnakeCase](https://godoc.org/github.com/huandu/xstrings#ToSnakeCase) | `String#underscore` in RoR | [#1](https://github.com/huandu/xstrings/issues/1) |
-| [Translate](https://godoc.org/github.com/huandu/xstrings#Translate) | `str.translate` in Python; `String#tr` in Ruby; `strtr` in PHP; `tr///` in Perl | [#21](https://github.com/huandu/xstrings/issues/21) |
-| [Width](https://godoc.org/github.com/huandu/xstrings#Width) | `mb_strwidth` in PHP | [#26](https://github.com/huandu/xstrings/issues/26) |
-| [WordCount](https://godoc.org/github.com/huandu/xstrings#WordCount) | `str_word_count` in PHP | [#14](https://github.com/huandu/xstrings/issues/14) |
-| [WordSplit](https://godoc.org/github.com/huandu/xstrings#WordSplit) | - | [#14](https://github.com/huandu/xstrings/issues/14) |
-
-### Package `strings` functions ###
-
-*Keep this table sorted by Function in ascending order.*
-
-| Function | Friends |
-| -------- | ------- |
-| [Contains](http://golang.org/pkg/strings/#Contains) | `String#include?` in Ruby |
-| [ContainsAny](http://golang.org/pkg/strings/#ContainsAny) | - |
-| [ContainsRune](http://golang.org/pkg/strings/#ContainsRune) | - |
-| [Count](http://golang.org/pkg/strings/#Count) | `str.count` in Python; `substr_count` in PHP |
-| [EqualFold](http://golang.org/pkg/strings/#EqualFold) | `stricmp` in PHP; `String#casecmp` in Ruby |
-| [Fields](http://golang.org/pkg/strings/#Fields) | `str.split` in Python; `split` in Perl; `String#split` in Ruby |
-| [FieldsFunc](http://golang.org/pkg/strings/#FieldsFunc) | - |
-| [HasPrefix](http://golang.org/pkg/strings/#HasPrefix) | `str.startswith` in Python; `String#start_with?` in Ruby |
-| [HasSuffix](http://golang.org/pkg/strings/#HasSuffix) | `str.endswith` in Python; `String#end_with?` in Ruby |
-| [Index](http://golang.org/pkg/strings/#Index) | `str.index` in Python; `String#index` in Ruby; `strpos` in PHP; `index` in Perl |
-| [IndexAny](http://golang.org/pkg/strings/#IndexAny) | - |
-| [IndexByte](http://golang.org/pkg/strings/#IndexByte) | - |
-| [IndexFunc](http://golang.org/pkg/strings/#IndexFunc) | - |
-| [IndexRune](http://golang.org/pkg/strings/#IndexRune) | - |
-| [Join](http://golang.org/pkg/strings/#Join) | `str.join` in Python; `Array#join` in Ruby; `implode` in PHP; `join` in Perl |
-| [LastIndex](http://golang.org/pkg/strings/#LastIndex) | `str.rindex` in Python; `String#rindex`; `strrpos` in PHP; `rindex` in Perl |
-| [LastIndexAny](http://golang.org/pkg/strings/#LastIndexAny) | - |
-| [LastIndexFunc](http://golang.org/pkg/strings/#LastIndexFunc) | - |
-| [Map](http://golang.org/pkg/strings/#Map) | `String#each_codepoint` in Ruby |
-| [Repeat](http://golang.org/pkg/strings/#Repeat) | operator `*` in Python and Ruby; `str_repeat` in PHP |
-| [Replace](http://golang.org/pkg/strings/#Replace) | `str.replace` in Python; `String#sub` in Ruby; `str_replace` in PHP |
-| [Split](http://golang.org/pkg/strings/#Split) | `str.split` in Python; `String#split` in Ruby; `explode` in PHP; `split` in Perl |
-| [SplitAfter](http://golang.org/pkg/strings/#SplitAfter) | - |
-| [SplitAfterN](http://golang.org/pkg/strings/#SplitAfterN) | - |
-| [SplitN](http://golang.org/pkg/strings/#SplitN) | `str.split` in Python; `String#split` in Ruby; `explode` in PHP; `split` in Perl |
-| [Title](http://golang.org/pkg/strings/#Title) | `str.title` in Python |
-| [ToLower](http://golang.org/pkg/strings/#ToLower) | `str.lower` in Python; `String#downcase` in Ruby; `strtolower` in PHP; `lc` in Perl |
-| [ToLowerSpecial](http://golang.org/pkg/strings/#ToLowerSpecial) | - |
-| [ToTitle](http://golang.org/pkg/strings/#ToTitle) | - |
-| [ToTitleSpecial](http://golang.org/pkg/strings/#ToTitleSpecial) | - |
-| [ToUpper](http://golang.org/pkg/strings/#ToUpper) | `str.upper` in Python; `String#upcase` in Ruby; `strtoupper` in PHP; `uc` in Perl |
-| [ToUpperSpecial](http://golang.org/pkg/strings/#ToUpperSpecial) | - |
-| [Trim](http://golang.org/pkg/strings/#Trim) | `str.strip` in Python; `String#strip` in Ruby; `trim` in PHP |
-| [TrimFunc](http://golang.org/pkg/strings/#TrimFunc) | - |
-| [TrimLeft](http://golang.org/pkg/strings/#TrimLeft) | `str.lstrip` in Python; `String#lstrip` in Ruby; `ltrim` in PHP |
-| [TrimLeftFunc](http://golang.org/pkg/strings/#TrimLeftFunc) | - |
-| [TrimPrefix](http://golang.org/pkg/strings/#TrimPrefix) | - |
-| [TrimRight](http://golang.org/pkg/strings/#TrimRight) | `str.rstrip` in Python; `String#rstrip` in Ruby; `rtrim` in PHP |
-| [TrimRightFunc](http://golang.org/pkg/strings/#TrimRightFunc) | - |
-| [TrimSpace](http://golang.org/pkg/strings/#TrimSpace) | `str.strip` in Python; `String#strip` in Ruby; `trim` in PHP |
-| [TrimSuffix](http://golang.org/pkg/strings/#TrimSuffix) | `String#chomp` in Ruby; `chomp` in Perl |
-
-## License ##
-
-This library is licensed under MIT license. See LICENSE for details.
diff --git a/vendor/github.com/huandu/xstrings/common.go b/vendor/github.com/huandu/xstrings/common.go
deleted file mode 100644
index f427cc84e2..0000000000
--- a/vendor/github.com/huandu/xstrings/common.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2015 Huan Du. All rights reserved.
-// Licensed under the MIT license that can be found in the LICENSE file.
-
-package xstrings
-
-const bufferMaxInitGrowSize = 2048
-
-// Lazy initialize a buffer.
-func allocBuffer(orig, cur string) *stringBuilder {
- output := &stringBuilder{}
- maxSize := len(orig) * 4
-
- // Avoid to reserve too much memory at once.
- if maxSize > bufferMaxInitGrowSize {
- maxSize = bufferMaxInitGrowSize
- }
-
- output.Grow(maxSize)
- output.WriteString(orig[:len(orig)-len(cur)])
- return output
-}
diff --git a/vendor/github.com/huandu/xstrings/convert.go b/vendor/github.com/huandu/xstrings/convert.go
deleted file mode 100644
index 3d5a34950b..0000000000
--- a/vendor/github.com/huandu/xstrings/convert.go
+++ /dev/null
@@ -1,590 +0,0 @@
-// Copyright 2015 Huan Du. All rights reserved.
-// Licensed under the MIT license that can be found in the LICENSE file.
-
-package xstrings
-
-import (
- "math/rand"
- "unicode"
- "unicode/utf8"
-)
-
-// ToCamelCase is to convert words separated by space, underscore and hyphen to camel case.
-//
-// Some samples.
-// "some_words" => "SomeWords"
-// "http_server" => "HttpServer"
-// "no_https" => "NoHttps"
-// "_complex__case_" => "_Complex_Case_"
-// "some words" => "SomeWords"
-func ToCamelCase(str string) string {
- if len(str) == 0 {
- return ""
- }
-
- buf := &stringBuilder{}
- var r0, r1 rune
- var size int
-
- // leading connector will appear in output.
- for len(str) > 0 {
- r0, size = utf8.DecodeRuneInString(str)
- str = str[size:]
-
- if !isConnector(r0) {
- r0 = unicode.ToUpper(r0)
- break
- }
-
- buf.WriteRune(r0)
- }
-
- if len(str) == 0 {
- // A special case for a string contains only 1 rune.
- if size != 0 {
- buf.WriteRune(r0)
- }
-
- return buf.String()
- }
-
- for len(str) > 0 {
- r1 = r0
- r0, size = utf8.DecodeRuneInString(str)
- str = str[size:]
-
- if isConnector(r0) && isConnector(r1) {
- buf.WriteRune(r1)
- continue
- }
-
- if isConnector(r1) {
- r0 = unicode.ToUpper(r0)
- } else {
- r0 = unicode.ToLower(r0)
- buf.WriteRune(r1)
- }
- }
-
- buf.WriteRune(r0)
- return buf.String()
-}
-
-// ToSnakeCase can convert all upper case characters in a string to
-// snake case format.
-//
-// Some samples.
-// "FirstName" => "first_name"
-// "HTTPServer" => "http_server"
-// "NoHTTPS" => "no_https"
-// "GO_PATH" => "go_path"
-// "GO PATH" => "go_path" // space is converted to underscore.
-// "GO-PATH" => "go_path" // hyphen is converted to underscore.
-// "http2xx" => "http_2xx" // insert an underscore before a number and after an alphabet.
-// "HTTP20xOK" => "http_20x_ok"
-// "Duration2m3s" => "duration_2m3s"
-// "Bld4Floor3rd" => "bld4_floor_3rd"
-func ToSnakeCase(str string) string {
- return camelCaseToLowerCase(str, '_')
-}
-
-// ToKebabCase can convert all upper case characters in a string to
-// kebab case format.
-//
-// Some samples.
-// "FirstName" => "first-name"
-// "HTTPServer" => "http-server"
-// "NoHTTPS" => "no-https"
-// "GO_PATH" => "go-path"
-// "GO PATH" => "go-path" // space is converted to '-'.
-// "GO-PATH" => "go-path" // hyphen is converted to '-'.
-// "http2xx" => "http-2xx" // insert an underscore before a number and after an alphabet.
-// "HTTP20xOK" => "http-20x-ok"
-// "Duration2m3s" => "duration-2m3s"
-// "Bld4Floor3rd" => "bld4-floor-3rd"
-func ToKebabCase(str string) string {
- return camelCaseToLowerCase(str, '-')
-}
-
-func camelCaseToLowerCase(str string, connector rune) string {
- if len(str) == 0 {
- return ""
- }
-
- buf := &stringBuilder{}
- wt, word, remaining := nextWord(str)
-
- for len(remaining) > 0 {
- if wt != connectorWord {
- toLower(buf, wt, word, connector)
- }
-
- prev := wt
- last := word
- wt, word, remaining = nextWord(remaining)
-
- switch prev {
- case numberWord:
- for wt == alphabetWord || wt == numberWord {
- toLower(buf, wt, word, connector)
- wt, word, remaining = nextWord(remaining)
- }
-
- if wt != invalidWord && wt != punctWord {
- buf.WriteRune(connector)
- }
-
- case connectorWord:
- toLower(buf, prev, last, connector)
-
- case punctWord:
- // nothing.
-
- default:
- if wt != numberWord {
- if wt != connectorWord && wt != punctWord {
- buf.WriteRune(connector)
- }
-
- break
- }
-
- if len(remaining) == 0 {
- break
- }
-
- last := word
- wt, word, remaining = nextWord(remaining)
-
- // consider number as a part of previous word.
- // e.g. "Bld4Floor" => "bld4_floor"
- if wt != alphabetWord {
- toLower(buf, numberWord, last, connector)
-
- if wt != connectorWord && wt != punctWord {
- buf.WriteRune(connector)
- }
-
- break
- }
-
- // if there are some lower case letters following a number,
- // add connector before the number.
- // e.g. "HTTP2xx" => "http_2xx"
- buf.WriteRune(connector)
- toLower(buf, numberWord, last, connector)
-
- for wt == alphabetWord || wt == numberWord {
- toLower(buf, wt, word, connector)
- wt, word, remaining = nextWord(remaining)
- }
-
- if wt != invalidWord && wt != connectorWord && wt != punctWord {
- buf.WriteRune(connector)
- }
- }
- }
-
- toLower(buf, wt, word, connector)
- return buf.String()
-}
-
-func isConnector(r rune) bool {
- return r == '-' || r == '_' || unicode.IsSpace(r)
-}
-
-type wordType int
-
-const (
- invalidWord wordType = iota
- numberWord
- upperCaseWord
- alphabetWord
- connectorWord
- punctWord
- otherWord
-)
-
-func nextWord(str string) (wt wordType, word, remaining string) {
- if len(str) == 0 {
- return
- }
-
- var offset int
- remaining = str
- r, size := nextValidRune(remaining, utf8.RuneError)
- offset += size
-
- if r == utf8.RuneError {
- wt = invalidWord
- word = str[:offset]
- remaining = str[offset:]
- return
- }
-
- switch {
- case isConnector(r):
- wt = connectorWord
- remaining = remaining[size:]
-
- for len(remaining) > 0 {
- r, size = nextValidRune(remaining, r)
-
- if !isConnector(r) {
- break
- }
-
- offset += size
- remaining = remaining[size:]
- }
-
- case unicode.IsPunct(r):
- wt = punctWord
- remaining = remaining[size:]
-
- for len(remaining) > 0 {
- r, size = nextValidRune(remaining, r)
-
- if !unicode.IsPunct(r) {
- break
- }
-
- offset += size
- remaining = remaining[size:]
- }
-
- case unicode.IsUpper(r):
- wt = upperCaseWord
- remaining = remaining[size:]
-
- if len(remaining) == 0 {
- break
- }
-
- r, size = nextValidRune(remaining, r)
-
- switch {
- case unicode.IsUpper(r):
- prevSize := size
- offset += size
- remaining = remaining[size:]
-
- for len(remaining) > 0 {
- r, size = nextValidRune(remaining, r)
-
- if !unicode.IsUpper(r) {
- break
- }
-
- prevSize = size
- offset += size
- remaining = remaining[size:]
- }
-
- // it's a bit complex when dealing with a case like "HTTPStatus".
- // it's expected to be splitted into "HTTP" and "Status".
- // Therefore "S" should be in remaining instead of word.
- if len(remaining) > 0 && isAlphabet(r) {
- offset -= prevSize
- remaining = str[offset:]
- }
-
- case isAlphabet(r):
- offset += size
- remaining = remaining[size:]
-
- for len(remaining) > 0 {
- r, size = nextValidRune(remaining, r)
-
- if !isAlphabet(r) || unicode.IsUpper(r) {
- break
- }
-
- offset += size
- remaining = remaining[size:]
- }
- }
-
- case isAlphabet(r):
- wt = alphabetWord
- remaining = remaining[size:]
-
- for len(remaining) > 0 {
- r, size = nextValidRune(remaining, r)
-
- if !isAlphabet(r) || unicode.IsUpper(r) {
- break
- }
-
- offset += size
- remaining = remaining[size:]
- }
-
- case unicode.IsNumber(r):
- wt = numberWord
- remaining = remaining[size:]
-
- for len(remaining) > 0 {
- r, size = nextValidRune(remaining, r)
-
- if !unicode.IsNumber(r) {
- break
- }
-
- offset += size
- remaining = remaining[size:]
- }
-
- default:
- wt = otherWord
- remaining = remaining[size:]
-
- for len(remaining) > 0 {
- r, size = nextValidRune(remaining, r)
-
- if size == 0 || isConnector(r) || isAlphabet(r) || unicode.IsNumber(r) || unicode.IsPunct(r) {
- break
- }
-
- offset += size
- remaining = remaining[size:]
- }
- }
-
- word = str[:offset]
- return
-}
-
-func nextValidRune(str string, prev rune) (r rune, size int) {
- var sz int
-
- for len(str) > 0 {
- r, sz = utf8.DecodeRuneInString(str)
- size += sz
-
- if r != utf8.RuneError {
- return
- }
-
- str = str[sz:]
- }
-
- r = prev
- return
-}
-
-func toLower(buf *stringBuilder, wt wordType, str string, connector rune) {
- buf.Grow(buf.Len() + len(str))
-
- if wt != upperCaseWord && wt != connectorWord {
- buf.WriteString(str)
- return
- }
-
- for len(str) > 0 {
- r, size := utf8.DecodeRuneInString(str)
- str = str[size:]
-
- if isConnector(r) {
- buf.WriteRune(connector)
- } else if unicode.IsUpper(r) {
- buf.WriteRune(unicode.ToLower(r))
- } else {
- buf.WriteRune(r)
- }
- }
-}
-
-// SwapCase will swap characters case from upper to lower or lower to upper.
-func SwapCase(str string) string {
- var r rune
- var size int
-
- buf := &stringBuilder{}
-
- for len(str) > 0 {
- r, size = utf8.DecodeRuneInString(str)
-
- switch {
- case unicode.IsUpper(r):
- buf.WriteRune(unicode.ToLower(r))
-
- case unicode.IsLower(r):
- buf.WriteRune(unicode.ToUpper(r))
-
- default:
- buf.WriteRune(r)
- }
-
- str = str[size:]
- }
-
- return buf.String()
-}
-
-// FirstRuneToUpper converts first rune to upper case if necessary.
-func FirstRuneToUpper(str string) string {
- if str == "" {
- return str
- }
-
- r, size := utf8.DecodeRuneInString(str)
-
- if !unicode.IsLower(r) {
- return str
- }
-
- buf := &stringBuilder{}
- buf.WriteRune(unicode.ToUpper(r))
- buf.WriteString(str[size:])
- return buf.String()
-}
-
-// FirstRuneToLower converts first rune to lower case if necessary.
-func FirstRuneToLower(str string) string {
- if str == "" {
- return str
- }
-
- r, size := utf8.DecodeRuneInString(str)
-
- if !unicode.IsUpper(r) {
- return str
- }
-
- buf := &stringBuilder{}
- buf.WriteRune(unicode.ToLower(r))
- buf.WriteString(str[size:])
- return buf.String()
-}
-
-// Shuffle randomizes runes in a string and returns the result.
-// It uses default random source in `math/rand`.
-func Shuffle(str string) string {
- if str == "" {
- return str
- }
-
- runes := []rune(str)
- index := 0
-
- for i := len(runes) - 1; i > 0; i-- {
- index = rand.Intn(i + 1)
-
- if i != index {
- runes[i], runes[index] = runes[index], runes[i]
- }
- }
-
- return string(runes)
-}
-
-// ShuffleSource randomizes runes in a string with given random source.
-func ShuffleSource(str string, src rand.Source) string {
- if str == "" {
- return str
- }
-
- runes := []rune(str)
- index := 0
- r := rand.New(src)
-
- for i := len(runes) - 1; i > 0; i-- {
- index = r.Intn(i + 1)
-
- if i != index {
- runes[i], runes[index] = runes[index], runes[i]
- }
- }
-
- return string(runes)
-}
-
-// Successor returns the successor to string.
-//
-// If there is one alphanumeric rune is found in string, increase the rune by 1.
-// If increment generates a "carry", the rune to the left of it is incremented.
-// This process repeats until there is no carry, adding an additional rune if necessary.
-//
-// If there is no alphanumeric rune, the rightmost rune will be increased by 1
-// regardless whether the result is a valid rune or not.
-//
-// Only following characters are alphanumeric.
-// * a - z
-// * A - Z
-// * 0 - 9
-//
-// Samples (borrowed from ruby's String#succ document):
-// "abcd" => "abce"
-// "THX1138" => "THX1139"
-// "<<koala>>" => "<<koalb>>"
-// "1999zzz" => "2000aaa"
-// "ZZZ9999" => "AAAA0000"
-// "***" => "**+"
-func Successor(str string) string {
- if str == "" {
- return str
- }
-
- var r rune
- var i int
- carry := ' '
- runes := []rune(str)
- l := len(runes)
- lastAlphanumeric := l
-
- for i = l - 1; i >= 0; i-- {
- r = runes[i]
-
- if ('a' <= r && r <= 'y') ||
- ('A' <= r && r <= 'Y') ||
- ('0' <= r && r <= '8') {
- runes[i]++
- carry = ' '
- lastAlphanumeric = i
- break
- }
-
- switch r {
- case 'z':
- runes[i] = 'a'
- carry = 'a'
- lastAlphanumeric = i
-
- case 'Z':
- runes[i] = 'A'
- carry = 'A'
- lastAlphanumeric = i
-
- case '9':
- runes[i] = '0'
- carry = '0'
- lastAlphanumeric = i
- }
- }
-
- // Needs to add one character for carry.
- if i < 0 && carry != ' ' {
- buf := &stringBuilder{}
- buf.Grow(l + 4) // Reserve enough space for write.
-
- if lastAlphanumeric != 0 {
- buf.WriteString(str[:lastAlphanumeric])
- }
-
- buf.WriteRune(carry)
-
- for _, r = range runes[lastAlphanumeric:] {
- buf.WriteRune(r)
- }
-
- return buf.String()
- }
-
- // No alphanumeric character. Simply increase last rune's value.
- if lastAlphanumeric == l {
- runes[l-1]++
- }
-
- return string(runes)
-}
diff --git a/vendor/github.com/huandu/xstrings/count.go b/vendor/github.com/huandu/xstrings/count.go
deleted file mode 100644
index f96e38703a..0000000000
--- a/vendor/github.com/huandu/xstrings/count.go
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright 2015 Huan Du. All rights reserved.
-// Licensed under the MIT license that can be found in the LICENSE file.
-
-package xstrings
-
-import (
- "unicode"
- "unicode/utf8"
-)
-
-// Len returns str's utf8 rune length.
-func Len(str string) int {
- return utf8.RuneCountInString(str)
-}
-
-// WordCount returns number of words in a string.
-//
-// Word is defined as a locale dependent string containing alphabetic characters,
-// which may also contain but not start with `'` and `-` characters.
-func WordCount(str string) int {
- var r rune
- var size, n int
-
- inWord := false
-
- for len(str) > 0 {
- r, size = utf8.DecodeRuneInString(str)
-
- switch {
- case isAlphabet(r):
- if !inWord {
- inWord = true
- n++
- }
-
- case inWord && (r == '\'' || r == '-'):
- // Still in word.
-
- default:
- inWord = false
- }
-
- str = str[size:]
- }
-
- return n
-}
-
-const minCJKCharacter = '\u3400'
-
-// Checks r is a letter but not CJK character.
-func isAlphabet(r rune) bool {
- if !unicode.IsLetter(r) {
- return false
- }
-
- switch {
- // Quick check for non-CJK character.
- case r < minCJKCharacter:
- return true
-
- // Common CJK characters.
- case r >= '\u4E00' && r <= '\u9FCC':
- return false
-
- // Rare CJK characters.
- case r >= '\u3400' && r <= '\u4D85':
- return false
-
- // Rare and historic CJK characters.
- case r >= '\U00020000' && r <= '\U0002B81D':
- return false
- }
-
- return true
-}
-
-// Width returns string width in monotype font.
-// Multi-byte characters are usually twice the width of single byte characters.
-//
-// Algorithm comes from `mb_strwidth` in PHP.
-// http://php.net/manual/en/function.mb-strwidth.php
-func Width(str string) int {
- var r rune
- var size, n int
-
- for len(str) > 0 {
- r, size = utf8.DecodeRuneInString(str)
- n += RuneWidth(r)
- str = str[size:]
- }
-
- return n
-}
-
-// RuneWidth returns character width in monotype font.
-// Multi-byte characters are usually twice the width of single byte characters.
-//
-// Algorithm comes from `mb_strwidth` in PHP.
-// http://php.net/manual/en/function.mb-strwidth.php
-func RuneWidth(r rune) int {
- switch {
- case r == utf8.RuneError || r < '\x20':
- return 0
-
- case '\x20' <= r && r < '\u2000':
- return 1
-
- case '\u2000' <= r && r < '\uFF61':
- return 2
-
- case '\uFF61' <= r && r < '\uFFA0':
- return 1
-
- case '\uFFA0' <= r:
- return 2
- }
-
- return 0
-}
diff --git a/vendor/github.com/huandu/xstrings/doc.go b/vendor/github.com/huandu/xstrings/doc.go
deleted file mode 100644
index 1a6ef069f6..0000000000
--- a/vendor/github.com/huandu/xstrings/doc.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright 2015 Huan Du. All rights reserved.
-// Licensed under the MIT license that can be found in the LICENSE file.
-
-// Package xstrings is to provide string algorithms which are useful but not included in `strings` package.
-// See project home page for details. https://github.com/huandu/xstrings
-//
-// Package xstrings assumes all strings are encoded in utf8.
-package xstrings
diff --git a/vendor/github.com/huandu/xstrings/format.go b/vendor/github.com/huandu/xstrings/format.go
deleted file mode 100644
index 8cd76c525c..0000000000
--- a/vendor/github.com/huandu/xstrings/format.go
+++ /dev/null
@@ -1,169 +0,0 @@
-// Copyright 2015 Huan Du. All rights reserved.
-// Licensed under the MIT license that can be found in the LICENSE file.
-
-package xstrings
-
-import (
- "unicode/utf8"
-)
-
-// ExpandTabs can expand tabs ('\t') rune in str to one or more spaces dpending on
-// current column and tabSize.
-// The column number is reset to zero after each newline ('\n') occurring in the str.
-//
-// ExpandTabs uses RuneWidth to decide rune's width.
-// For example, CJK characters will be treated as two characters.
-//
-// If tabSize <= 0, ExpandTabs panics with error.
-//
-// Samples:
-// ExpandTabs("a\tbc\tdef\tghij\tk", 4) => "a bc def ghij k"
-// ExpandTabs("abcdefg\thij\nk\tl", 4) => "abcdefg hij\nk l"
-// ExpandTabs("z中\t文\tw", 4) => "z中 文 w"
-func ExpandTabs(str string, tabSize int) string {
- if tabSize <= 0 {
- panic("tab size must be positive")
- }
-
- var r rune
- var i, size, column, expand int
- var output *stringBuilder
-
- orig := str
-
- for len(str) > 0 {
- r, size = utf8.DecodeRuneInString(str)
-
- if r == '\t' {
- expand = tabSize - column%tabSize
-
- if output == nil {
- output = allocBuffer(orig, str)
- }
-
- for i = 0; i < expand; i++ {
- output.WriteRune(' ')
- }
-
- column += expand
- } else {
- if r == '\n' {
- column = 0
- } else {
- column += RuneWidth(r)
- }
-
- if output != nil {
- output.WriteRune(r)
- }
- }
-
- str = str[size:]
- }
-
- if output == nil {
- return orig
- }
-
- return output.String()
-}
-
-// LeftJustify returns a string with pad string at right side if str's rune length is smaller than length.
-// If str's rune length is larger than length, str itself will be returned.
-//
-// If pad is an empty string, str will be returned.
-//
-// Samples:
-// LeftJustify("hello", 4, " ") => "hello"
-// LeftJustify("hello", 10, " ") => "hello "
-// LeftJustify("hello", 10, "123") => "hello12312"
-func LeftJustify(str string, length int, pad string) string {
- l := Len(str)
-
- if l >= length || pad == "" {
- return str
- }
-
- remains := length - l
- padLen := Len(pad)
-
- output := &stringBuilder{}
- output.Grow(len(str) + (remains/padLen+1)*len(pad))
- output.WriteString(str)
- writePadString(output, pad, padLen, remains)
- return output.String()
-}
-
-// RightJustify returns a string with pad string at left side if str's rune length is smaller than length.
-// If str's rune length is larger than length, str itself will be returned.
-//
-// If pad is an empty string, str will be returned.
-//
-// Samples:
-// RightJustify("hello", 4, " ") => "hello"
-// RightJustify("hello", 10, " ") => " hello"
-// RightJustify("hello", 10, "123") => "12312hello"
-func RightJustify(str string, length int, pad string) string {
- l := Len(str)
-
- if l >= length || pad == "" {
- return str
- }
-
- remains := length - l
- padLen := Len(pad)
-
- output := &stringBuilder{}
- output.Grow(len(str) + (remains/padLen+1)*len(pad))
- writePadString(output, pad, padLen, remains)
- output.WriteString(str)
- return output.String()
-}
-
-// Center returns a string with pad string at both side if str's rune length is smaller than length.
-// If str's rune length is larger than length, str itself will be returned.
-//
-// If pad is an empty string, str will be returned.
-//
-// Samples:
-// Center("hello", 4, " ") => "hello"
-// Center("hello", 10, " ") => " hello "
-// Center("hello", 10, "123") => "12hello123"
-func Center(str string, length int, pad string) string {
- l := Len(str)
-
- if l >= length || pad == "" {
- return str
- }
-
- remains := length - l
- padLen := Len(pad)
-
- output := &stringBuilder{}
- output.Grow(len(str) + (remains/padLen+1)*len(pad))
- writePadString(output, pad, padLen, remains/2)
- output.WriteString(str)
- writePadString(output, pad, padLen, (remains+1)/2)
- return output.String()
-}
-
-func writePadString(output *stringBuilder, pad string, padLen, remains int) {
- var r rune
- var size int
-
- repeats := remains / padLen
-
- for i := 0; i < repeats; i++ {
- output.WriteString(pad)
- }
-
- remains = remains % padLen
-
- if remains != 0 {
- for i := 0; i < remains; i++ {
- r, size = utf8.DecodeRuneInString(pad)
- output.WriteRune(r)
- pad = pad[size:]
- }
- }
-}
diff --git a/vendor/github.com/huandu/xstrings/go.mod b/vendor/github.com/huandu/xstrings/go.mod
deleted file mode 100644
index 3982c204ca..0000000000
--- a/vendor/github.com/huandu/xstrings/go.mod
+++ /dev/null
@@ -1,3 +0,0 @@
-module github.com/huandu/xstrings
-
-go 1.12
diff --git a/vendor/github.com/huandu/xstrings/manipulate.go b/vendor/github.com/huandu/xstrings/manipulate.go
deleted file mode 100644
index 64075f9bb8..0000000000
--- a/vendor/github.com/huandu/xstrings/manipulate.go
+++ /dev/null
@@ -1,216 +0,0 @@
-// Copyright 2015 Huan Du. All rights reserved.
-// Licensed under the MIT license that can be found in the LICENSE file.
-
-package xstrings
-
-import (
- "strings"
- "unicode/utf8"
-)
-
-// Reverse a utf8 encoded string.
-func Reverse(str string) string {
- var size int
-
- tail := len(str)
- buf := make([]byte, tail)
- s := buf
-
- for len(str) > 0 {
- _, size = utf8.DecodeRuneInString(str)
- tail -= size
- s = append(s[:tail], []byte(str[:size])...)
- str = str[size:]
- }
-
- return string(buf)
-}
-
-// Slice a string by rune.
-//
-// Start must satisfy 0 <= start <= rune length.
-//
-// End can be positive, zero or negative.
-// If end >= 0, start and end must satisfy start <= end <= rune length.
-// If end < 0, it means slice to the end of string.
-//
-// Otherwise, Slice will panic as out of range.
-func Slice(str string, start, end int) string {
- var size, startPos, endPos int
-
- origin := str
-
- if start < 0 || end > len(str) || (end >= 0 && start > end) {
- panic("out of range")
- }
-
- if end >= 0 {
- end -= start
- }
-
- for start > 0 && len(str) > 0 {
- _, size = utf8.DecodeRuneInString(str)
- start--
- startPos += size
- str = str[size:]
- }
-
- if end < 0 {
- return origin[startPos:]
- }
-
- endPos = startPos
-
- for end > 0 && len(str) > 0 {
- _, size = utf8.DecodeRuneInString(str)
- end--
- endPos += size
- str = str[size:]
- }
-
- if len(str) == 0 && (start > 0 || end > 0) {
- panic("out of range")
- }
-
- return origin[startPos:endPos]
-}
-
-// Partition splits a string by sep into three parts.
-// The return value is a slice of strings with head, match and tail.
-//
-// If str contains sep, for example "hello" and "l", Partition returns
-// "he", "l", "lo"
-//
-// If str doesn't contain sep, for example "hello" and "x", Partition returns
-// "hello", "", ""
-func Partition(str, sep string) (head, match, tail string) {
- index := strings.Index(str, sep)
-
- if index == -1 {
- head = str
- return
- }
-
- head = str[:index]
- match = str[index : index+len(sep)]
- tail = str[index+len(sep):]
- return
-}
-
-// LastPartition splits a string by last instance of sep into three parts.
-// The return value is a slice of strings with head, match and tail.
-//
-// If str contains sep, for example "hello" and "l", LastPartition returns
-// "hel", "l", "o"
-//
-// If str doesn't contain sep, for example "hello" and "x", LastPartition returns
-// "", "", "hello"
-func LastPartition(str, sep string) (head, match, tail string) {
- index := strings.LastIndex(str, sep)
-
- if index == -1 {
- tail = str
- return
- }
-
- head = str[:index]
- match = str[index : index+len(sep)]
- tail = str[index+len(sep):]
- return
-}
-
-// Insert src into dst at given rune index.
-// Index is counted by runes instead of bytes.
-//
-// If index is out of range of dst, panic with out of range.
-func Insert(dst, src string, index int) string {
- return Slice(dst, 0, index) + src + Slice(dst, index, -1)
-}
-
-// Scrub scrubs invalid utf8 bytes with repl string.
-// Adjacent invalid bytes are replaced only once.
-func Scrub(str, repl string) string {
- var buf *stringBuilder
- var r rune
- var size, pos int
- var hasError bool
-
- origin := str
-
- for len(str) > 0 {
- r, size = utf8.DecodeRuneInString(str)
-
- if r == utf8.RuneError {
- if !hasError {
- if buf == nil {
- buf = &stringBuilder{}
- }
-
- buf.WriteString(origin[:pos])
- hasError = true
- }
- } else if hasError {
- hasError = false
- buf.WriteString(repl)
-
- origin = origin[pos:]
- pos = 0
- }
-
- pos += size
- str = str[size:]
- }
-
- if buf != nil {
- buf.WriteString(origin)
- return buf.String()
- }
-
- // No invalid byte.
- return origin
-}
-
-// WordSplit splits a string into words. Returns a slice of words.
-// If there is no word in a string, return nil.
-//
-// Word is defined as a locale dependent string containing alphabetic characters,
-// which may also contain but not start with `'` and `-` characters.
-func WordSplit(str string) []string {
- var word string
- var words []string
- var r rune
- var size, pos int
-
- inWord := false
-
- for len(str) > 0 {
- r, size = utf8.DecodeRuneInString(str)
-
- switch {
- case isAlphabet(r):
- if !inWord {
- inWord = true
- word = str
- pos = 0
- }
-
- case inWord && (r == '\'' || r == '-'):
- // Still in word.
-
- default:
- if inWord {
- inWord = false
- words = append(words, word[:pos])
- }
- }
-
- pos += size
- str = str[size:]
- }
-
- if inWord {
- words = append(words, word[:pos])
- }
-
- return words
-}
diff --git a/vendor/github.com/huandu/xstrings/stringbuilder.go b/vendor/github.com/huandu/xstrings/stringbuilder.go
deleted file mode 100644
index bb0919d32f..0000000000
--- a/vendor/github.com/huandu/xstrings/stringbuilder.go
+++ /dev/null
@@ -1,7 +0,0 @@
-//+build go1.10
-
-package xstrings
-
-import "strings"
-
-type stringBuilder = strings.Builder
diff --git a/vendor/github.com/huandu/xstrings/stringbuilder_go110.go b/vendor/github.com/huandu/xstrings/stringbuilder_go110.go
deleted file mode 100644
index dac389d139..0000000000
--- a/vendor/github.com/huandu/xstrings/stringbuilder_go110.go
+++ /dev/null
@@ -1,9 +0,0 @@
-//+build !go1.10
-
-package xstrings
-
-import "bytes"
-
-type stringBuilder struct {
- bytes.Buffer
-}
diff --git a/vendor/github.com/huandu/xstrings/translate.go b/vendor/github.com/huandu/xstrings/translate.go
deleted file mode 100644
index 42e694fb17..0000000000
--- a/vendor/github.com/huandu/xstrings/translate.go
+++ /dev/null
@@ -1,546 +0,0 @@
-// Copyright 2015 Huan Du. All rights reserved.
-// Licensed under the MIT license that can be found in the LICENSE file.
-
-package xstrings
-
-import (
- "unicode"
- "unicode/utf8"
-)
-
-type runeRangeMap struct {
- FromLo rune // Lower bound of range map.
- FromHi rune // An inclusive higher bound of range map.
- ToLo rune
- ToHi rune
-}
-
-type runeDict struct {
- Dict [unicode.MaxASCII + 1]rune
-}
-
-type runeMap map[rune]rune
-
-// Translator can translate string with pre-compiled from and to patterns.
-// If a from/to pattern pair needs to be used more than once, it's recommended
-// to create a Translator and reuse it.
-type Translator struct {
- quickDict *runeDict // A quick dictionary to look up rune by index. Only available for latin runes.
- runeMap runeMap // Rune map for translation.
- ranges []*runeRangeMap // Ranges of runes.
- mappedRune rune // If mappedRune >= 0, all matched runes are translated to the mappedRune.
- reverted bool // If to pattern is empty, all matched characters will be deleted.
- hasPattern bool
-}
-
-// NewTranslator creates new Translator through a from/to pattern pair.
-func NewTranslator(from, to string) *Translator {
- tr := &Translator{}
-
- if from == "" {
- return tr
- }
-
- reverted := from[0] == '^'
- deletion := len(to) == 0
-
- if reverted {
- from = from[1:]
- }
-
- var fromStart, fromEnd, fromRangeStep rune
- var toStart, toEnd, toRangeStep rune
- var fromRangeSize, toRangeSize rune
- var singleRunes []rune
-
- // Update the to rune range.
- updateRange := func() {
- // No more rune to read in the to rune pattern.
- if toEnd == utf8.RuneError {
- return
- }
-
- if toRangeStep == 0 {
- to, toStart, toEnd, toRangeStep = nextRuneRange(to, toEnd)
- return
- }
-
- // Current range is not empty. Consume 1 rune from start.
- if toStart != toEnd {
- toStart += toRangeStep
- return
- }
-
- // No more rune. Repeat the last rune.
- if to == "" {
- toEnd = utf8.RuneError
- return
- }
-
- // Both start and end are used. Read two more runes from the to pattern.
- to, toStart, toEnd, toRangeStep = nextRuneRange(to, utf8.RuneError)
- }
-
- if deletion {
- toStart = utf8.RuneError
- toEnd = utf8.RuneError
- } else {
- // If from pattern is reverted, only the last rune in the to pattern will be used.
- if reverted {
- var size int
-
- for len(to) > 0 {
- toStart, size = utf8.DecodeRuneInString(to)
- to = to[size:]
- }
-
- toEnd = utf8.RuneError
- } else {
- to, toStart, toEnd, toRangeStep = nextRuneRange(to, utf8.RuneError)
- }
- }
-
- fromEnd = utf8.RuneError
-
- for len(from) > 0 {
- from, fromStart, fromEnd, fromRangeStep = nextRuneRange(from, fromEnd)
-
- // fromStart is a single character. Just map it with a rune in the to pattern.
- if fromRangeStep == 0 {
- singleRunes = tr.addRune(fromStart, toStart, singleRunes)
- updateRange()
- continue
- }
-
- for toEnd != utf8.RuneError && fromStart != fromEnd {
- // If mapped rune is a single character instead of a range, simply shift first
- // rune in the range.
- if toRangeStep == 0 {
- singleRunes = tr.addRune(fromStart, toStart, singleRunes)
- updateRange()
- fromStart += fromRangeStep
- continue
- }
-
- fromRangeSize = (fromEnd - fromStart) * fromRangeStep
- toRangeSize = (toEnd - toStart) * toRangeStep
-
- // Not enough runes in the to pattern. Need to read more.
- if fromRangeSize > toRangeSize {
- fromStart, toStart = tr.addRuneRange(fromStart, fromStart+toRangeSize*fromRangeStep, toStart, toEnd, singleRunes)
- fromStart += fromRangeStep
- updateRange()
-
- // Edge case: If fromRangeSize == toRangeSize + 1, the last fromStart value needs be considered
- // as a single rune.
- if fromStart == fromEnd {
- singleRunes = tr.addRune(fromStart, toStart, singleRunes)
- updateRange()
- }
-
- continue
- }
-
- fromStart, toStart = tr.addRuneRange(fromStart, fromEnd, toStart, toStart+fromRangeSize*toRangeStep, singleRunes)
- updateRange()
- break
- }
-
- if fromStart == fromEnd {
- fromEnd = utf8.RuneError
- continue
- }
-
- _, toStart = tr.addRuneRange(fromStart, fromEnd, toStart, toStart, singleRunes)
- fromEnd = utf8.RuneError
- }
-
- if fromEnd != utf8.RuneError {
- tr.addRune(fromEnd, toStart, singleRunes)
- }
-
- tr.reverted = reverted
- tr.mappedRune = -1
- tr.hasPattern = true
-
- // Translate RuneError only if in deletion or reverted mode.
- if deletion || reverted {
- tr.mappedRune = toStart
- }
-
- return tr
-}
-
-func (tr *Translator) addRune(from, to rune, singleRunes []rune) []rune {
- if from <= unicode.MaxASCII {
- if tr.quickDict == nil {
- tr.quickDict = &runeDict{}
- }
-
- tr.quickDict.Dict[from] = to
- } else {
- if tr.runeMap == nil {
- tr.runeMap = make(runeMap)
- }
-
- tr.runeMap[from] = to
- }
-
- singleRunes = append(singleRunes, from)
- return singleRunes
-}
-
-func (tr *Translator) addRuneRange(fromLo, fromHi, toLo, toHi rune, singleRunes []rune) (rune, rune) {
- var r rune
- var rrm *runeRangeMap
-
- if fromLo < fromHi {
- rrm = &runeRangeMap{
- FromLo: fromLo,
- FromHi: fromHi,
- ToLo: toLo,
- ToHi: toHi,
- }
- } else {
- rrm = &runeRangeMap{
- FromLo: fromHi,
- FromHi: fromLo,
- ToLo: toHi,
- ToHi: toLo,
- }
- }
-
- // If there is any single rune conflicts with this rune range, clear single rune record.
- for _, r = range singleRunes {
- if rrm.FromLo <= r && r <= rrm.FromHi {
- if r <= unicode.MaxASCII {
- tr.quickDict.Dict[r] = 0
- } else {
- delete(tr.runeMap, r)
- }
- }
- }
-
- tr.ranges = append(tr.ranges, rrm)
- return fromHi, toHi
-}
-
-func nextRuneRange(str string, last rune) (remaining string, start, end rune, rangeStep rune) {
- var r rune
- var size int
-
- remaining = str
- escaping := false
- isRange := false
-
- for len(remaining) > 0 {
- r, size = utf8.DecodeRuneInString(remaining)
- remaining = remaining[size:]
-
- // Parse special characters.
- if !escaping {
- if r == '\\' {
- escaping = true
- continue
- }
-
- if r == '-' {
- // Ignore slash at beginning of string.
- if last == utf8.RuneError {
- continue
- }
-
- start = last
- isRange = true
- continue
- }
- }
-
- escaping = false
-
- if last != utf8.RuneError {
- // This is a range which start and end are the same.
- // Considier it as a normal character.
- if isRange && last == r {
- isRange = false
- continue
- }
-
- start = last
- end = r
-
- if isRange {
- if start < end {
- rangeStep = 1
- } else {
- rangeStep = -1
- }
- }
-
- return
- }
-
- last = r
- }
-
- start = last
- end = utf8.RuneError
- return
-}
-
-// Translate str with a from/to pattern pair.
-//
-// See comment in Translate function for usage and samples.
-func (tr *Translator) Translate(str string) string {
- if !tr.hasPattern || str == "" {
- return str
- }
-
- var r rune
- var size int
- var needTr bool
-
- orig := str
-
- var output *stringBuilder
-
- for len(str) > 0 {
- r, size = utf8.DecodeRuneInString(str)
- r, needTr = tr.TranslateRune(r)
-
- if needTr && output == nil {
- output = allocBuffer(orig, str)
- }
-
- if r != utf8.RuneError && output != nil {
- output.WriteRune(r)
- }
-
- str = str[size:]
- }
-
- // No character is translated.
- if output == nil {
- return orig
- }
-
- return output.String()
-}
-
-// TranslateRune return translated rune and true if r matches the from pattern.
-// If r doesn't match the pattern, original r is returned and translated is false.
-func (tr *Translator) TranslateRune(r rune) (result rune, translated bool) {
- switch {
- case tr.quickDict != nil:
- if r <= unicode.MaxASCII {
- result = tr.quickDict.Dict[r]
-
- if result != 0 {
- translated = true
-
- if tr.mappedRune >= 0 {
- result = tr.mappedRune
- }
-
- break
- }
- }
-
- fallthrough
-
- case tr.runeMap != nil:
- var ok bool
-
- if result, ok = tr.runeMap[r]; ok {
- translated = true
-
- if tr.mappedRune >= 0 {
- result = tr.mappedRune
- }
-
- break
- }
-
- fallthrough
-
- default:
- var rrm *runeRangeMap
- ranges := tr.ranges
-
- for i := len(ranges) - 1; i >= 0; i-- {
- rrm = ranges[i]
-
- if rrm.FromLo <= r && r <= rrm.FromHi {
- translated = true
-
- if tr.mappedRune >= 0 {
- result = tr.mappedRune
- break
- }
-
- if rrm.ToLo < rrm.ToHi {
- result = rrm.ToLo + r - rrm.FromLo
- } else if rrm.ToLo > rrm.ToHi {
- // ToHi can be smaller than ToLo if range is from higher to lower.
- result = rrm.ToLo - r + rrm.FromLo
- } else {
- result = rrm.ToLo
- }
-
- break
- }
- }
- }
-
- if tr.reverted {
- if !translated {
- result = tr.mappedRune
- }
-
- translated = !translated
- }
-
- if !translated {
- result = r
- }
-
- return
-}
-
-// HasPattern returns true if Translator has one pattern at least.
-func (tr *Translator) HasPattern() bool {
- return tr.hasPattern
-}
-
-// Translate str with the characters defined in from replaced by characters defined in to.
-//
-// From and to are patterns representing a set of characters. Pattern is defined as following.
-//
-// * Special characters
-// * '-' means a range of runes, e.g.
-// * "a-z" means all characters from 'a' to 'z' inclusive;
-// * "z-a" means all characters from 'z' to 'a' inclusive.
-// * '^' as first character means a set of all runes excepted listed, e.g.
-// * "^a-z" means all characters except 'a' to 'z' inclusive.
-// * '\' escapes special characters.
-// * Normal character represents itself, e.g. "abc" is a set including 'a', 'b' and 'c'.
-//
-// Translate will try to find a 1:1 mapping from from to to.
-// If to is smaller than from, last rune in to will be used to map "out of range" characters in from.
-//
-// Note that '^' only works in the from pattern. It will be considered as a normal character in the to pattern.
-//
-// If the to pattern is an empty string, Translate works exactly the same as Delete.
-//
-// Samples:
-// Translate("hello", "aeiou", "12345") => "h2ll4"
-// Translate("hello", "a-z", "A-Z") => "HELLO"
-// Translate("hello", "z-a", "a-z") => "svool"
-// Translate("hello", "aeiou", "*") => "h*ll*"
-// Translate("hello", "^l", "*") => "**ll*"
-// Translate("hello ^ world", `\^lo`, "*") => "he*** * w*r*d"
-func Translate(str, from, to string) string {
- tr := NewTranslator(from, to)
- return tr.Translate(str)
-}
-
-// Delete runes in str matching the pattern.
-// Pattern is defined in Translate function.
-//
-// Samples:
-// Delete("hello", "aeiou") => "hll"
-// Delete("hello", "a-k") => "llo"
-// Delete("hello", "^a-k") => "he"
-func Delete(str, pattern string) string {
- tr := NewTranslator(pattern, "")
- return tr.Translate(str)
-}
-
-// Count how many runes in str match the pattern.
-// Pattern is defined in Translate function.
-//
-// Samples:
-// Count("hello", "aeiou") => 3
-// Count("hello", "a-k") => 3
-// Count("hello", "^a-k") => 2
-func Count(str, pattern string) int {
- if pattern == "" || str == "" {
- return 0
- }
-
- var r rune
- var size int
- var matched bool
-
- tr := NewTranslator(pattern, "")
- cnt := 0
-
- for len(str) > 0 {
- r, size = utf8.DecodeRuneInString(str)
- str = str[size:]
-
- if _, matched = tr.TranslateRune(r); matched {
- cnt++
- }
- }
-
- return cnt
-}
-
-// Squeeze deletes adjacent repeated runes in str.
-// If pattern is not empty, only runes matching the pattern will be squeezed.
-//
-// Samples:
-// Squeeze("hello", "") => "helo"
-// Squeeze("hello", "m-z") => "hello"
-// Squeeze("hello world", " ") => "hello world"
-func Squeeze(str, pattern string) string {
- var last, r rune
- var size int
- var skipSqueeze, matched bool
- var tr *Translator
- var output *stringBuilder
-
- orig := str
- last = -1
-
- if len(pattern) > 0 {
- tr = NewTranslator(pattern, "")
- }
-
- for len(str) > 0 {
- r, size = utf8.DecodeRuneInString(str)
-
- // Need to squeeze the str.
- if last == r && !skipSqueeze {
- if tr != nil {
- if _, matched = tr.TranslateRune(r); !matched {
- skipSqueeze = true
- }
- }
-
- if output == nil {
- output = allocBuffer(orig, str)
- }
-
- if skipSqueeze {
- output.WriteRune(r)
- }
- } else {
- if output != nil {
- output.WriteRune(r)
- }
-
- last = r
- skipSqueeze = false
- }
-
- str = str[size:]
- }
-
- if output == nil {
- return orig
- }
-
- return output.String()
-}