/** * Decodes a value of type {@link Length}. * * @param input * The {@link InputStream} to decode the value from. * @param type * Since all methods use the same name, a default value must be * passed to determine the type of the value to decode. The * {@link Encoding} class provides constants for each type that * is supported. The name of the constant equals the typename, * and is written in capital letters. * @return The decoded value. * @throws NoSuchElementException * Thrown if {@link input} contains no more elements. * @throws NullPointerException * Thrown if {@link input} is <i>null</i>. */ public static Length decode(InputStream input, Length type) throws NoSuchElementException, NullPointerException { Assert.AssertNotNull(input, "input"); int length = input.peek(); input.consume(); if ((length & 0x80) != 0) { long bytes = length & 0x7F; if (bytes == 0) { return Length.INDEFINITE; } else { length = 0; for (/* Nothing */; bytes > 0; bytes--) { length = ((length << 8) | input.peek()); input.consume(); } } } return new Length(length); }
/** * Decodes a value of type {@link Octets}. * * @param input * The {@link InputStream} to decode the value from. * @param encodedLength * The encoded length of this value. * @param type * Since all methods use the same name, a default value must be * passed to determine the type of the value to decode. The * {@link Encoding} class provides constants for each type that * is supported. The name of the constant equals the typename, * and is written in capital letters. * @return The decoded value. * @throws NoSuchElementException * Thrown if {@link input} contains no more elements. * @throws NullPointerException * Thrown if {@link input} is <i>null</i>. */ public static Octets decode(InputStream input, int encodedLength, Octets type) throws NoSuchElementException, NullPointerException { Assert.AssertNotNull(input, "input"); final ArrayList<Integer> data = new ArrayList<Integer>(encodedLength); for (int i = 0; i < encodedLength; ++i) { data.add(input.peek() & 0xFF); input.consume(); } return new Octets(data); }
/** * Decodes a {@link Tag}. Since the length is not required, it must not be passed. * @param input The {@link InputStream to decode the value from. * @param type Since all methods use the same name, a default value must be passed to * determine the type of the value to decode. The {@link Encoding} class provides * constants for each type that is supported. The name of the constant equals * the typename, and is written in capital letters. * @return The decoded value. * @throws NoSuchElementException Thrown if {@link input} contains no more elements. * @throws NullPointerException Thrown if {@link input} is <i>null</i>. */ public static Tag decode(InputStream input, Tag type) throws NoSuchElementException, NullPointerException { Assert.AssertNotNull(input, "input"); final int peek = input.peek(); input.consume(); final int preamble = peek & 0xE0; int number = peek & 0x1F; if (number == 0x1F) number = (int) MultiByte.decode(input); return new Tag(preamble, number); }
/** * Decodes a value of type <i>String</i>. * * @param input * The {@link InputStream} to decode the value from. * @param encodedLength * The encoded length of this value. * @param type * Since all methods use the same name, a default value must be * passed to determine the type of the value to decode. The * {@link Encoding} class provides constants for each type that * is supported. The name of the constant equals the typename, * and is written in capital letters. * @return The decoded value. * @throws NoSuchElementException * Thrown if {@link input} contains no more elements. * @throws NullPointerException * Thrown if {@link input} is <i>null</i>. */ public static String decode(InputStream input, int encodedLength, String type) throws NoSuchElementException, NullPointerException { Assert.AssertNotNull(input, "input"); final byte[] encodedString = new byte[encodedLength]; for (int i = 0; i < encodedLength; ++i) { encodedString[i] = (byte) input.peek(); input.consume(); } try { return new String(encodedString, "UTF-8"); } catch (UnsupportedEncodingException e) { return ""; } }
/** * Decodes a value of type <i>boolean</i>. Since the length is not required, it must not be passed. * @param input The {@link InputStream to decode the value from. * @param type Since all methods use the same name, a default value must be passed to * determine the type of the value to decode. The {@link Encoding} class provides * constants for each type that is supported. The name of the constant equals * the typename, and is written in capital letters. * @return The decoded value. * @throws NoSuchElementException Thrown if {@link input} contains no more elements. * @throws NullPointerException Thrown if {@link input} is <i>null</i>. */ public static boolean decode(InputStream input, boolean type) throws NoSuchElementException, NullPointerException { Assert.AssertNotNull(input, "input"); final int value = input.peek(); return value != 0; }
/** * Decodes an integer value. * * @param input * The {@link InputStream} to read the encoded data from. * @param length * The encoded length of the value to decode. * @param isSigned * Indicates whether the encoded value is signed or unsigned. * @return The decoded value. * @throws NoSuchElementException * Thrown if {@link input} contains no more elements. */ private static long decodeLong(InputStream input, int length, boolean isSigned) throws NoSuchElementException { long value = 0; long read = 0; for (long byteCount = 0; byteCount < length; byteCount++) { read = input.peek(); input.consume(); if (byteCount == 0 && (read & 0x80) != 0 && isSigned) { read -= 0x100; } value = (value << 8) | read; } return value; }
/** * Decodes a value of type <i>long</i>. Since the length is not required, it * must not be passed. * * @param input * The {@link InputStream} to decode the value from. * @param type * Since all methods use the same name, a default value must be * passed to determine the type of the value to decode. The * {@link Encoding} class provides constants for each type that * is supported. The name of the constant equals the typename, * and is written in capital letters. * @return The decoded value. * @throws NoSuchElementException * Thrown if {@link input} contains no more elements. * @throws NullPointerException * Thrown if {@link input} is <i>null</i>. */ public static long decode(InputStream input, int encodedLength, long type) throws NoSuchElementException, NullPointerException { Assert.AssertNotNull(input, "input"); long value = 0; for (int i = 0; i < encodedLength; i++) { final long part = input.peek(); if ((i == 0) && (part == 0x80)) { value = part; value -= 0x100; } else { value = (value << 8) | part; } input.consume(); } return value; }
/** * Decodes a value of type <i>double</i>. * * @param input * The {@link InputStream} to decode the value from. * @param encodedLength * The encoded length of this value. * @param type * Since all methods use the same name, a default value must be * passed to determine the type of the value to decode. The * {@link Encoding} class provides constants for each type that * is supported. The name of the constant equals the typename, * and is written in capital letters. * @return The decoded value. * @throws NoSuchElementException * Thrown if {@link input} contains no more elements. * @throws NullPointerException * Thrown if {@link input} is <i>null</i>. */ public static double decode(InputStream input, int encodedLength, double type) throws NoSuchElementException, NullPointerException { Assert.AssertNotNull(input, "input"); if (encodedLength == 0) { return 0.0; } final int preamble = input.peek(); input.consume(); if (encodedLength == 1) { if (preamble == 0x40) { return Double.POSITIVE_INFINITY; } else if (preamble == 0x41) { return Double.NEGATIVE_INFINITY; } } final int exponentLength = 1 + (preamble & 3); final int sign = (preamble & 0x40); final int ff = (preamble >> 2) & 3; long exponent = decodeLong(input, exponentLength, true); long mantissa = decodeLong(input, encodedLength - exponentLength - 1, false) << ff; while ((mantissa & 0x7FFFF00000000000L) == 0x0) mantissa <<= 8; while ((mantissa & 0x7FF0000000000000L) == 0x0) mantissa <<= 1; mantissa &= 0x0FFFFFFFFFFFFFL; final long bits = ((exponent + 1023) << 52) | mantissa | (sign != 0 ? 0x8000000000000000L : 0); return Double.longBitsToDouble(bits); }