All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.jetty.http.compression.NBitStringDecoder Maven / Gradle / Ivy

There is a newer version: 12.1.0.alpha0
Show newest version
//
// ========================================================================
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//

package org.eclipse.jetty.http.compression;

import java.nio.ByteBuffer;

import org.eclipse.jetty.util.CharsetStringBuilder;

/**
 * 

Used to decode string literals as described in RFC7541.

* *

The string literal representation consists of a single bit to indicate whether huffman encoding is used, * followed by the string byte length encoded with the n-bit integer representation also from RFC7541, and * the bytes of the string are directly after this.

* *

Characters which are illegal field-vchar values are replaced with * either ' ' or '?' as described in RFC9110

*/ public class NBitStringDecoder { private final NBitIntegerDecoder _integerDecoder; private final HuffmanDecoder _huffmanBuilder; private final CharsetStringBuilder.Iso88591StringBuilder _builder; private boolean _huffman; private int _count; private int _length; private int _prefix; private State _state = State.PARSING; private enum State { PARSING, LENGTH, VALUE } public NBitStringDecoder() { _integerDecoder = new NBitIntegerDecoder(); _huffmanBuilder = new HuffmanDecoder(); _builder = new CharsetStringBuilder.Iso88591StringBuilder(); } /** * Set the prefix length in of the string representation in bits. * A prefix of 6 means the string representation starts after the first 2 bits. * @param prefix the number of bits in the string prefix. */ public void setPrefix(int prefix) { if (_state != State.PARSING) throw new IllegalStateException(); _prefix = prefix; } /** * Decode a string from the buffer. If the buffer does not contain the complete string representation * then a value of null is returned to indicate that more data is needed to complete parsing. * This should be only after the prefix has been set with {@link #setPrefix(int)}. * @param buffer the buffer containing the encoded string. * @return the decoded string or null to indicate that more data is needed. * @throws ArithmeticException if the string length value overflows a int. * @throws EncodingException if the string encoding is invalid. */ public String decode(ByteBuffer buffer) throws EncodingException { while (true) { switch (_state) { case PARSING: byte firstByte = buffer.get(buffer.position()); _huffman = ((0x80 >>> (8 - _prefix)) & firstByte) != 0; _state = State.LENGTH; _integerDecoder.setPrefix(_prefix - 1); continue; case LENGTH: _length = _integerDecoder.decodeInt(buffer); if (_length < 0) return null; _state = State.VALUE; _huffmanBuilder.setLength(_length); continue; case VALUE: String value = _huffman ? _huffmanBuilder.decode(buffer) : stringDecode(buffer); if (value != null) reset(); return value; default: throw new IllegalStateException(_state.name()); } } } private String stringDecode(ByteBuffer buffer) { for (; _count < _length; _count++) { if (!buffer.hasRemaining()) return null; _builder.append(buffer.get()); } return _builder.build(); } public void reset() { _state = State.PARSING; _integerDecoder.reset(); _huffmanBuilder.reset(); _builder.reset(); _prefix = 0; _count = 0; _length = 0; _huffman = false; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy