-
Notifications
You must be signed in to change notification settings - Fork 70
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix #1. camel case from/to underscore.
- Loading branch information
Showing
5 changed files
with
210 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,15 @@ | ||
xstrings | ||
======== | ||
# xstrings # | ||
|
||
More string algorithm for Go. | ||
Go [strings](http://golang.org/pkg/strings) package only has a few string algorithms. There are lots of other useful algorithms missing. | ||
|
||
`xstrings` is to fill the gap. It will include as many useful string algorithm as possible. Please [create new issue](https://github.com/huandu/xstrings/issues) if you find one string algorithm is useful but not in either `strings` and `xstrings`. | ||
|
||
## Install ## | ||
|
||
Use `go get` to install this library. | ||
|
||
go get github.com/huandu/xstrings | ||
|
||
## Document ## | ||
|
||
See [GoDoc](https://godoc.org/github.com/huandu/xstrings) for details. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
// Copyright 2015 Huan Du. All rights reserved. | ||
// Licensed under the MIT license that can be found in the LICENSE file. | ||
|
||
package xstrings | ||
|
||
import ( | ||
"bytes" | ||
"unicode" | ||
"unicode/utf8" | ||
) | ||
|
||
// ToCamelCase can convert all lower case characters behind underscores | ||
// to upper case character. | ||
// Underscore character will be removed in result except following cases. | ||
// * More than 1 underscore, e.g. "a__b" => "A_B" | ||
// * At the beginning of string, e.g. "_a" => "_A" | ||
// * At the end of string, e.g. "ab_" => "Ab_" | ||
func ToCamelCase(str string) string { | ||
if len(str) == 0 { | ||
return "" | ||
} | ||
|
||
buf := &bytes.Buffer{} | ||
var r0, r1 rune | ||
var size int | ||
|
||
// leading '_' will appear in output. | ||
for len(str) > 0 { | ||
r0, size = utf8.DecodeRuneInString(str) | ||
str = str[size:] | ||
|
||
if r0 != '_' { | ||
break | ||
} | ||
|
||
buf.WriteRune(r0) | ||
} | ||
|
||
if len(str) == 0 { | ||
return buf.String() | ||
} | ||
|
||
buf.WriteRune(unicode.ToUpper(r0)) | ||
r0, size = utf8.DecodeRuneInString(str) | ||
str = str[size:] | ||
|
||
for len(str) > 0 { | ||
r1 = r0 | ||
r0, size = utf8.DecodeRuneInString(str) | ||
str = str[size:] | ||
|
||
if r1 == '_' && r0 != '_' { | ||
r0 = unicode.ToUpper(r0) | ||
} else { | ||
buf.WriteRune(r1) | ||
} | ||
} | ||
|
||
buf.WriteRune(r0) | ||
return buf.String() | ||
} | ||
|
||
// ToUnderscore can convert all upper case characters in a string to | ||
// underscore format. | ||
// | ||
// Some samples. | ||
// "FirstName" => "first_name" | ||
// "HTTPServer" => "http_server" | ||
// "NoHTTPS" => "no_https" | ||
func ToUnderscore(str string) string { | ||
if len(str) == 0 { | ||
return "" | ||
} | ||
|
||
buf := &bytes.Buffer{} | ||
var r0, r1 rune | ||
var size int | ||
|
||
for len(str) > 0 { | ||
r0, size = utf8.DecodeRuneInString(str) | ||
str = str[size:] | ||
|
||
switch { | ||
case r0 == utf8.RuneError: | ||
buf.WriteByte(byte(str[0])) | ||
|
||
case unicode.IsUpper(r0): | ||
if buf.Len() > 0 { | ||
buf.WriteRune('_') | ||
} | ||
|
||
buf.WriteRune(unicode.ToLower(r0)) | ||
|
||
if len(str) == 0 { | ||
break | ||
} | ||
|
||
r0, size = utf8.DecodeRuneInString(str) | ||
str = str[size:] | ||
|
||
if !unicode.IsUpper(r0) { | ||
buf.WriteRune(r0) | ||
break | ||
} | ||
|
||
// find next non-upper-case character and insert `_` properly. | ||
// it's designed to convert `HTTPServer` to `http_server`. | ||
// if there are more than 2 adjacent upper case characters in a word, | ||
// treat them as an abbreviation plus a normal word. | ||
for len(str) > 0 { | ||
r1 = r0 | ||
r0, size = utf8.DecodeRuneInString(str) | ||
str = str[size:] | ||
|
||
if r0 == utf8.RuneError { | ||
buf.WriteRune(unicode.ToLower(r1)) | ||
buf.WriteByte(byte(str[0])) | ||
break | ||
} | ||
|
||
if !unicode.IsUpper(r0) { | ||
buf.WriteRune('_') | ||
buf.WriteRune(unicode.ToLower(r1)) | ||
buf.WriteRune(r0) | ||
break | ||
} | ||
|
||
buf.WriteRune(unicode.ToLower(r1)) | ||
} | ||
|
||
if len(str) == 0 { | ||
buf.WriteRune(unicode.ToLower(r0)) | ||
} | ||
|
||
default: | ||
buf.WriteRune(r0) | ||
} | ||
} | ||
|
||
return buf.String() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// Copyright 2015 Huan Du. All rights reserved. | ||
// Licensed under the MIT license that can be found in the LICENSE file. | ||
|
||
package xstrings | ||
|
||
import ( | ||
"testing" | ||
) | ||
|
||
func TestToUnderscore(t *testing.T) { | ||
runTestCases(t, ToUnderscore, map[string]string{ | ||
"HTTPServer": "http_server", | ||
"_camelCase": "_camel_case", | ||
"NoHTTPS": "no_https", | ||
"Wi_thF": "wi_th_f", | ||
"_AnotherTES_TCaseP": "__another_te_s__t_case_p", | ||
"ALL": "all", | ||
}) | ||
} | ||
|
||
func TestToCamelCase(t *testing.T) { | ||
runTestCases(t, ToCamelCase, map[string]string{ | ||
"http_server": "HttpServer", | ||
"_camel_case": "_CamelCase", | ||
"no_https": "NoHttps", | ||
"_complex__case_": "_Complex_Case_", | ||
"all": "All", | ||
}) | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
// 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. | ||
// All algorithms working directly on string can be added to this package. | ||
package xstrings | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// Copyright 2015 Huan Du. All rights reserved. | ||
// Licensed under the MIT license that can be found in the LICENSE file. | ||
|
||
package xstrings | ||
|
||
import ( | ||
"testing" | ||
) | ||
|
||
func runTestCases(t *testing.T, converter func(string)string, cases map[string]string) { | ||
for k, v := range cases { | ||
s := converter(k) | ||
|
||
if s != v { | ||
t.Fatalf("case fails. [expected:%v] [actual:%v]", v, s) | ||
} | ||
} | ||
} |