
net.named_data.jndn.encoding.tlv.TlvEncoder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jndn-android-with-async-io Show documentation
Show all versions of jndn-android-with-async-io Show documentation
jNDN is a new implementation of a Named Data Networking client library written in Java. It is wire format compatible with the new NDN-TLV encoding, with NDNx and PARC's CCNx.
/**
* Copyright (C) 2014-2017 Regents of the University of California.
* @author: Jeff Thompson
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
* A copy of the GNU Lesser General Public License is in the file COPYING.
*/
package net.named_data.jndn.encoding.tlv;
import java.nio.ByteBuffer;
import net.named_data.jndn.util.DynamicByteBuffer;
/**
* A TlvEncoder holds an output buffer and has methods to output NDN-TLV.
*/
public class TlvEncoder {
/**
* Create a new TlvEncoder to use a DynamicByteBuffer with the initialCapacity.
* When done, you should call getOutput().
* @param initialCapacity The initial capacity of buffer().
*/
public
TlvEncoder(int initialCapacity)
{
output_ = new DynamicByteBuffer(initialCapacity);
// We will start encoding from the back.
output_.position(output_.limit());
}
/**
* Create a new TlvEncoder with a default DynamicByteBuffer.
* When done, you should call getOutput().
*/
public
TlvEncoder()
{
output_ = new DynamicByteBuffer(16);
// We will start encoding from the back.
output_.position(output_.limit());
}
/**
* Get the number of bytes that have been written to the output. You can
* save this number, write sub TLVs, then subtract the new length from this
* to get the total length of the sub TLVs.
* @return The number of bytes that have been written to the output.
*/
public final int
getLength()
{
return output_.remaining();
}
/**
* Encode varNumber as a VAR-NUMBER in NDN-TLV and write it to the output just
* before getLength() from the back. Advance getLength().
* @param varNumber The non-negative number to encode. This is a Java 32-bit
* int, so this does not support encoding a 64-bit VAR-NUMBER.
*/
public final void
writeVarNumber(int varNumber)
{
if (varNumber < 253) {
int position = output_.setRemainingFromBack(output_.remaining() + 1);
output_.buffer().put(position, (byte)(varNumber & 0xff));
}
else if (varNumber <= 0xffff) {
int position = output_.setRemainingFromBack(output_.remaining() + 3);
output_.buffer().put(position, (byte)253);
output_.buffer().put(position + 1, (byte)((varNumber >> 8) & 0xff));
output_.buffer().put(position + 2, (byte)(varNumber & 0xff));
}
else {
// A Java int is 32 bits so ignore a 64-bit VAR-NUMBER.
int position = output_.setRemainingFromBack(output_.remaining() + 5);
output_.buffer().put(position, (byte)254);
output_.buffer().put(position + 1, (byte)((varNumber >> 24) & 0xff));
output_.buffer().put(position + 2, (byte)((varNumber >> 16) & 0xff));
output_.buffer().put(position + 3, (byte)((varNumber >> 8) & 0xff));
output_.buffer().put(position + 4, (byte)(varNumber & 0xff));
}
}
/**
* Encode the type and length as VAR-NUMBER and write to the output just
* before getLength() from the back. Advance getLength().
* @param type The type of the TLV. This is a Java 32-bit int, so this does
* not support encoding a 64-bit type code.
* @param length The non-negative length of the TLV. This is a Java 32-bit
* int, so this does not support encoding a 64-bit length.
*/
public final void
writeTypeAndLength(int type, int length)
{
// Write backwards.
writeVarNumber(length);
writeVarNumber(type);
}
/**
* Encode value as a non-negative integer and write it to the output just
* before getLength() from the back. Advance getLength(). This does not write
* a type or length for the value.
* @param value The non-negative integer to encode. This is a Java 64-bit
* long, so encoding of 64-bit values is supported (actually 63-bit because
* a Java long is signed).
* @throws Error if the value is negative.
*/
public final void
writeNonNegativeInteger(long value)
{
if (value < 0)
throw new Error("TLV integer value may not be negative");
// Write backwards.
if (value <= 0xffL) {
int position = output_.setRemainingFromBack(output_.remaining() + 1);
output_.buffer().put(position, (byte)(value & 0xff));
}
else if (value <= 0xffffL) {
int position = output_.setRemainingFromBack(output_.remaining() + 2);
output_.buffer().put(position, (byte)((value >> 8) & 0xff));
output_.buffer().put(position + 1, (byte)(value & 0xff));
}
else if (value <= 0xffffffffL) {
int position = output_.setRemainingFromBack(output_.remaining() + 4);
output_.buffer().put(position, (byte)((value >> 24) & 0xff));
output_.buffer().put(position + 1, (byte)((value >> 16) & 0xff));
output_.buffer().put(position + 2, (byte)((value >> 8) & 0xff));
output_.buffer().put(position + 3, (byte)(value & 0xff));
}
else {
int position = output_.setRemainingFromBack(output_.remaining() + 8);
output_.buffer().put(position, (byte)((value >> 56) & 0xff));
output_.buffer().put(position + 1, (byte)((value >> 48) & 0xff));
output_.buffer().put(position + 2, (byte)((value >> 40) & 0xff));
output_.buffer().put(position + 3, (byte)((value >> 32) & 0xff));
output_.buffer().put(position + 4, (byte)((value >> 24) & 0xff));
output_.buffer().put(position + 5, (byte)((value >> 16) & 0xff));
output_.buffer().put(position + 6, (byte)((value >> 8) & 0xff));
output_.buffer().put(position + 7, (byte)(value & 0xff));
}
}
/**
* Write the type, then the length of the encoded value then encode value as a
* non-negative integer and write it to the output just before getLength()
* from the back. Advance getLength().
* @param type The type of the TLV. This is a Java 32-bit int, so this does
* not support encoding a 64-bit type code.
* @param value The non-negative integer to encode. This is a Java 64-bit
* long, so encoding of 64-bit values is supported (actually 63-bit because
* a Java long is signed).
* @throws Error if the value is negative.
*/
public final void
writeNonNegativeIntegerTlv(int type, long value)
{
// Write backwards.
int saveNBytes = output_.remaining();
writeNonNegativeInteger(value);
writeTypeAndLength(type, output_.remaining() - saveNBytes);
}
/**
* If value is negative or null then do nothing, otherwise call
* writeNonNegativeIntegerTlv.
* @param type The type of the TLV. This is a Java 32-bit int, so this does
* not support encoding a 64-bit type code.
* @param value If negative do nothing, otherwise the integer to encode. This
* is a Java 64-bit long, so encoding of 64-bit values is supported (actually
* 63-bit because a Java long is signed).
*/
public final void
writeOptionalNonNegativeIntegerTlv(int type, long value)
{
if (value >= 0)
writeNonNegativeIntegerTlv(type, value);
}
/**
* If value is negative or null then do nothing, otherwise call
* writeNonNegativeIntegerTlv.
* @param type The type of the TLV. This is a Java 32-bit int, so this does
* not support encoding a 64-bit type code.
* @param value If negative do nothing, otherwise use (long)Math.round(value).
*/
public final void
writeOptionalNonNegativeIntegerTlvFromDouble(int type, double value)
{
if (value >= 0.0)
writeNonNegativeIntegerTlv(type, (long)Math.round(value));
}
/**
* Write the buffer from its position() to limit() to the output just
* before getLength() from the back. Advance getLength() of the output. This
* does NOT change buffer.position(). Note that this does not encode a type
* and length; for that see writeBlobTlv.
* @param buffer The byte buffer with the bytes to write. If buffer is null,
* then do nothing.
*/
public final void
writeBuffer(ByteBuffer buffer)
{
if (buffer == null)
return;
// Write backwards.
int position = output_.setRemainingFromBack
(output_.remaining() + buffer.remaining());
int saveBufferValuePosition = buffer.position();
output_.buffer().put(buffer);
// Restore positions after put.
output_.position(position);
buffer.position(saveBufferValuePosition);
}
/**
* Write the type, then the length of the buffer then the buffer value from
* its position() to limit() to the output just before getLength() from the
* back. Advance getLength() of the output. This does NOT change
* value.position().
* @param type The type of the TLV. This is a Java 32-bit int, so this does
* not support encoding a 64-bit type code.
* @param value The byte buffer with the bytes of the blob. If value is null,
* then just write the type and length 0.
*/
public final void
writeBlobTlv(int type, ByteBuffer value)
{
if (value == null) {
writeTypeAndLength(type, 0);
return;
}
// Write backwards.
writeBuffer(value);
writeTypeAndLength(type, value.remaining());
}
/**
* If the byte buffer value is null or value.remaining() is zero then do
* nothing, otherwise call writeBlobTlv.
* @param type The type of the TLV. This is a Java 32-bit int, so this does
* not support encoding a 64-bit type code.
* @param value If null or value.remaining() is zero do nothing, otherwise
* the buffer with the bytes of the blob.
*/
public final void
writeOptionalBlobTlv(int type, ByteBuffer value)
{
if (value != null && value.remaining() > 0)
writeBlobTlv(type, value);
}
/**
* Return a slice of the output buffer up to the current length of the output
* encoding.
* @return A ByteBuffer which shares the same underlying buffer with the
* output buffer.
*/
public final ByteBuffer
getOutput()
{
// The output buffer position is already at the beginning of the encoding.
return output_.buffer().slice();
}
private final DynamicByteBuffer output_;
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy