stringutils.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /*
  2. Copyright 2014 Alexander Okoli
  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. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package goutils
  14. import (
  15. "bytes"
  16. "fmt"
  17. "strings"
  18. "unicode"
  19. )
  20. // Typically returned by functions where a searched item cannot be found
  21. const INDEX_NOT_FOUND = -1
  22. /*
  23. Abbreviate abbreviates a string using ellipses. This will turn the string "Now is the time for all good men" into "Now is the time for..."
  24. Specifically, the algorithm is as follows:
  25. - If str is less than maxWidth characters long, return it.
  26. - Else abbreviate it to (str[0:maxWidth - 3] + "...").
  27. - If maxWidth is less than 4, return an illegal argument error.
  28. - In no case will it return a string of length greater than maxWidth.
  29. Parameters:
  30. str - the string to check
  31. maxWidth - maximum length of result string, must be at least 4
  32. Returns:
  33. string - abbreviated string
  34. error - if the width is too small
  35. */
  36. func Abbreviate(str string, maxWidth int) (string, error) {
  37. return AbbreviateFull(str, 0, maxWidth)
  38. }
  39. /*
  40. AbbreviateFull abbreviates a string using ellipses. This will turn the string "Now is the time for all good men" into "...is the time for..."
  41. This function works like Abbreviate(string, int), but allows you to specify a "left edge" offset. Note that this left edge is not
  42. necessarily going to be the leftmost character in the result, or the first character following the ellipses, but it will appear
  43. somewhere in the result.
  44. In no case will it return a string of length greater than maxWidth.
  45. Parameters:
  46. str - the string to check
  47. offset - left edge of source string
  48. maxWidth - maximum length of result string, must be at least 4
  49. Returns:
  50. string - abbreviated string
  51. error - if the width is too small
  52. */
  53. func AbbreviateFull(str string, offset int, maxWidth int) (string, error) {
  54. if str == "" {
  55. return "", nil
  56. }
  57. if maxWidth < 4 {
  58. err := fmt.Errorf("stringutils illegal argument: Minimum abbreviation width is 4")
  59. return "", err
  60. }
  61. if len(str) <= maxWidth {
  62. return str, nil
  63. }
  64. if offset > len(str) {
  65. offset = len(str)
  66. }
  67. if len(str)-offset < (maxWidth - 3) { // 15 - 5 < 10 - 3 = 10 < 7
  68. offset = len(str) - (maxWidth - 3)
  69. }
  70. abrevMarker := "..."
  71. if offset <= 4 {
  72. return str[0:maxWidth-3] + abrevMarker, nil // str.substring(0, maxWidth - 3) + abrevMarker;
  73. }
  74. if maxWidth < 7 {
  75. err := fmt.Errorf("stringutils illegal argument: Minimum abbreviation width with offset is 7")
  76. return "", err
  77. }
  78. if (offset + maxWidth - 3) < len(str) { // 5 + (10-3) < 15 = 12 < 15
  79. abrevStr, _ := Abbreviate(str[offset:len(str)], (maxWidth - 3))
  80. return abrevMarker + abrevStr, nil // abrevMarker + abbreviate(str.substring(offset), maxWidth - 3);
  81. }
  82. return abrevMarker + str[(len(str)-(maxWidth-3)):len(str)], nil // abrevMarker + str.substring(str.length() - (maxWidth - 3));
  83. }
  84. /*
  85. DeleteWhiteSpace deletes all whitespaces from a string as defined by unicode.IsSpace(rune).
  86. It returns the string without whitespaces.
  87. Parameter:
  88. str - the string to delete whitespace from, may be nil
  89. Returns:
  90. the string without whitespaces
  91. */
  92. func DeleteWhiteSpace(str string) string {
  93. if str == "" {
  94. return str
  95. }
  96. sz := len(str)
  97. var chs bytes.Buffer
  98. count := 0
  99. for i := 0; i < sz; i++ {
  100. ch := rune(str[i])
  101. if !unicode.IsSpace(ch) {
  102. chs.WriteRune(ch)
  103. count++
  104. }
  105. }
  106. if count == sz {
  107. return str
  108. }
  109. return chs.String()
  110. }
  111. /*
  112. IndexOfDifference compares two strings, and returns the index at which the strings begin to differ.
  113. Parameters:
  114. str1 - the first string
  115. str2 - the second string
  116. Returns:
  117. the index where str1 and str2 begin to differ; -1 if they are equal
  118. */
  119. func IndexOfDifference(str1 string, str2 string) int {
  120. if str1 == str2 {
  121. return INDEX_NOT_FOUND
  122. }
  123. if IsEmpty(str1) || IsEmpty(str2) {
  124. return 0
  125. }
  126. var i int
  127. for i = 0; i < len(str1) && i < len(str2); i++ {
  128. if rune(str1[i]) != rune(str2[i]) {
  129. break
  130. }
  131. }
  132. if i < len(str2) || i < len(str1) {
  133. return i
  134. }
  135. return INDEX_NOT_FOUND
  136. }
  137. /*
  138. IsBlank checks if a string is whitespace or empty (""). Observe the following behavior:
  139. goutils.IsBlank("") = true
  140. goutils.IsBlank(" ") = true
  141. goutils.IsBlank("bob") = false
  142. goutils.IsBlank(" bob ") = false
  143. Parameter:
  144. str - the string to check
  145. Returns:
  146. true - if the string is whitespace or empty ("")
  147. */
  148. func IsBlank(str string) bool {
  149. strLen := len(str)
  150. if str == "" || strLen == 0 {
  151. return true
  152. }
  153. for i := 0; i < strLen; i++ {
  154. if unicode.IsSpace(rune(str[i])) == false {
  155. return false
  156. }
  157. }
  158. return true
  159. }
  160. /*
  161. IndexOf returns the index of the first instance of sub in str, with the search beginning from the
  162. index start point specified. -1 is returned if sub is not present in str.
  163. An empty string ("") will return -1 (INDEX_NOT_FOUND). A negative start position is treated as zero.
  164. A start position greater than the string length returns -1.
  165. Parameters:
  166. str - the string to check
  167. sub - the substring to find
  168. start - the start position; negative treated as zero
  169. Returns:
  170. the first index where the sub string was found (always >= start)
  171. */
  172. func IndexOf(str string, sub string, start int) int {
  173. if start < 0 {
  174. start = 0
  175. }
  176. if len(str) < start {
  177. return INDEX_NOT_FOUND
  178. }
  179. if IsEmpty(str) || IsEmpty(sub) {
  180. return INDEX_NOT_FOUND
  181. }
  182. partialIndex := strings.Index(str[start:len(str)], sub)
  183. if partialIndex == -1 {
  184. return INDEX_NOT_FOUND
  185. }
  186. return partialIndex + start
  187. }
  188. // IsEmpty checks if a string is empty (""). Returns true if empty, and false otherwise.
  189. func IsEmpty(str string) bool {
  190. return len(str) == 0
  191. }
  192. // Returns either the passed in string, or if the string is empty, the value of defaultStr.
  193. func DefaultString(str string, defaultStr string) string {
  194. if IsEmpty(str) {
  195. return defaultStr
  196. }
  197. return str
  198. }
  199. // Returns either the passed in string, or if the string is whitespace, empty (""), the value of defaultStr.
  200. func DefaultIfBlank(str string, defaultStr string) string {
  201. if IsBlank(str) {
  202. return defaultStr
  203. }
  204. return str
  205. }