/*******************************************************************************
* Copyright (c) 2005-2011, G. Weirich and Elexis
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* G. Weirich - initial implementation
*
*******************************************************************************/
package ch.rgw.tools;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
/**
* Einige Utilities für Zahlen, Integer IO und Konversionen
*/
public class IntTool {
public static String Version(){
return "1.1.1";
}
/**
* Schreibt ein Long als Array von Bytes
*
* @param arr
* Zielarray
* @param offset
* Offset im Array, ab dem geschrieben werden soll
* @param value
* Wert, der geschrieben werden soll
* @return Neuer Offset zum Schreiben des nächsten Werts
*/
public static int toBytes(byte[] arr, int offset, long value){
int low = (int) (value & 0xffffffff);
offset = toBytes(arr, offset, low);
int hi = (int) ((value >> 32) & 0xffffffff);
offset = toBytes(arr, offset, hi);
return offset;
}
/**
* Schreibt einen Integer als Array von Bytes
*
* @param arr
* Zielarray
* @param offset
* Offset im Array, ab dem geschrieben werden soll
* @param value
* Wert, der geschrieben werden soll
* @return Neuer Offset zum Schreiben des nächsten Werts
*/
public static int toBytes(byte[] arr, int offset, int value){
int b1 = value & 0xff;
int b2 = (value >> 8) & 0xff;
int b3 = (value >> 16) & 0xff;
int b4 = (value >> 24) & 0xff;
arr[offset++] = (byte) (b1); // 8
arr[offset++] = (byte) (b2); // 16
arr[offset++] = (byte) (b3); // 24
arr[offset++] = (byte) (b4); // 32
return offset;
}
/** Schreibt einen Integer als Bytefolge in einen OutputStream */
public static void writeInt(int i, OutputStream out) throws IOException{
byte[] arr = new byte[4];
toBytes(arr, 0, i);
out.write(arr);
}
/** Liest einen als Bytefolge abgelegten Integer aus einem InputStream */
public static int readInt(InputStream in) throws IOException{
byte[] arr = new byte[4];
in.read(arr);
return fromBytesInt(arr, 0);
}
/**
* Holt einen als Bytefolge in einem Array abgelegten Long-Wert
*
* @param arr
* Das Quellarray
* @param offset
* Offset innerhalb des Arrays, ab dem gelesen werden soll
* @return Den gelesenen Long Wert
*/
public static long fromBytesLong(byte[] arr, int offset){
int low = fromBytesInt(arr, offset);
long ret = ((long) fromBytesInt(arr, offset + 4)) << 32;
ret |= low;
return ret;
}
/**
* Holt einen als Bytefolge in einem Array abgelegten Integer-Wert
*
* @param arr
* Das Quellarray
* @param offset
* Offset innerhalb des Arrays, ab dem gelesen werden soll
* @return Den gelesenen Integer Wert
*/
public static int fromBytesInt(byte[] arr, int offset){
int b1 = ByteToInt((arr[offset++]));
int b2 = ByteToInt((arr[offset++]));
int b3 = ByteToInt((arr[offset++]));
int b4 = ByteToInt(arr[offset++]);
return b1 + (b2 << 8) + (b3 << 16) + (b4 << 24);
}
/** Wandelt ein Long in einen druckbaren String um */
public static String to_prt(long val){
long num = val;
int flag = 65;
int off = 28;
int siz = 9;
while ((num >> off) == 0) {
off -= 4;
siz--;
}
byte[] res = new byte[siz];
for (int i = 1; off >= 0; off -= 4, i++) {
int nibble = (int) ((num >> off) & 15);
res[i] = (byte) (65 + nibble);
flag++;
}
res[0] = (byte) (flag - 1);
try {
return new String(res, "UTF-8");
} catch (Exception ex) {
ExHandler.handle(ex);
return null;
}
}
/* Holt einen mit to_prt geschriebenen Long zur�ck */
public static long from_prt(String val){
byte[] bytes = null;
try {
bytes = val.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
ExHandler.handle(e);
return 0;
}
int flag = bytes[0] - 65;
int off = 4 * flag;
long ret = 0;
int i = 1;
for (; off >= 0; off -= 4, i++) {
int nibble = bytes[i] - 65;
ret += nibble << off;
}
return ret;
}
/**
* Ergänzt ein Long um eine Prüfsumme und wandelt das ganze in einen leicht abtippbaren String,
* bestehend aus kurzen Zeichenfolgen um
*
* @param num
* die Zahl
* @return der codierte und �berpr�fbare String
*/
public static String envelope(long num){
String s0 = to_prt(num);
byte[] s1;
try {
s1 = s0.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
ExHandler.handle(e);
return null;
}
int l = s1.length;
int chk = 0;
for (int i = 0; i < l; i++) {
chk += s1[i];
if (chk > 255)
chk -= 255;
}
String s2 = to_prt(chk);
String cmb = s0 + s2.substring(1);
cmb = cmb.replaceAll("(-?[^-]{4})", "$1-");
cmb = cmb.replaceFirst("-$", "");
cmb = cmb.toLowerCase();
return cmb;
}
/**
* Holt einen Long-Wert aus einem envelope. Prüft, ob die Prüfsumme korrekt ist.
*
* @param env
* @return
*/
public static long disenvelope(String env){
String in = env.toUpperCase().replaceAll("-", "");
long res = IntTool.from_prt(in);
String cmp = envelope(res);
if (cmp.equals(env)) {
return res;
}
return -1;
}
/** Betrachtet ein byte als unsigned und liefert diesen Wert als Integer zurück */
public static int ByteToInt(byte s){
if (s < 0) {
byte s1 = (byte) (s & (byte) 127);
int s2 = s1;
int s3 = s2 | 128;
return s3;
}
return s;
}
/*
* public static String toHexString(int x) { int hi=x>>16; int lo=x&0x0000ffff; return
* toHexString(hi)+toHexString(lo); }
*/
public static String toHexString(byte x){
int hi = x / 16;
int lo = x - hi;
StringBuffer s = new StringBuffer(2);
s.append(Character.forDigit(hi, 16));
s.append(Character.forDigit(lo, 16));
return s.toString();
}
/** rundet eine Zahl auf definierte Stellen */
public static float round(double val, int stel){
double mult = Math.pow(10, stel);
long zwi = Math.round(val * mult);
return (float) (zwi / 100.0);
}
/** Log10 */
public static double lg(double x){
return Math.log(x) / Math.log(10);
}
}