CdbUtils.java
package sk.iway.iwcm.system.fulltext.cdb;
import java.io.UnsupportedEncodingException;
import java.lang.ref.SoftReference;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.nio.charset.CodingErrorAction;
import java.util.Arrays;
/**
*
* Implementácia kódovania poľa znakov do poľa bajtov CdbUtils.java
*
* @Title webjet7
* @Company Interway s.r.o. (www.interway.sk)
* @Copyright Interway s.r.o. (c) 2001-2011
* @author $Author: jeeff thaber $
* @version $Revision: 1.3 $
* @created Date: 5.5.2011 14:11:19
* @modified $Date: 2004/08/16 06:26:11 $
*/
@SuppressWarnings({"unused", "unchecked", "rawtypes"})
public class CdbUtils
{
private CdbUtils()
{
}
public static final Charset cs = Charset.defaultCharset();
private static ThreadLocal decoder = new ThreadLocal(); //NOSONAR
private static ThreadLocal encoder = new ThreadLocal(); //NOSONAR
private static Object deref(ThreadLocal tl)
{
SoftReference sr = (SoftReference) tl.get();
if (sr == null)
return null;
return sr.get();
}
private static void set(ThreadLocal tl, Object ob)
{
tl.set(new SoftReference(ob));
}
private static byte[] safeTrim(byte[] ba, int len)
{
if (len == ba.length)
return ba;
else
return Arrays.copyOf(ba, len);
}
// Trim the given byte array to the given length
//
@SuppressWarnings("java:S3398")
private static byte[] safeTrim(byte[] ba, int len, Charset cs) {
if (len == ba.length )
return ba;
else
return Arrays.copyOf(ba, len);
}
// Trim the given char array to the given length
//
@SuppressWarnings("java:S3398")
private static char[] safeTrim(char[] ca, int len, Charset cs)
{
if (len == ca.length)
return ca;
else
return Arrays.copyOf(ca, len);
}
private static int scale(int len, float expansionFactor)
{
// We need to perform double, not float, arithmetic; otherwise
// we lose low order bits when len is larger than 2**24.
return (int) (len * (double) expansionFactor);
}
public static byte[] encode(char[] ca, int off, int len)
{
StringEncoder se = (StringEncoder) deref(encoder);
se = new StringEncoder(cs, cs.name());
set(encoder, se);
return se.encode(ca, off, len);
}
public static char[] decode(byte[] ba)
{
StringDecoder sd = (StringDecoder) deref(decoder);
sd = new StringDecoder(cs, cs.name());
set(decoder, sd);
return sd.decode(ba, 0, ba.length);
}
public static char[] decode(byte[] ba, int off, int len)
{
StringDecoder sd = (StringDecoder) deref(decoder);
sd = new StringDecoder(cs, cs.name());
set(decoder, sd);
return sd.decode(ba, off, len);
}
// -- Decoding --
private static class StringDecoder
{
private final String requestedCharsetName;
private final Charset cs;
private final CharsetDecoder cd;
private StringDecoder(Charset cs, String rcn)
{
this.requestedCharsetName = rcn;
this.cs = cs;
this.cd = cs.newDecoder().onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE);
}
char[] decode(byte[] ba, int off, int len)
{
int en = scale(len, cd.maxCharsPerByte());
char[] ca = new char[en];
if (len == 0)
return ca;
cd.reset();
ByteBuffer bb = ByteBuffer.wrap(ba, off, len);
CharBuffer cb = CharBuffer.wrap(ca);
try
{
CoderResult cr = cd.decode(bb, cb, true);
if (!cr.isUnderflow())
cr.throwException();
cr = cd.flush(cb);
if (!cr.isUnderflow())
cr.throwException();
}
catch (CharacterCodingException x)
{
// Substitution is always enabled,
// so this shouldn't happen
throw new Error(x);
}
return safeTrim(ca, cb.position(), cs);
}
}
// -- Encoding --
private static class StringEncoder
{
private Charset cs;
private CharsetEncoder ce;
private final String requestedCharsetName;
private StringEncoder(Charset cs, String rcn)
{
this.requestedCharsetName = rcn;
this.cs = cs;
this.ce = cs.newEncoder().onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE);
}
/*String charsetName()
{
if (cs instanceof HistoricallyNamedCharset)
return ((HistoricallyNamedCharset) cs).historicalName();
return cs.name();
}*/
final String requestedCharsetName()
{
return requestedCharsetName;
}
byte[] encode(char[] ca, int off, int len)
{
int en = scale(len, ce.maxBytesPerChar());
byte[] ba = new byte[en];
if (len == 0)
return ba;
ce.reset();
ByteBuffer bb = ByteBuffer.wrap(ba);
CharBuffer cb = CharBuffer.wrap(ca, off, len);
try
{
CoderResult cr = ce.encode(cb, bb, true);
if (!cr.isUnderflow())
cr.throwException();
cr = ce.flush(bb);
if (!cr.isUnderflow())
cr.throwException();
}
catch (CharacterCodingException x)
{
// Substitution is always enabled,
// so this shouldn't happen
throw new Error(x);
}
return safeTrim(ba, bb.position(), cs);
}
}
}