Compare commits

...

4 Commits

Author SHA1 Message Date
Robinson 3bf845f355
version 1.46 2023-08-21 01:43:56 +02:00
Robinson 0ff5f377d1
updated license 2023-08-21 01:43:36 +02:00
Robinson 5fa2e2aff6
updated gradle 2023-08-21 01:42:39 +02:00
Robinson db0be638b4
Moved byte array utilities to byteUtils project 2023-08-21 01:41:15 +02:00
8 changed files with 61 additions and 340 deletions

View File

@ -21,13 +21,6 @@
Lightweight Java Game Library Project
Riven
- Modified hex conversion utility methods -
[The Apache Software License, Version 2.0]
https://git.dorkbox.com/dorkbox/Utilities
https://netty.io
Copyright 2014
The Netty Project
- Retrofit - A type-safe HTTP client for Android and Java
[The Apache Software License, Version 2.0]
https://github.com/square/retrofit

View File

@ -17,7 +17,7 @@ Maven Info
<dependency>
<groupId>com.dorkbox</groupId>
<artifactId>Utilities</artifactId>
<version>1.45</version>
<version>1.46</version>
</dependency>
</dependencies>
```
@ -27,7 +27,7 @@ Gradle Info
```
dependencies {
...
compile "com.dorkbox:Utilities:1.45"
compile "com.dorkbox:Utilities:1.46"
}
```

View File

@ -24,7 +24,7 @@ gradle.startParameter.showStacktrace = ShowStacktrace.ALWAYS // always show th
plugins {
id("com.dorkbox.GradleUtils") version "3.17"
id("com.dorkbox.Licensing") version "2.24"
id("com.dorkbox.Licensing") version "2.26"
id("com.dorkbox.VersionUpdate") version "2.8"
id("com.dorkbox.GradlePublish") version "1.18"
@ -35,7 +35,7 @@ object Extras {
// set for the project
const val description = "Utilities for use within Java projects"
const val group = "com.dorkbox"
const val version = "1.45"
const val version = "1.46"
// set as project.ext
const val name = "Utilities"
@ -75,12 +75,6 @@ licensing {
author("Riven")
}
extra("Modified hex conversion utility methods", License.APACHE_2) {
url(Extras.url)
url("https://netty.io")
copyright(2014)
author("The Netty Project")
}
extra("Retrofit", License.APACHE_2) {
copyright(2020)
description("A type-safe HTTP client for Android and Java")
@ -142,8 +136,6 @@ dependencies {
// api("org.slf4j:slf4j-api:2.0.7")
compileOnly("com.fasterxml.uuid:java-uuid-generator:4.1.0")
// api "com.koloboke:koloboke-api-jdk8:1.0.0"
// runtime "com.koloboke:koloboke-impl-jdk8:1.0.0"

Binary file not shown.

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

12
gradlew vendored Normal file → Executable file
View File

@ -55,7 +55,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
@ -80,10 +80,10 @@ do
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
@ -143,12 +143,16 @@ fi
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac

1
gradlew.bat vendored
View File

@ -26,6 +26,7 @@ if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%

View File

@ -15,7 +15,6 @@
*/
package dorkbox.util
import dorkbox.os.OS.LINE_SEPARATOR
import java.io.ByteArrayOutputStream
import java.io.IOException
import java.io.InputStream
@ -27,7 +26,7 @@ object Sys {
/**
* Gets the version number.
*/
val version = "1.45"
val version = "1.46"
init {
// Add this project to the updates system, which verifies this class + UUID + version information
@ -39,52 +38,7 @@ object Sys {
const val MEGABYTE = 1024 * KILOBYTE
const val GIGABYTE = 1024 * MEGABYTE
const val TERABYTE = 1024L * GIGABYTE
val HEX_CHARS = charArrayOf('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F')
fun convertStringToChars(string: String): CharArray {
val charArray = string.toCharArray()
eraseString(string)
return charArray
}
fun eraseString(string: String?) {
// You can change the value of the inner char[] using reflection.
//
// You must be careful to either change it with an array of the same length,
// or to also update the count field.
//
// If you want to be able to use it as an entry in a set or as a value in map,
// you will need to recalculate the hash code and set the value of the hashCode field.
try {
val valueField = String::class.java.getDeclaredField("value")
valueField.isAccessible = true
val chars = valueField[string] as CharArray
Arrays.fill(chars, '*') // asterisk it out in case of GC not picking up the old char array.
valueField[string] = CharArray(0) // replace it.
// set count to 0
try {
// newer versions of java don't have this field
val countField = String::class.java.getDeclaredField("count")
countField.isAccessible = true
countField[string] = 0
} catch (ignored: Exception) {
}
// set hash to 0
val hashField = String::class.java.getDeclaredField("hash")
hashField.isAccessible = true
hashField[string] = 0
} catch (e: SecurityException) {
e.printStackTrace()
} catch (e: NoSuchFieldException) {
e.printStackTrace()
} catch (e: IllegalArgumentException) {
e.printStackTrace()
} catch (e: IllegalAccessException) {
e.printStackTrace()
}
}
/**
* FROM: https://www.cqse.eu/en/blog/string-replace-performance/
@ -245,6 +199,7 @@ object Sys {
*
* @return "" if there is no extension
*/
@Deprecated("Use kotlin")
fun getExtension(fileName: String): String {
val dot = fileName.lastIndexOf('.')
return if (dot > -1) {
@ -254,10 +209,10 @@ object Sys {
}
}
/**
* Convert the contents of the input stream to a byte array.
*/
@Deprecated("Use kotlin")
@Throws(IOException::class)
fun getBytesFromStream(inputStream: InputStream): ByteArray {
val baos = ByteArrayOutputStream(8192)
@ -271,6 +226,7 @@ object Sys {
return baos.toByteArray()
}
@Deprecated("Use kotlin")
@JvmOverloads
fun copyBytes(src: ByteArray, position: Int = 0): ByteArray {
val length = src.size - position
@ -279,6 +235,7 @@ object Sys {
return b
}
@Deprecated("Use kotlin")
fun concatBytes(vararg arrayBytes: ByteArray): ByteArray {
var length = 0
for (bytes in arrayBytes) {
@ -292,272 +249,46 @@ object Sys {
}
return concatBytes
}
@JvmOverloads
fun bytesToHex(bytes: ByteArray, startPosition: Int = 0, length: Int = bytes.size, padding: Boolean = false): String {
val endPosition = startPosition + length
return if (padding) {
val hexString = CharArray(3 * length)
var j = 0
for (i in startPosition until endPosition) {
hexString[j++] = HEX_CHARS[bytes[i].toInt() and 0xF0 shr 4]
hexString[j++] = HEX_CHARS[bytes[i].toInt() and 0x0F]
hexString[j++] = ' '
}
String(hexString)
} else {
val hexString = CharArray(2 * length)
var j = 0
for (i in startPosition until endPosition) {
hexString[j++] = HEX_CHARS[bytes[i].toInt() and 0xF0 shr 4]
hexString[j++] = HEX_CHARS[bytes[i].toInt() and 0x0F]
}
String(hexString)
}
}
/**
* Converts an ASCII character representing a hexadecimal
* value into its integer equivalent.
*/
fun hexByteToInt(b: Byte): Int {
return when (b.toInt()) {
'0'.code -> 0
'1'.code -> 1
'2'.code -> 2
'3'.code -> 3
'4'.code -> 4
'5'.code -> 5
'6'.code -> 6
'7'.code -> 7
'8'.code -> 8
'9'.code -> 9
'A'.code, 'a'.code -> 10
'B'.code, 'b'.code -> 11
'C'.code, 'c'.code -> 12
'D'.code, 'd'.code -> 13
'E'.code, 'e'.code -> 14
'F'.code, 'f'.code -> 15
else -> throw IllegalArgumentException("Error decoding byte")
}
}
/**
* Converts an ASCII character representing a hexadecimal
* value into its integer equivalent.
*/
fun hexCharToInt(b: Char): Int {
return when (b) {
'0' -> 0
'1' -> 1
'2' -> 2
'3' -> 3
'4' -> 4
'5' -> 5
'6' -> 6
'7' -> 7
'8' -> 8
'9' -> 9
'A', 'a' -> 10
'B', 'b' -> 11
'C', 'c' -> 12
'D', 'd' -> 13
'E', 'e' -> 14
'F', 'f' -> 15
else -> throw IllegalArgumentException("Error decoding byte")
}
}
/**
* A 4-digit hex result.
*/
fun hex4(c: Char, sb: StringBuilder) {
sb.append(HEX_CHARS[c.code and 0xF000 shr 12])
sb.append(HEX_CHARS[c.code and 0x0F00 shr 8])
sb.append(HEX_CHARS[c.code and 0x00F0 shr 4])
sb.append(HEX_CHARS[c.code and 0x000F])
}
/**
* Returns a string representation of the byte array as a series of
* hexadecimal characters.
*
* @param bytes byte array to convert
* @return a string representation of the byte array as a series of
* hexadecimal characters
*/
fun toHexString(bytes: ByteArray): String {
val hexString = CharArray(2 * bytes.size)
var j = 0
for (i in bytes.indices) {
hexString[j++] = HEX_CHARS[bytes[i].toInt() and 0xF0 shr 4]
hexString[j++] = HEX_CHARS[bytes[i].toInt() and 0x0F]
}
return String(hexString)
}
/**
* from netty 4.1, apache 2.0, https://netty.io
*/
fun hexToByte(s: CharSequence, pos: Int): Byte {
val hi = hexCharToInt(s[pos])
val lo = hexCharToInt(s[pos + 1])
require(!(hi == -1 || lo == -1)) {
String.format(
"invalid hex byte '%s' at index %d of '%s'", s.subSequence(pos, pos + 2), pos, s
)
}
return ((hi shl 4) + lo).toByte()
}
/**
* Decodes a string with [hex dump](http://en.wikipedia.org/wiki/Hex_dump)
*
* @param hex a [CharSequence] which contains the hex dump
*/
fun hexToBytes(hex: CharSequence): ByteArray {
return hexToBytes(hex, 0, hex.length)
}
/**
* Decodes part of a string with [hex dump](http://en.wikipedia.org/wiki/Hex_dump)
*
* from netty 4.1, apache 2.0, https://netty.io
*
* @param hexDump a [CharSequence] which contains the hex dump
* @param fromIndex start of hex dump in `hexDump`
* @param length hex string length
*/
fun hexToBytes(hexDump: CharSequence, fromIndex: Int, length: Int): ByteArray {
require(!(length < 0 || length and 1 != 0)) { "length: $length" }
if (length == 0) {
return ByteArray(0)
}
val bytes = ByteArray(length ushr 1)
var i = 0
while (i < length) {
bytes[i ushr 1] = hexToByte(hexDump, fromIndex + i)
i += 2
}
return bytes
}
fun encodeStringArray(array: List<String>): ByteArray {
var length = 0
for (s in array) {
val bytes = s.toByteArray()
length += bytes.size
}
if (length == 0) {
return ByteArray(0)
}
val bytes = ByteArray(length + array.size)
length = 0
for (s in array) {
val sBytes = s.toByteArray()
System.arraycopy(sBytes, 0, bytes, length, sBytes.size)
length += sBytes.size
bytes[length++] = 0x01.toByte()
}
return bytes
}
fun decodeStringArray(bytes: ByteArray): ArrayList<String> {
val length = bytes.size
var position = 0
val token = 0x01.toByte()
val list = ArrayList<String>(0)
var last = 0
while (last + position < length) {
val b = bytes[last + position++]
if (b == token) {
val xx = ByteArray(position - 1)
System.arraycopy(bytes, last, xx, 0, position - 1)
list.add(String(xx))
last += position
position = 0
}
}
return list
}
@JvmOverloads
fun printArrayRaw(bytes: ByteArray, lineLength: Int = 0): String {
return if (lineLength > 0) {
val length = bytes.size
val comma = length - 1
val builder = StringBuilder(length + length / lineLength)
for (i in 0 until length) {
builder.append(bytes[i].toInt())
if (i < comma) {
builder.append(",")
}
if (i > 0 && i % lineLength == 0) {
builder.append(LINE_SEPARATOR)
}
}
builder.toString()
} else {
val length = bytes.size
val comma = length - 1
val builder = StringBuilder(length + length)
for (i in 0 until length) {
builder.append(bytes[i].toInt())
if (i < comma) {
builder.append(",")
}
}
builder.toString()
}
}
@JvmOverloads
fun printArray(bytes: ByteArray, length: Int = bytes.size, includeByteCount: Boolean = true) {
printArray(bytes, 0, length, includeByteCount, 40, null)
}
@JvmOverloads
fun printArray(
bytes: ByteArray,
inputOffset: Int,
length: Int,
includeByteCount: Boolean,
lineLength: Int = 40,
header: String? = null
) {
val comma = length - 1
var builderLength = length + comma + 2
if (includeByteCount) {
builderLength += 7 + Integer.toString(length).length
}
if (lineLength > 0) {
builderLength += length / lineLength
}
if (header != null) {
builderLength += header.length + 2
}
val builder = StringBuilder(builderLength)
if (header != null) {
builder.append(header).append(LINE_SEPARATOR)
}
if (includeByteCount) {
builder.append("Bytes: ").append(length).append(LINE_SEPARATOR)
}
builder.append("{")
for (i in inputOffset until length) {
builder.append(bytes[i].toInt())
if (i < comma) {
builder.append(",")
}
if (i > inputOffset && lineLength > 0 && i % lineLength == 0) {
builder.append(LINE_SEPARATOR)
}
}
builder.append("}")
System.err.println(builder.toString())
}
}
/**
* Erase the contents of a string, in-memory. This has no effect if the string has been interned.
*/
fun String.eraseString() {
// You can change the value of the inner char[] using reflection.
//
// You must be careful to either change it with an array of the same length,
// or to also update the count field.
//
// If you want to be able to use it as an entry in a set or as a value in map,
// you will need to recalculate the hash code and set the value of the hashCode field.
try {
val valueField = String::class.java.getDeclaredField("value")
valueField.isAccessible = true
val chars = valueField[this] as CharArray
Arrays.fill(chars, '*') // asterisk it out in case of GC not picking up the old char array.
valueField[this] = CharArray(0) // replace it.
// set count to 0
try {
// newer versions of java don't have this field
val countField = String::class.java.getDeclaredField("count")
countField.isAccessible = true
countField[this] = 0
} catch (ignored: Exception) {
}
// set hash to 0
val hashField = String::class.java.getDeclaredField("hash")
hashField.isAccessible = true
hashField[this] = 0
} catch (e: SecurityException) {
e.printStackTrace()
} catch (e: NoSuchFieldException) {
e.printStackTrace()
} catch (e: IllegalArgumentException) {
e.printStackTrace()
} catch (e: IllegalAccessException) {
e.printStackTrace()
}
}