diff options
author | Andreas Fankhauser hiddenalpha.ch | 2022-12-21 00:10:40 +0100 |
---|---|---|
committer | Andreas Fankhauser hiddenalpha.ch | 2022-12-21 00:10:40 +0100 |
commit | e3450fca17fdeb5f64df260b224916b6b2cbdb73 (patch) | |
tree | 4421f334eaff74383e6807a1992a6601a4fb2869 | |
parent | 449b4d73f317d18b5fbd8e3382a9d4708af0044f (diff) | |
download | xtra4j-e3450fca17fdeb5f64df260b224916b6b2cbdb73.zip xtra4j-e3450fca17fdeb5f64df260b224916b6b2cbdb73.tar.gz |
Add misc setup files. Add few java classes.
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | LICENSE.txt | 14 | ||||
-rw-r--r-- | README.md | 7 | ||||
-rw-r--r-- | pom.xml | 24 | ||||
-rw-r--r-- | xtra4j-misc/pom.xml | 18 | ||||
-rw-r--r-- | xtra4j-misc/src/main/java/ch/hiddenalpha/xtra4j/format/FormatUtils.java | 49 | ||||
-rw-r--r-- | xtra4j-misc/src/main/java/ch/hiddenalpha/xtra4j/stream/StreamUtils.java | 58 | ||||
-rw-r--r-- | xtra4j-misc/src/main/java/ch/hiddenalpha/xtra4j/time/TimeUtils.java | 61 |
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. + @@ -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; + } + +} |