1// 2// ======================================================================== 3// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. 4// ------------------------------------------------------------------------ 5// All rights reserved. This program and the accompanying materials 6// are made available under the terms of the Eclipse Public License v1.0 7// and Apache License v2.0 which accompanies this distribution. 8// 9// The Eclipse Public License is available at 10// http://www.eclipse.org/legal/epl-v10.html 11// 12// The Apache License v2.0 is available at 13// http://www.opensource.org/licenses/apache2.0.php 14// 15// You may elect to redistribute this code under either of these licenses. 16// ======================================================================== 17// 18 19package org.eclipse.jetty.util; 20 21import java.io.BufferedInputStream; 22import java.io.IOException; 23import java.io.InputStream; 24 25/** 26 * ReadLineInputStream 27 * 28 * Read from an input stream, accepting CR/LF, LF or just CR. 29 */ 30public class ReadLineInputStream extends BufferedInputStream 31{ 32 boolean _seenCRLF; 33 boolean _skipLF; 34 35 public ReadLineInputStream(InputStream in) 36 { 37 super(in); 38 } 39 40 public ReadLineInputStream(InputStream in, int size) 41 { 42 super(in,size); 43 } 44 45 public String readLine() throws IOException 46 { 47 mark(buf.length); 48 49 while (true) 50 { 51 int b=super.read(); 52 53 if (markpos < 0) 54 throw new IOException("Buffer size exceeded: no line terminator"); 55 56 if (b==-1) 57 { 58 int m=markpos; 59 markpos=-1; 60 if (pos>m) 61 return new String(buf,m,pos-m,StringUtil.__UTF8_CHARSET); 62 63 return null; 64 } 65 66 if (b=='\r') 67 { 68 int p=pos; 69 70 // if we have seen CRLF before, hungrily consume LF 71 if (_seenCRLF && pos<count) 72 { 73 if (buf[pos]=='\n') 74 pos+=1; 75 } 76 else 77 _skipLF=true; 78 int m=markpos; 79 markpos=-1; 80 return new String(buf,m,p-m-1,StringUtil.__UTF8_CHARSET); 81 } 82 83 if (b=='\n') 84 { 85 if (_skipLF) 86 { 87 _skipLF=false; 88 _seenCRLF=true; 89 markpos++; 90 continue; 91 } 92 int m=markpos; 93 markpos=-1; 94 return new String(buf,m,pos-m-1,StringUtil.__UTF8_CHARSET); 95 } 96 } 97 } 98 99 @Override 100 public synchronized int read() throws IOException 101 { 102 int b = super.read(); 103 if (_skipLF) 104 { 105 _skipLF=false; 106 if (_seenCRLF && b=='\n') 107 b=super.read(); 108 } 109 return b; 110 } 111 112 @Override 113 public synchronized int read(byte[] buf, int off, int len) throws IOException 114 { 115 if (_skipLF && len>0) 116 { 117 _skipLF=false; 118 if (_seenCRLF) 119 { 120 int b = super.read(); 121 if (b==-1) 122 return -1; 123 124 if (b!='\n') 125 { 126 buf[off]=(byte)(0xff&b); 127 return 1+super.read(buf,off+1,len-1); 128 } 129 } 130 } 131 132 return super.read(buf,off,len); 133 } 134 135 136} 137