1/* 2 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25package jdk.incubator.http.internal.hpack; 26 27import java.nio.ByteBuffer; 28import java.util.Arrays; 29 30// 31// 0 1 2 3 4 5 6 7 32// +---+---+---+---+---+---+---+---+ 33// | H | String Length (7+) | 34// +---+---------------------------+ 35// | String Data (Length octets) | 36// +-------------------------------+ 37// 38final class StringReader { 39 40 private static final int NEW = 0; 41 private static final int FIRST_BYTE_READ = 1; 42 private static final int LENGTH_READ = 2; 43 private static final int DONE = 4; 44 45 private final IntegerReader intReader = new IntegerReader(); 46 private final Huffman.Reader huffmanReader = new Huffman.Reader(); 47 private final ISO_8859_1.Reader plainReader = new ISO_8859_1.Reader(); 48 49 private int state = NEW; 50 51 private boolean huffman; 52 private int remainingLength; 53 54 boolean read(ByteBuffer input, Appendable output) { 55 if (state == DONE) { 56 return true; 57 } 58 if (!input.hasRemaining()) { 59 return false; 60 } 61 if (state == NEW) { 62 int p = input.position(); 63 huffman = (input.get(p) & 0b10000000) != 0; 64 state = FIRST_BYTE_READ; 65 intReader.configure(7); 66 } 67 if (state == FIRST_BYTE_READ) { 68 boolean lengthRead = intReader.read(input); 69 if (!lengthRead) { 70 return false; 71 } 72 remainingLength = intReader.get(); 73 state = LENGTH_READ; 74 } 75 if (state == LENGTH_READ) { 76 boolean isLast = input.remaining() >= remainingLength; 77 int oldLimit = input.limit(); 78 if (isLast) { 79 input.limit(input.position() + remainingLength); 80 } 81 remainingLength -= Math.min(input.remaining(), remainingLength); 82 if (huffman) { 83 huffmanReader.read(input, output, isLast); 84 } else { 85 plainReader.read(input, output); 86 } 87 if (isLast) { 88 input.limit(oldLimit); 89 state = DONE; 90 } 91 return isLast; 92 } 93 throw new InternalError(Arrays.toString( 94 new Object[]{state, huffman, remainingLength})); 95 } 96 97 boolean isHuffmanEncoded() { 98 if (state < FIRST_BYTE_READ) { 99 throw new IllegalStateException("Has not been fully read yet"); 100 } 101 return huffman; 102 } 103 104 void reset() { 105 if (huffman) { 106 huffmanReader.reset(); 107 } else { 108 plainReader.reset(); 109 } 110 intReader.reset(); 111 state = NEW; 112 } 113} 114