org.apache.qpid.transport.codec.AbstractDecoder Maven / Gradle / Ivy
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.qpid.transport.codec;
import org.apache.qpid.transport.Binary;
import org.apache.qpid.transport.Range;
import org.apache.qpid.transport.RangeSet;
import org.apache.qpid.transport.RangeSetFactory;
import org.apache.qpid.transport.Struct;
import org.apache.qpid.transport.Type;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* AbstractDecoder
*
* @author Rafael H. Schloming
*/
public abstract class AbstractDecoder implements Decoder
{
private final Map str8cache = new LinkedHashMap()
{
@Override protected boolean removeEldestEntry(Map.Entry me)
{
return size() > 4*1024;
}
};
protected abstract byte doGet();
protected abstract void doGet(byte[] bytes);
protected byte get()
{
return doGet();
}
protected void get(byte[] bytes)
{
doGet(bytes);
}
protected Binary get(int size)
{
byte[] bytes = new byte[size];
get(bytes);
return new Binary(bytes);
}
protected short uget()
{
return (short) (0xFF & get());
}
public short readUint8()
{
return uget();
}
public int readUint16()
{
int i = uget() << 8;
i |= uget();
return i;
}
public long readUint32()
{
long l = uget() << 24;
l |= uget() << 16;
l |= uget() << 8;
l |= uget();
return l;
}
public int readSequenceNo()
{
return (int) readUint32();
}
public long readUint64()
{
long l = 0;
for (int i = 0; i < 8; i++)
{
l |= ((long) (0xFF & get())) << (56 - i*8);
}
return l;
}
public long readDatetime()
{
return readUint64();
}
private static final String decode(byte[] bytes, int offset, int length, String charset)
{
try
{
return new String(bytes, offset, length, charset);
}
catch (UnsupportedEncodingException e)
{
throw new RuntimeException(e);
}
}
private static final String decode(byte[] bytes, String charset)
{
return decode(bytes, 0, bytes.length, charset);
}
public String readStr8()
{
short size = readUint8();
Binary bin = get(size);
String str = str8cache.get(bin);
if (str == null)
{
str = decode(bin.array(), bin.offset(), bin.size(), "UTF-8");
if(bin.hasExcessCapacity())
{
str8cache.put(bin.copy(), str);
}
else
{
str8cache.put(bin, str);
}
}
return str;
}
public String readStr16()
{
int size = readUint16();
byte[] bytes = new byte[size];
get(bytes);
return decode(bytes, "UTF-8");
}
public byte[] readVbin8()
{
int size = readUint8();
byte[] bytes = new byte[size];
get(bytes);
return bytes;
}
public byte[] readVbin16()
{
int size = readUint16();
byte[] bytes = new byte[size];
get(bytes);
return bytes;
}
public byte[] readVbin32()
{
int size = (int) readUint32();
byte[] bytes = new byte[size];
get(bytes);
return bytes;
}
public RangeSet readSequenceSet()
{
int count = readUint16()/8;
switch(count)
{
case 0:
return null;
case 1:
return Range.newInstance(readSequenceNo(), readSequenceNo());
default:
RangeSet ranges = RangeSetFactory.createRangeSet(count);
for (int i = 0; i < count; i++)
{
ranges.add(readSequenceNo(), readSequenceNo());
}
return ranges;
}
}
public RangeSet readByteRanges()
{
throw new Error("not implemented");
}
public UUID readUuid()
{
long msb = readUint64();
long lsb = readUint64();
return new UUID(msb, lsb);
}
public String readContent()
{
throw new Error("Deprecated");
}
public Struct readStruct(int type)
{
Struct st = Struct.create(type);
int width = st.getSizeWidth();
if (width > 0)
{
long size = readSize(width);
if (size == 0)
{
return null;
}
}
if (type > 0)
{
int code = readUint16();
assert code == type;
}
st.read(this);
return st;
}
public Struct readStruct32()
{
long size = readUint32();
if (size == 0)
{
return null;
}
else
{
int type = readUint16();
Struct result = Struct.create(type);
result.read(this);
return result;
}
}
public Map readMap()
{
long size = readUint32();
if (size == 0)
{
return null;
}
long count = readUint32();
if (count == 0)
{
return Collections.EMPTY_MAP;
}
Map result = new LinkedHashMap();
for (int i = 0; i < count; i++)
{
String key = readStr8();
byte code = get();
Type t = getType(code);
Object value = read(t);
result.put(key, value);
}
return result;
}
public List