-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathstringFunctions.scala
136 lines (119 loc) · 3.88 KB
/
stringFunctions.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package common.utility
import scala.annotation.tailrec
/**
* Created by markmo on 27/02/2016.
*/
object stringFunctions {
/**
* Turns a string of format "foo_bar" or "foo-bar" into camel case "FooBar"
*
* @param str String
*/
def camelize(str: String, startUpper: Boolean = false): String = {
def loop(x: List[Char]): List[Char] = x match {
case ('_' | '-') :: ('_' | '-') :: rest => loop('_' :: rest)
case ('_' | '-') :: ch :: rest => Character.toUpperCase(ch) :: loop(rest)
case ('_' | '-') :: Nil => Nil
case ch :: rest => ch :: loop(rest)
case Nil => Nil
}
if (str == null) {
""
} else if (startUpper) {
loop('_' :: str.toList).mkString
} else {
loop(str.toList).mkString
}
}
def underscore(str: String): String = str.replaceAll("\\s+", "_")
def countSubstring(str: String, sub: String): Int =
if (str == null || sub == null || str.length < sub.length) {
0
} else {
@tailrec
def loop(acc: Int, i: Int): Int =
str.indexOf(sub, i) match {
case -1 => acc
case j => loop(acc + 1, j + sub.length)
}
loop(0, 0)
}
/**
* Convert map of format { some-key: anyval } to { someKey: str }
*
* @param conf Map[String, Any]
* @return Map[String, String]
*/
def parameterize(conf: Map[String, Any]): Map[String, String] = conf map {
case (k, v) => (camelize(k), v.toString)
}
implicit class RichString(val str: String) extends AnyVal {
def isNumber =
str.matches(s"""[+-]?((\d+(e\d+)?[lL]?)|(((\d+(\.\d*)?)|(\.\d+))(e\d+)?[fF]?))""")
}
/**
* Using the "pimp my library" pattern.
*
* @param str String template
*/
implicit class StringTemplate(val str: String) extends AnyVal {
/**
* Render a string template substituting variables.
*
* @param vars Map of variables to replace
* @return String
*/
def template(vars: Map[String, String]): String = {
val sb = new StringBuilder
val pattern = """^('\$([^']*)'|"\$([^"]*)"|'\$\{([^']*)}'|"\$\{([^"]*)}"|\$\{([^}]*)}|\$([^\s]*)\s|\$([^\s]*)$).*""".r
@tailrec
def loop(str: String): String = str match {
case x if x.isEmpty => sb.toString
case pattern(x, a, b, c, d, e, f, g) =>
if (a != null) {
// '$a'
val replacement = vars.getOrElse(a, s"$$a")
sb.append("'").append(replacement).append("'")
loop(str.substring(x.length))
} else if (b != null) {
// "$b"
val replacement = vars.getOrElse(b, s"$$b")
sb.append('"').append(replacement).append('"')
loop(str.substring(x.length))
} else if (c != null) {
// '${c}'
val replacement = vars.getOrElse(c, s"$${c}")
sb.append("'").append(replacement).append("'")
loop(str.substring(x.length))
} else if (d != null) {
// "${d}"
val replacement = vars.getOrElse(c, s"$${d}")
sb.append('"').append(replacement).append('"')
loop(str.substring(x.length))
} else if (e != null) {
// ${e}
val replacement = vars.getOrElse(e, s"$${$e}")
sb.append(replacement)
loop(str.substring(x.length))
} else if (f != null) {
// $f\s
val replacement = vars.getOrElse(f, s"$$$f")
sb.append(replacement).append(" ")
loop(str.substring(x.length))
} else if (g != null) {
// $e<end-of-string>
val replacement = vars.getOrElse(g, s"$$$g")
sb.append(replacement)
loop(str.substring(x.length))
} else {
sb.append(str.head)
loop(str.tail)
}
case _ =>
sb.append(str.head)
loop(str.tail)
}
loop(str)
}
}
}