summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Fankhauser hiddenalpha.ch2022-12-21 00:10:40 +0100
committerAndreas Fankhauser hiddenalpha.ch2022-12-21 00:10:40 +0100
commite3450fca17fdeb5f64df260b224916b6b2cbdb73 (patch)
tree4421f334eaff74383e6807a1992a6601a4fb2869
parent449b4d73f317d18b5fbd8e3382a9d4708af0044f (diff)
downloadxtra4j-e3450fca17fdeb5f64df260b224916b6b2cbdb73.zip
xtra4j-e3450fca17fdeb5f64df260b224916b6b2cbdb73.tar.gz
Add misc setup files. Add few java classes.
-rw-r--r--.gitignore2
-rw-r--r--LICENSE.txt14
-rw-r--r--README.md7
-rw-r--r--pom.xml24
-rw-r--r--xtra4j-misc/pom.xml18
-rw-r--r--xtra4j-misc/src/main/java/ch/hiddenalpha/xtra4j/format/FormatUtils.java49
-rw-r--r--xtra4j-misc/src/main/java/ch/hiddenalpha/xtra4j/stream/StreamUtils.java58
-rw-r--r--xtra4j-misc/src/main/java/ch/hiddenalpha/xtra4j/time/TimeUtils.java61
8 files changed, 233 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..56256e4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+/target/
+/*/target/
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..8f302c9
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,14 @@
+
+Copyright (c) 2022 Andreas Fankhauser
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..2acd66a
--- /dev/null
+++ b/README.md
@@ -0,0 +1,7 @@
+
+xtra4j
+======
+
+Utilities the original author of this library did miss
+in the JDK.
+
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..d97fb24
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>ch.hiddenalpha.xtra4j</groupId>
+ <artifactId>xtra4j-parent</artifactId>
+ <version>0.0.0-SNAPSHOT</version>
+
+ <packaging>pom</packaging>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <maven.compiler.source>8</maven.compiler.source>
+ <maven.compiler.target>8</maven.compiler.target>
+ </properties>
+
+ <modules>
+ <module>xtra4j-misc</module>
+ </modules>
+
+</project>
diff --git a/xtra4j-misc/pom.xml b/xtra4j-misc/pom.xml
new file mode 100644
index 0000000..8172f36
--- /dev/null
+++ b/xtra4j-misc/pom.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>xtra4j-misc</artifactId>
+
+ <parent>
+ <groupId>ch.hiddenalpha.xtra4j</groupId>
+ <artifactId>xtra4j-parent</artifactId>
+ <version>0.0.0-SNAPSHOT</version>
+ </parent>
+
+ <packaging>jar</packaging>
+
+</project>
diff --git a/xtra4j-misc/src/main/java/ch/hiddenalpha/xtra4j/format/FormatUtils.java b/xtra4j-misc/src/main/java/ch/hiddenalpha/xtra4j/format/FormatUtils.java
new file mode 100644
index 0000000..fc10ab2
--- /dev/null
+++ b/xtra4j-misc/src/main/java/ch/hiddenalpha/xtra4j/format/FormatUtils.java
@@ -0,0 +1,49 @@
+package ch.hiddenalpha.xtra4j.format;
+
+
+public class FormatUtils {
+
+ /**
+ * Tries to format 'val' as a small integer. If not possible falls back
+ * to decimal representation. If also not possible, falls back to scientific
+ * notation.
+ *
+ * Handy in cases where we need to "just print that number" without having
+ * stupid amount of nonsense decimal places or bother readers with
+ * scientific notation where "just an int" would perfectly do the job.
+ *
+ * @param val
+ * The number to format.
+ *
+ * @param ndig
+ * How many significant digits to be printed. MUST be in range 1..7.
+ */
+ public static String toStr( float val, int ndig ){
+ int exp;
+ float limit;
+ String fmt;
+ if( val == 0 ){
+ return "0";
+ }
+ switch( ndig ){
+ case 1: exp = 1; limit = 1e4F ; fmt = "%.1g"; break;
+ case 2: exp = 10; limit = 1e6F ; fmt = "%.2g"; break;
+ case 3: exp = 100; limit = 1e7F ; fmt = "%.3g"; break;
+ case 4: exp = 1000; limit = 1e8F ; fmt = "%.4g"; break;
+ case 5: exp = 10000; limit = 1e9F ; fmt = "%.5g"; break;
+ case 6: exp = 100000; limit = 1e10F; fmt = "%.6g"; break;
+ case 7: exp = 1000000; limit = 1e11F; fmt = "%.7g"; break;
+ default: throw new IllegalArgumentException("ndig "+ ndig +" not in expected range 1..7");
+ }
+ if( val >= exp && val <= limit ){
+ // Print simple numbers as int.
+ return String.valueOf((int)val);
+ }else{
+ // Format too large or too small numbers with not wasting too much
+ // space. In addition, fix annoying locale chars as this function is
+ // about printing numbers and not ascii-art.
+ return String.format(fmt, val).replace(',', '.').replace("'", "");
+ }
+ }
+
+}
diff --git a/xtra4j-misc/src/main/java/ch/hiddenalpha/xtra4j/stream/StreamUtils.java b/xtra4j-misc/src/main/java/ch/hiddenalpha/xtra4j/stream/StreamUtils.java
new file mode 100644
index 0000000..7aef622
--- /dev/null
+++ b/xtra4j-misc/src/main/java/ch/hiddenalpha/xtra4j/stream/StreamUtils.java
@@ -0,0 +1,58 @@
+package ch.hiddenalpha.xtra4j.stream;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+
+public class StreamUtils {
+
+ /**
+ * Copies 'is' to 'os' until end of 'is' is reached. (Blocking)
+ *
+ * <p>BTW: Using this function makes no longer sense in projects using java
+ * 9 or later. Just use {@link java.io.InputStream#transferTo(java.io.OutputStream)}
+ * instead.</p>
+ *
+ * @return
+ * Count of copied bytes.
+ */
+ public static long copy( InputStream is, OutputStream os ) throws IOException {
+ byte[] buffer = new byte[8192];
+ long totalBytes = 0;
+ int readLen;
+ while( -1 != (readLen=is.read(buffer,0,buffer.length)) ){
+ totalBytes += readLen;
+ os.write(buffer, 0, readLen);
+ }
+ return totalBytes;
+ }
+
+ /**
+ * Maps every value flowing through iterator using passed callback.
+ */
+ public static <SRC,DST> Iterator<DST> map( Iterator<SRC> src , Function<SRC,DST> mapper ){
+ return new Iterator<DST>(){
+ @Override public boolean hasNext() { return src.hasNext(); }
+ @Override public DST next() { return mapper.apply(src.next()); }
+ };
+ }
+
+ public static <T> Predicate<T> distinctBy(Function<? super T, ?> keyExtractor) {
+ Set<Object> seen = ConcurrentHashMap.newKeySet();
+ return t -> seen.add(keyExtractor.apply(t));
+ }
+
+ /**
+ * Negates the passed predicate.
+ */
+ public static <T> Predicate<T> not( Predicate<T> p ){
+ return e -> !p.test(e);
+ }
+
+}
diff --git a/xtra4j-misc/src/main/java/ch/hiddenalpha/xtra4j/time/TimeUtils.java b/xtra4j-misc/src/main/java/ch/hiddenalpha/xtra4j/time/TimeUtils.java
new file mode 100644
index 0000000..5bdc975
--- /dev/null
+++ b/xtra4j-misc/src/main/java/ch/hiddenalpha/xtra4j/time/TimeUtils.java
@@ -0,0 +1,61 @@
+package ch.hiddenalpha.xtra4j.time;
+
+import static java.lang.System.*;
+
+
+public class TimeUtils {
+
+ /**
+ * Delegates to {@link #nanosToEpochMillis(long, long, long)} and
+ * assumes that the 'nanos' value was measured in the same JVM
+ * process as this call here occurs and is not too long back.
+ */
+ public static long nanosToEpochMillis( long nanos ){
+ return nanosToEpochMillis(nanos, nanoTime(), currentTimeMillis());
+ }
+
+ public static long nanosToEpochMillis( long nanos, long referenceNanos, long referenceEpochMs ){
+ long diffNs = nanos - referenceNanos;
+ if( diffNs < (Long.MIN_VALUE >> 1) || diffNs > (Long.MAX_VALUE>>1) ){
+ // Looks as System.nanoTime() did overflow while measurement. So
+ // flip result.
+ diffNs -= Long.MAX_VALUE;
+ }
+ return referenceEpochMs + (diffNs / 1_000_000);
+ }
+
+ /**
+ * <p>Find smallest distance assuming integers overflow "like a circle".</p>
+ *
+ * <p>Just imagine integers more like a circle. So when we infinitely
+ * increment an integer, we assume it overflows and continues to walk around
+ * this (imaginary) circle continuing its steps in the far negative range
+ * towards zero again.</p>
+ *
+ * <p>This function takes two of those numbers on this circle and returns
+ * the smallest distance to travel on the circle between them. Here some
+ * examples:</p>
+ * <ul>
+ * <li>f(7, 13) = 6</li>
+ * <li>f(-7, +11) = 18</li>
+ * <li>f(LONG_MIN, LONG_MAX) = 1</li>
+ * <li>f(-9223372036854775805, 9223372036854775802) = 9</li>
+ * </ul>
+ *
+ * <p>This can be handy for example in conjunction with {@link System#nanoTime()}.
+ * Because in case of overflows between measuring begNs and endNs a simple
+ * subtraction would lead to uselessly large results. So we can use it as:</p>
+ * <code>
+ * long begNs = System.nanoTime();<br/>
+ * long endNs = System.nanoTime();<br/>
+ * long durationNs = nanosSmallDiff(endNs, begNs);<br/>
+ * </code>
+ *
+ * <p>WARN: Do NOT use this if your distance can reach (LONG_MAX / 2).
+ * Because in this case you would get wrong (too small) results.</p>
+ */
+ public static long nanosSmallDiff( long a, long b ){
+ return (a - b >= 0) ? a - b : b - a;
+ }
+
+}