From 8394014dcc32c4583756a8ed1b3970b5882c7568 Mon Sep 17 00:00:00 2001 From: Andreas Fankhauser hiddenalpha.ch Date: Thu, 29 Dec 2022 00:47:43 +0100 Subject: Bunch of cleanup throughout recently added java stuff --- .../collection/CollectionUtils.java | 6 +-- .../unspecifiedgarbage/format/FormatUtils.java | 54 ++------------------ .../unspecifiedgarbage/json/JsonUtils.java | 8 +-- .../octetstream/ByteChunkOStream.java | 8 +-- .../octetstream/ByteCountOutputStream.java | 8 +-- .../unspecifiedgarbage/octetstream/BytePool.java | 4 +- .../octetstream/CRLFtoLFOutputStream.java | 26 ++++++++-- .../octetstream/CloseNotifyOutputStream.java | 8 ++- .../octetstream/ConcatInputStream.java | 9 ++-- .../unspecifiedgarbage/shell/ShellUtils.java | 15 ++++-- .../unspecifiedgarbage/stream/StreamUtils.java | 26 +++++----- .../unspecifiedgarbage/time/TimeUtils.java | 57 +++++++++++++--------- 12 files changed, 111 insertions(+), 118 deletions(-) diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/collection/CollectionUtils.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/collection/CollectionUtils.java index a75594f..415090f 100644 --- a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/collection/CollectionUtils.java +++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/collection/CollectionUtils.java @@ -13,9 +13,9 @@ public class CollectionUtils { * @param * Type of the elements we are working with. */ - public static boolean contains(T[] haystack, T needle, java.util.function.BiPredicate equals) { - for (T t : haystack) { - if (equals.test(needle, t)) { + public static boolean contains( T[] haystack, T needle, java.util.function.BiPredicate equals ){ + for( T t : haystack ){ + if( equals.test(needle, t) ){ return true; } } diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/format/FormatUtils.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/format/FormatUtils.java index bd39e40..e156eb8 100644 --- a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/format/FormatUtils.java +++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/format/FormatUtils.java @@ -1,54 +1,6 @@ package ch.hiddenalpha.unspecifiedgarbage.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; - if (val == 0) return "0"; - switch (ndig) { - case 1: exp = 1; limit = 1e4F; break; - case 2: exp = 10; limit = 1e6F; break; - case 3: exp = 100; limit = 1e7F; break; - case 4: exp = 1000; limit = 1e8F; break; - case 5: exp = 10000; limit = 1e9F; break; - case 6: exp = 100000; limit = 1e10F; break; - case 7: exp = 1000000; limit = 1e11F; break; - default: throw new IllegalArgumentException("ndig " + ndig + " not in expected range 1..7"); - } - if (val >= exp && val <= limit) { - // Just print as an int. - return String.valueOf((int) val); - } else { - String fmt; - switch (ndig) { // Select an appropriate format. - case 1: fmt = "%.1g"; break; - case 2: fmt = "%.2g"; break; - case 3: fmt = "%.3g"; break; - case 4: fmt = "%.4g"; break; - case 5: fmt = "%.5g"; break; - case 6: fmt = "%.6g"; break; - case 7: fmt = "%.7g"; break; - default: throw new IllegalArgumentException("ndig " + ndig + " not in expected range 1..7"); - } - return String.format(fmt, val).replace(',', '.').replace("'", ""); - } - } - -} +/** Obsolete: This class did migrate to "xtra4j" */ +@Deprecated +public class FormatUtils {} diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/json/JsonUtils.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/json/JsonUtils.java index c8be86a..f860b85 100644 --- a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/json/JsonUtils.java +++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/json/JsonUtils.java @@ -24,18 +24,18 @@ public class JsonUtils { */ public static , JsonNode, K, V> - Map decodeMap(TreeToValueFunc treeToValueFunc, JsonNode mapNode, Class keyType, Class valueType) throws IOException { + Map decodeMap( TreeToValueFunc treeToValueFunc, JsonNode mapNode, Class keyType, Class valueType ) throws IOException { final Map envVars; - if (mapNode == null) { + if( mapNode == null ){ envVars = new LinkedHashMap<>(); - } else { + }else{ envVars = treeToValueFunc.treeToValue(mapNode, Map.class); } return envVars; } public static interface ObjectCodecIface { - Value treeToValue(TreeNode input, Class returnType) throws IOException; + Value treeToValue( TreeNode input, Class returnType ) throws IOException; } diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/ByteChunkOStream.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/ByteChunkOStream.java index 04688d6..49959fc 100644 --- a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/ByteChunkOStream.java +++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/ByteChunkOStream.java @@ -38,8 +38,8 @@ public class ByteChunkOStream extends OutputStream { len -= appendedBytes; }else if( remainingBytes == 0 ){ break; // Done :) - }else { - throw new UnsupportedOperationException("Huh?!? why is remainingBytes " + remainingBytes + "?"); + }else{ + throw new UnsupportedOperationException("Huh?!? why is remainingBytes "+ remainingBytes +"?"); } } } @@ -117,11 +117,11 @@ public class ByteChunkOStream extends OutputStream { /** Inspired by {@link java.util.function.Consumer} */ public static interface ChunkHandler { - void accept(byte[] bytes) throws IOException; + void accept( byte[] bytes ) throws IOException; } - /** Inspired by {@link Runnable#run()} */ + /** Inspired by {@link java.util.function.Runnable#run()} */ public static interface EndHandler { void run() throws IOException; } diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/ByteCountOutputStream.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/ByteCountOutputStream.java index 006ea6b..8e2b47f 100644 --- a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/ByteCountOutputStream.java +++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/ByteCountOutputStream.java @@ -31,13 +31,9 @@ public class ByteCountOutputStream extends OutputStream { } @Override - public void flush() throws IOException { - origin.flush(); - } + public void flush() throws IOException { origin.flush(); } @Override - public void close() throws IOException { - origin.close(); - } + public void close() throws IOException { origin.close(); } } diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/BytePool.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/BytePool.java index 4a619da..b6c8131 100644 --- a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/BytePool.java +++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/BytePool.java @@ -91,7 +91,7 @@ public class BytePool { long amountLong = oldVal - newVal; this.amount.set((int) amountLong); if( this.amount.get() != amountLong ){ - throw new RuntimeException("A moron just tried to allocate " + amountLong + " bytes (more than INT_MAX)"); + throw new RuntimeException("A moron just tried to allocate "+ amountLong +" bytes (more than INT_MAX)"); } } @@ -107,7 +107,7 @@ public class BytePool { * // Don't know exactly how much we need. Make a guess.
* allocdBytes = pool.alloc(42);
* int actuallyNeeded = source.read(buf, 0, allocdBytes.getAmount());
- * // Now we know exactly how much we need and can free the rest.
+ * // Now we know exactly how much we need and can release the rest.
* allocdBytes.shrinkTo(actuallyNeeded);
* */ diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/CRLFtoLFOutputStream.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/CRLFtoLFOutputStream.java index 75b1a9f..465491e 100644 --- a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/CRLFtoLFOutputStream.java +++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/CRLFtoLFOutputStream.java @@ -4,6 +4,9 @@ import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; +import org.slf4j.ILoggerFactory; +import org.slf4j.Logger; + /** * Filter to fix broken newlines. @@ -11,6 +14,7 @@ import java.io.OutputStream; public class CRLFtoLFOutputStream extends FilterOutputStream { private static final int EMPTY = -42; + private final Logger log; private int previous = EMPTY; /** @@ -18,7 +22,16 @@ public class CRLFtoLFOutputStream extends FilterOutputStream { * Destination where the result will be written to. */ public CRLFtoLFOutputStream( OutputStream dst ) { + this(dst, null); + } + + /** + * @param dst + * Destination where the result will be written to. + */ + public CRLFtoLFOutputStream( OutputStream dst, ILoggerFactory lf ) { super(dst); + this.log = (lf == null) ? null : lf.getLogger(CRLFtoLFOutputStream.class.getName()); } @Override @@ -27,7 +40,7 @@ public class CRLFtoLFOutputStream extends FilterOutputStream { // This allows us to assign special meanings to those values internally (eg our // 'EMPTY' value). For this to work, we clear the high bits to not get confused // just in case someone really passes such values. - current = current & 0xFF; + current &= 0xFF; if( previous == '\r' && current == '\n' ){ // Ignore the CR and only write the LF. @@ -43,14 +56,21 @@ public class CRLFtoLFOutputStream extends FilterOutputStream { } } + // TODO we should override this. + //@Override + //public void write( byte[] buf, int off, int len ) throws IOException { + // throw new UnsupportedOperationException("TODO impl");/*TODO*/ + //} + @Override public void flush() throws IOException { if( previous == '\r' ){ - //log.warn("Have to flush a CR byte without knowing if the next byte might be a LF"); + log.debug("Have to flush a CR byte without knowing if the next byte might be a LF"); } if( previous != EMPTY ){ - super.write(previous); + int tmp = previous; previous = EMPTY; + super.write(tmp); } super.flush(); } diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/CloseNotifyOutputStream.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/CloseNotifyOutputStream.java index 2e19c52..a8d6eea 100644 --- a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/CloseNotifyOutputStream.java +++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/CloseNotifyOutputStream.java @@ -17,9 +17,9 @@ public class CloseNotifyOutputStream extends FilterOutputStream { private final Runnable onClose; private final AtomicBoolean isFired = new AtomicBoolean(false); - public CloseNotifyOutputStream(OutputStream out, Runnable onClose) { + public CloseNotifyOutputStream( OutputStream out, Runnable onClose ){ super(out); - if(true) throw new UnsupportedOperationException("TODO need to delegate close call");/*TODO*/ + if( true ) throw new UnsupportedOperationException("TODO need to delegate close call");/*TODO*/ this.onClose = requireNonNull(onClose); } @@ -28,6 +28,10 @@ public class CloseNotifyOutputStream extends FilterOutputStream { if (!isFired.getAndSet(true)) { onClose.run(); } + // TODO Need to delegate to filtered stream. + // Properly delegating requires to propery handle all the + // special cases around exceptions. See also + // CloseNotifyInputStream which does a similar task. } } diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/ConcatInputStream.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/ConcatInputStream.java index 819e6da..8c89fc0 100644 --- a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/ConcatInputStream.java +++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/ConcatInputStream.java @@ -57,12 +57,13 @@ public class ConcatInputStream extends InputStream { public void close() throws IOException { // Close all remaining sources. Exception firstException = null; - for( int i = iSrc; i < sources.length; ++i ){ + for( int i = iSrc ; i < sources.length ; ++i ){ try{ sources[i].close(); }catch( IOException|RuntimeException ex ){ if( firstException == null ){ - // Track the exception. But we need to close the remaining ones. + // Track the exception. But we have to close the + // remaining streams regardless of early exceptions. firstException = ex; }else if( firstException != ex ){ firstException.addSuppressed(ex); @@ -72,7 +73,7 @@ public class ConcatInputStream extends InputStream { sources = null; // Allow GC // Bubble exception if we had any. if( firstException instanceof RuntimeException ){ - throw (RuntimeException) firstException; + throw (RuntimeException)firstException; }else if( firstException != null ){ throw (IOException)firstException; } @@ -83,6 +84,8 @@ public class ConcatInputStream extends InputStream { InputStream oldSrc = sources[iSrc]; sources[iSrc] = null; iSrc += 1; + // Calling close as last step to prevent trouble with our + // state as it potentially could throw. oldSrc.close(); } } diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/shell/ShellUtils.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/shell/ShellUtils.java index 5e2aff2..6c903ec 100644 --- a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/shell/ShellUtils.java +++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/shell/ShellUtils.java @@ -6,10 +6,13 @@ public class ShellUtils { /** * Escapes the string so we can use the result in a * double-quoted shell string. - * But keeps parameter expansion alive. + * But keeps parameter expansion + * alive. * Example usage: - * String path = "pâth \\with ${varToResolve} but a|so €vil chars like spaces, p|pes or * asterisk"; - * cmd = "ls '"+ escapeForSnglQuotEverything(path) +"'"; + * + * String path = "pâth \\with ${varToResolve} but a|so €vil chars like spaces, p|pes or * asterisk";
+ * cmd = "ls \""+ escapeForDblQuotButParams(path) +"\"";
+ *
*/ public static String escapeForDblQuotButParams( String s ){ s = s.replace("\\", "\\\\"); @@ -23,8 +26,10 @@ public class ShellUtils { * Escapes the string so we can use result in a * single-quoted shell string. * Example usage: - * String path = "pâth \\with ${MustNotResolveThisVar} and a|so €vil chars like spaces, p|pes or * asterisk"; - * cmd = "ls '"+ escapeForSnglQuotEverything(path) +"'"; + * + * String path = "pâth \\with ${MustNotResolveThisVar} and a|so €vil chars like spaces, p|pes or * asterisk";
+ * cmd = "ls '"+ escapeForSnglQuotEverything(path) +"'";
+ *
*/ public static String escapeForSingleQuotEverything( String s ){ // Cited from "Single-Quotes" in "https://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html": diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/stream/StreamUtils.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/stream/StreamUtils.java index 696d4d3..7d712ee 100644 --- a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/stream/StreamUtils.java +++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/stream/StreamUtils.java @@ -1,5 +1,8 @@ package ch.hiddenalpha.unspecifiedgarbage.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; @@ -11,28 +14,29 @@ public class StreamUtils { /** * Copies 'is' to 'os' until end of 'is' is reached. (Blocking) + * + *

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.

+ * * @return * Count of copied bytes. */ - public static long copy(java.io.InputStream is, java.io.OutputStream os) throws java.io.IOException { - byte[] buffer = new byte[1024]; + public static long copy( java.io.InputStream is, java.io.OutputStream os ) throws java.io.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 ); + os.write(buffer, 0, readLen); } return totalBytes; } - public static java.util.Iterator map(java.util.Iterator src , java.util.function.Function mapper) { + public static java.util.Iterator map( java.util.Iterator src , java.util.function.Function mapper ) { return new Iterator() { - @Override public boolean hasNext() { - return src.hasNext(); - } - @Override public DST next() { - return mapper.apply(src.next()); - } + @Override public boolean hasNext() { return src.hasNext(); } + @Override public DST next() { return mapper.apply(src.next()); } }; } @@ -41,7 +45,7 @@ public class StreamUtils { return t -> seen.add(keyExtractor.apply(t)); } - public static Predicate not(Predicate p){ + public static Predicate not( Predicate p ){ return e -> !p.test(e); } diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/time/TimeUtils.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/time/TimeUtils.java index ddb1c13..2bb1bfb 100644 --- a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/time/TimeUtils.java +++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/time/TimeUtils.java @@ -4,17 +4,17 @@ package ch.hiddenalpha.unspecifiedgarbage.time; public class TimeUtils { /** - * Delegates to {@link #nanosToEpochMillis(long, long, long)} and assumes - * that the 'nanos' value was measure in the same JVM process as this call - * here occurs and is not too long back. + * 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) { + public static long nanosToEpochMillis( long nanos ){ return nanosToEpochMillis(nanos, System.nanoTime(), System.currentTimeMillis()); } - public static long nanosToEpochMillis(long nanos, long referenceNanos, long referenceEpochMs) { + 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)) { + if( diffNs < (Long.MIN_VALUE >> 1) || diffNs > (Long.MAX_VALUE>>1) ){ // Looks as System.nanoTime() did overflow while measurement. So flip result too. diffNs -= Long.MAX_VALUE; } @@ -22,29 +22,38 @@ public class TimeUtils { } /** - * Computers cannot represent all existing integers. Due to how integers - * are represented in computers, they are not infinite but more like a circle. - * Speak when we infinitely increment an integer, it overflows and (usually) - * continues to walk around this (imaginary) circle. + * Find smallest distance assuming integers overflow "like a circle". * - * 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: - * - f(7, 13) = 6 - * - f(-7, +11) = 18 - * - f(LONG_MIN, LONG_MAX) = 1 - * - f(-9223372036854775805, 9223372036854775802) = 9 + * Computers cannot represent all existing integers. Due to how + * integers are represented in computers, they are not infinite but + * more like a circle. Speak when we infinitely increment an + * integer, it overflows and (usually) continues to walk around this + * (imaginary) circle. + * + * 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: + *
    + *
  • f(7, 13) = 6
  • + *
  • f(-7, +11) = 18
  • + *
  • f(LONG_MIN, LONG_MAX) = 1
  • + *
  • f(-9223372036854775805, 9223372036854775802) = 9
  • + *
* * 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: - * long begNs = System.nanoTime(); - * long endNs = System.nanoTime(); - * long durationNs = nanosSmallDiff(begNs, endNs); + * 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: + * + * long begNs = System.nanoTime(); + * long endNs = System.nanoTime(); + * long durationNs = nanosSmallDiff(endNs, begNs); + * * - * WARN: Do NOT use this if your distance can reach (LONG_MAX / 2). Because - * in this case you would get wrong (too small) results. + * WARN: Do NOT use this if your distance can reach (LONG_MAX / 2). + * Because in this case you would get wrong (too small) results. */ - public static long nanosSmallDiff(long a, long b) { + public static long nanosSmallDiff( long a, long b ){ return (a - b >= 0) ? a - b : b - a; } -- cgit v1.1