jcifs.util.Encdec Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jcifs Show documentation
Show all versions of jcifs Show documentation
JCIFS is an Open Source client library that implements the CIFS/SMB networking protocol in 100% Java
/* encdec - encode and decode integers, times, and
* internationalized strings to and from popular binary formats
* http://www.ioplex.com/~miallen/encdec/
* Copyright (c) 2003 Michael B. Allen
*
* The GNU Library General Public License
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA
*/
package jcifs.util;
import java.io.IOException;
import java.util.Date;
import jcifs.SmbConstants;
@SuppressWarnings ( "javadoc" )
public final class Encdec {
private static final long SEC_BETWEEEN_1904_AND_1970 = 2082844800L;
private static final int TIME_1970_SEC_32BE = 1;
private static final int TIME_1970_SEC_32LE = 2;
private static final int TIME_1904_SEC_32BE = 3;
private static final int TIME_1904_SEC_32LE = 4;
private static final int TIME_1601_NANOS_64LE = 5;
private static final int TIME_1601_NANOS_64BE = 6;
private static final int TIME_1970_MILLIS_64BE = 7;
private static final int TIME_1970_MILLIS_64LE = 8;
/**
*
*/
private Encdec () {}
/*
* Encode integers
*/
public static int enc_uint16be ( short s, byte[] dst, int di ) {
dst[ di++ ] = (byte) ( ( s >> 8 ) & 0xFF );
dst[ di ] = (byte) ( s & 0xFF );
return 2;
}
public static int enc_uint32be ( int i, byte[] dst, int di ) {
dst[ di++ ] = (byte) ( ( i >> 24 ) & 0xFF );
dst[ di++ ] = (byte) ( ( i >> 16 ) & 0xFF );
dst[ di++ ] = (byte) ( ( i >> 8 ) & 0xFF );
dst[ di ] = (byte) ( i & 0xFF );
return 4;
}
public static int enc_uint16le ( short s, byte[] dst, int di ) {
dst[ di++ ] = (byte) ( s & 0xFF );
dst[ di ] = (byte) ( ( s >> 8 ) & 0xFF );
return 2;
}
public static int enc_uint32le ( int i, byte[] dst, int di ) {
dst[ di++ ] = (byte) ( i & 0xFF );
dst[ di++ ] = (byte) ( ( i >> 8 ) & 0xFF );
dst[ di++ ] = (byte) ( ( i >> 16 ) & 0xFF );
dst[ di ] = (byte) ( ( i >> 24 ) & 0xFF );
return 4;
}
/*
* Decode integers
*/
public static short dec_uint16be ( byte[] src, int si ) {
return (short) ( ( ( src[ si ] & 0xFF ) << 8 ) | ( src[ si + 1 ] & 0xFF ) );
}
public static int dec_uint32be ( byte[] src, int si ) {
return ( ( src[ si ] & 0xFF ) << 24 ) | ( ( src[ si + 1 ] & 0xFF ) << 16 ) | ( ( src[ si + 2 ] & 0xFF ) << 8 ) | ( src[ si + 3 ] & 0xFF );
}
public static short dec_uint16le ( byte[] src, int si ) {
return (short) ( ( src[ si ] & 0xFF ) | ( ( src[ si + 1 ] & 0xFF ) << 8 ) );
}
public static int dec_uint32le ( byte[] src, int si ) {
return ( src[ si ] & 0xFF ) | ( ( src[ si + 1 ] & 0xFF ) << 8 ) | ( ( src[ si + 2 ] & 0xFF ) << 16 ) | ( ( src[ si + 3 ] & 0xFF ) << 24 );
}
/*
* Encode and decode 64 bit integers
*/
public static int enc_uint64be ( long l, byte[] dst, int di ) {
enc_uint32be((int) ( l & 0xFFFFFFFFL ), dst, di + 4);
enc_uint32be((int) ( ( l >> 32L ) & 0xFFFFFFFFL ), dst, di);
return 8;
}
public static int enc_uint64le ( long l, byte[] dst, int di ) {
enc_uint32le((int) ( l & 0xFFFFFFFFL ), dst, di);
enc_uint32le((int) ( ( l >> 32L ) & 0xFFFFFFFFL ), dst, di + 4);
return 8;
}
public static long dec_uint64be ( byte[] src, int si ) {
long l;
l = dec_uint32be(src, si) & 0xFFFFFFFFL;
l <<= 32L;
l |= dec_uint32be(src, si + 4) & 0xFFFFFFFFL;
return l;
}
public static long dec_uint64le ( byte[] src, int si ) {
long l;
l = dec_uint32le(src, si + 4) & 0xFFFFFFFFL;
l <<= 32L;
l |= dec_uint32le(src, si) & 0xFFFFFFFFL;
return l;
}
/*
* Encode floats
*/
public static int enc_floatle ( float f, byte[] dst, int di ) {
return enc_uint32le(Float.floatToIntBits(f), dst, di);
}
public static int enc_floatbe ( float f, byte[] dst, int di ) {
return enc_uint32be(Float.floatToIntBits(f), dst, di);
}
/*
* Decode floating point numbers
*/
public static float dec_floatle ( byte[] src, int si ) {
return Float.intBitsToFloat(dec_uint32le(src, si));
}
public static float dec_floatbe ( byte[] src, int si ) {
return Float.intBitsToFloat(dec_uint32be(src, si));
}
/*
* Encode and decode doubles
*/
public static int enc_doublele ( double d, byte[] dst, int di ) {
return enc_uint64le(Double.doubleToLongBits(d), dst, di);
}
public static int enc_doublebe ( double d, byte[] dst, int di ) {
return enc_uint64be(Double.doubleToLongBits(d), dst, di);
}
public static double dec_doublele ( byte[] src, int si ) {
return Double.longBitsToDouble(dec_uint64le(src, si));
}
public static double dec_doublebe ( byte[] src, int si ) {
return Double.longBitsToDouble(dec_uint64be(src, si));
}
/*
* Encode times
*/
public static int enc_time ( Date date, byte[] dst, int di, int enc ) {
long t;
switch ( enc ) {
case TIME_1970_SEC_32BE:
return enc_uint32be((int) ( date.getTime() / 1000L ), dst, di);
case TIME_1970_SEC_32LE:
return enc_uint32le((int) ( date.getTime() / 1000L ), dst, di);
case TIME_1904_SEC_32BE:
return enc_uint32be((int) ( ( date.getTime() / 1000L + SEC_BETWEEEN_1904_AND_1970 ) & 0xFFFFFFFF ), dst, di);
case TIME_1904_SEC_32LE:
return enc_uint32le((int) ( ( date.getTime() / 1000L + SEC_BETWEEEN_1904_AND_1970 ) & 0xFFFFFFFF ), dst, di);
case TIME_1601_NANOS_64BE:
t = ( date.getTime() + SmbConstants.MILLISECONDS_BETWEEN_1970_AND_1601 ) * 10000L;
return enc_uint64be(t, dst, di);
case TIME_1601_NANOS_64LE:
t = ( date.getTime() + SmbConstants.MILLISECONDS_BETWEEN_1970_AND_1601 ) * 10000L;
return enc_uint64le(t, dst, di);
case TIME_1970_MILLIS_64BE:
return enc_uint64be(date.getTime(), dst, di);
case TIME_1970_MILLIS_64LE:
return enc_uint64le(date.getTime(), dst, di);
default:
throw new IllegalArgumentException("Unsupported time encoding");
}
}
/*
* Decode times
*/
public static Date dec_time ( byte[] src, int si, int enc ) {
long t;
switch ( enc ) {
case TIME_1970_SEC_32BE:
return new Date(dec_uint32be(src, si) * 1000L);
case TIME_1970_SEC_32LE:
return new Date(dec_uint32le(src, si) * 1000L);
case TIME_1904_SEC_32BE:
return new Date( ( ( dec_uint32be(src, si) & 0xFFFFFFFFL ) - SEC_BETWEEEN_1904_AND_1970 ) * 1000L);
case TIME_1904_SEC_32LE:
return new Date( ( ( dec_uint32le(src, si) & 0xFFFFFFFFL ) - SEC_BETWEEEN_1904_AND_1970 ) * 1000L);
case TIME_1601_NANOS_64BE:
t = dec_uint64be(src, si);
return new Date(t / 10000L - SmbConstants.MILLISECONDS_BETWEEN_1970_AND_1601);
case TIME_1601_NANOS_64LE:
t = dec_uint64le(src, si);
return new Date(t / 10000L - SmbConstants.MILLISECONDS_BETWEEN_1970_AND_1601);
case TIME_1970_MILLIS_64BE:
return new Date(dec_uint64be(src, si));
case TIME_1970_MILLIS_64LE:
return new Date(dec_uint64le(src, si));
default:
throw new IllegalArgumentException("Unsupported time encoding");
}
}
public static int enc_utf8 ( String str, byte[] dst, int di, int dlim ) {
int start = di, ch;
int strlen = str.length();
for ( int i = 0; di < dlim && i < strlen; i++ ) {
ch = str.charAt(i);
if ( ( ch >= 0x0001 ) && ( ch <= 0x007F ) ) {
dst[ di++ ] = (byte) ch;
}
else if ( ch > 0x07FF ) {
if ( ( dlim - di ) < 3 ) {
break;
}
dst[ di++ ] = (byte) ( 0xE0 | ( ( ch >> 12 ) & 0x0F ) );
dst[ di++ ] = (byte) ( 0x80 | ( ( ch >> 6 ) & 0x3F ) );
dst[ di++ ] = (byte) ( 0x80 | ( ( ch >> 0 ) & 0x3F ) );
}
else {
if ( ( dlim - di ) < 2 ) {
break;
}
dst[ di++ ] = (byte) ( 0xC0 | ( ( ch >> 6 ) & 0x1F ) );
dst[ di++ ] = (byte) ( 0x80 | ( ( ch >> 0 ) & 0x3F ) );
}
}
return di - start;
}
public static String dec_utf8 ( byte[] src, int si, int slim ) throws IOException {
char[] uni = new char[slim - si];
int ui, ch;
for ( ui = 0; si < slim && ( ch = src[ si++ ] & 0xFF ) != 0; ui++ ) {
if ( ch < 0x80 ) {
uni[ ui ] = (char) ch;
}
else if ( ( ch & 0xE0 ) == 0xC0 ) {
if ( ( slim - si ) < 2 ) {
break;
}
uni[ ui ] = (char) ( ( ch & 0x1F ) << 6 );
ch = src[ si++ ] & 0xFF;
uni[ ui ] |= ch & 0x3F;
if ( ( ch & 0xC0 ) != 0x80 || uni[ ui ] < 0x80 ) {
throw new IOException("Invalid UTF-8 sequence");
}
}
else if ( ( ch & 0xF0 ) == 0xE0 ) {
if ( ( slim - si ) < 3 ) {
break;
}
uni[ ui ] = (char) ( ( ch & 0x0F ) << 12 );
ch = src[ si++ ] & 0xFF;
if ( ( ch & 0xC0 ) != 0x80 ) {
throw new IOException("Invalid UTF-8 sequence");
}
uni[ ui ] |= ( ch & 0x3F ) << 6;
ch = src[ si++ ] & 0xFF;
uni[ ui ] |= ch & 0x3F;
if ( ( ch & 0xC0 ) != 0x80 || uni[ ui ] < 0x800 ) {
throw new IOException("Invalid UTF-8 sequence");
}
}
else {
throw new IOException("Unsupported UTF-8 sequence");
}
}
return new String(uni, 0, ui);
}
public static String dec_ucs2le ( byte[] src, int si, int slim, char[] buf ) {
int bi;
for ( bi = 0; ( si + 1 ) < slim; bi++, si += 2 ) {
buf[ bi ] = (char) dec_uint16le(src, si);
if ( buf[ bi ] == '\0' ) {
break;
}
}
return new String(buf, 0, bi);
}
}