-
Notifications
You must be signed in to change notification settings - Fork 155
/
Copy pathUtils.scala
168 lines (149 loc) · 4.9 KB
/
Utils.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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
package io.kaitai.struct
import java.nio.charset.Charset
import scala.collection.mutable.ListBuffer
object Utils {
/**
* BigInt-typed max value of unsigned 32-bit integer.
*/
final val MAX_UINT32 = BigInt("4294967295")
/**
* BigInt-typed max value of unsigned 64-bit integer.
*/
final val MAX_UINT64 = BigInt("18446744073709551615")
private val RDecimal = "^(-?[0-9]+)$".r
private val RHex = "^0x([0-9a-fA-F]+)$".r
def strToOptInt(s: String): Option[Int] = {
s match {
case null => None
case RDecimal(_) => Some(s.toInt)
case RHex(hex) => Some(Integer.parseInt(hex, 16))
}
}
def strToLong(s: String): Long = {
s match {
case RDecimal(_) => s.toLong
case RHex(hex) => java.lang.Long.parseLong(hex, 16)
}
}
def strToBytes(s: String): Array[Byte] = {
s match {
case RDecimal(_) => Array(clampIntToByte(s.toInt))
case RHex(hex) => Array(clampIntToByte(java.lang.Integer.parseInt(hex, 16)))
case _ => s.getBytes(Charset.forName("UTF-8"))
}
}
def clampIntToByte(i: Int): Byte = {
if (i >= -128 && i < 256) {
i.toByte
} else {
throw new RuntimeException(s"value $i outside of byte range")
}
}
/**
* Converts string to `UPPER_UNDER_SCORE` case.
* @param s original string in `lower_under_score` case.
* @return same string in `UPPER_UNDER_SCORE` case.
*/
def upperUnderscoreCase(s: String): String =
Platform.toUpperLocaleInsensitive(s)
/**
* Converts string to `lower_under_score` case. Given that currently
* original string is using the same case, it is essentially a no-op.
* @param s original string in `lower_under_score` case.
* @return same string in `lower_under_score` case.
*/
def lowerUnderscoreCase(s: String): String = s
/**
* Converts string to `UpperCamelCase`.
* @param s original string in `lower_under_score` case.
* @return same string in `UpperCamelCase`.
*/
def upperCamelCase(s: String): String = {
if (s.startsWith("_")) {
"_" + upperCamelCase(s.substring(1))
} else {
s.split("_").map(capitalize).mkString
}
}
/**
* Converts string to `lowerCamelCase`.
* @param s original string in `lower_under_score` case.
* @return same string in `lowerCamelCase`.
*/
def lowerCamelCase(s: String): String = {
if (s.startsWith("_")) {
"_" + lowerCamelCase(s.substring(1))
} else {
val firstWord :: restWords = s.split("_").toList
(firstWord :: restWords.map(capitalize)).mkString
}
}
def capitalize(s: String): String = {
if (s.isEmpty) {
s
} else {
s.charAt(0).toUpper.toString + s.substring(1)
}
}
/**
* Joins collection together to make a single string. Makes extra exception for empty
* collections (not like [[IterableOnce]] `mkString`).
* @param start the starting string.
* @param sep the separator string.
* @param end the ending string.
* @return If the collection is empty, returns empty string, otherwise returns `start`,
* then elements of the collection, every pair separated with `sep`, then `end`.
*/
def join[T](coll: IterableOnce[T], start: String, sep: String, end: String): String = {
val it = coll.iterator
if (it.isEmpty) "" else it.mkString(start, sep, end)
}
/**
* Converts byte array (Seq[Byte]) into hex-escaped C-style literal characters
* (i.e. like \xFF).
* @param arr byte array to escape
* @return array contents hex-escaped as string
*/
def hexEscapeByteArray(arr: Seq[Byte]): String = {
arr.map((x) =>
// Note that we'll have to use "x & 0xff" trick to get byte as unsigned integer.
// This code works differently in Scala JVM and JS, and this is by design.
// For the details, see https://github.com/scala-js/scala-js/issues/2206
"\\x%02X".format(x & 0xff)
).mkString
}
def addUniqueAttr[T](list: ListBuffer[T], element: T): Unit = {
if (!list.contains(element))
list += element
}
/**
* Derives relative name to fullPath, given that we're currently located curPath.
* @param fullPath
* @param curPath
* @return
*/
def relClass(fullPath: List[String], curPath: List[String]): List[String] =
if (fullPath.startsWith(curPath)) {
fullPath.slice(curPath.length, fullPath.length)
} else {
fullPath
}
/**
* Performs safe lookup for up to `len` character in a given
* string `src`, starting at `from`.
* @param src string to work on
* @param from starting character index
* @param len max length of substring
* @return substring of `src`, starting at `from`, up to `len` chars max
*/
def safeLookup(src: String, from: Int, len: Int): String = {
val maxLen = src.length
if (from >= maxLen) {
""
} else {
val to = from + len
val safeTo = if (to > maxLen) maxLen else to
src.substring(from, safeTo)
}
}
}