1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package org.apache.commons.net.io; 19 20 import java.io.FilterInputStream; 21 import java.io.IOException; 22 import java.io.InputStream; 23 24 /*** 25 * This class wraps an input stream, replacing all singly occurring 26 * <LF> (linefeed) characters with <CR><LF> (carriage return 27 * followed by linefeed), which is the NETASCII standard for representing 28 * a newline. 29 * You would use this class to implement ASCII file transfers requiring 30 * conversion to NETASCII. 31 * <p> 32 * <p> 33 ***/ 34 35 public final class ToNetASCIIInputStream extends FilterInputStream 36 { 37 private static final int __NOTHING_SPECIAL = 0; 38 private static final int __LAST_WAS_CR = 1; 39 private static final int __LAST_WAS_NL = 2; 40 private int __status; 41 42 /*** 43 * Creates a ToNetASCIIInputStream instance that wraps an existing 44 * InputStream. 45 * <p> 46 * @param input The InputStream to wrap. 47 ***/ 48 public ToNetASCIIInputStream(InputStream input) 49 { 50 super(input); 51 __status = __NOTHING_SPECIAL; 52 } 53 54 55 /*** 56 * Reads and returns the next byte in the stream. If the end of the 57 * message has been reached, returns -1. 58 * <p> 59 * @return The next character in the stream. Returns -1 if the end of the 60 * stream has been reached. 61 * @exception IOException If an error occurs while reading the underlying 62 * stream. 63 ***/ 64 @Override 65 public int read() throws IOException 66 { 67 int ch; 68 69 if (__status == __LAST_WAS_NL) 70 { 71 __status = __NOTHING_SPECIAL; 72 return '\n'; 73 } 74 75 ch = in.read(); 76 77 switch (ch) 78 { 79 case '\r': 80 __status = __LAST_WAS_CR; 81 return '\r'; 82 case '\n': 83 if (__status != __LAST_WAS_CR) 84 { 85 __status = __LAST_WAS_NL; 86 return '\r'; 87 } 88 //$FALL-THROUGH$ 89 default: 90 __status = __NOTHING_SPECIAL; 91 return ch; 92 } 93 // statement not reached 94 //return ch; 95 } 96 97 98 /*** 99 * Reads the next number of bytes from the stream into an array and 100 * returns the number of bytes read. Returns -1 if the end of the 101 * stream has been reached. 102 * <p> 103 * @param buffer The byte array in which to store the data. 104 * @return The number of bytes read. Returns -1 if the 105 * end of the message has been reached. 106 * @exception IOException If an error occurs in reading the underlying 107 * stream. 108 ***/ 109 @Override 110 public int read(byte buffer[]) throws IOException 111 { 112 return read(buffer, 0, buffer.length); 113 } 114 115 116 /*** 117 * Reads the next number of bytes from the stream into an array and returns 118 * the number of bytes read. Returns -1 if the end of the 119 * message has been reached. The characters are stored in the array 120 * starting from the given offset and up to the length specified. 121 * <p> 122 * @param buffer The byte array in which to store the data. 123 * @param offset The offset into the array at which to start storing data. 124 * @param length The number of bytes to read. 125 * @return The number of bytes read. Returns -1 if the 126 * end of the stream has been reached. 127 * @exception IOException If an error occurs while reading the underlying 128 * stream. 129 ***/ 130 @Override 131 public int read(byte buffer[], int offset, int length) throws IOException 132 { 133 int ch, off; 134 135 if (length < 1) { 136 return 0; 137 } 138 139 ch = available(); 140 141 if (length > ch) { 142 length = ch; 143 } 144 145 // If nothing is available, block to read only one character 146 if (length < 1) { 147 length = 1; 148 } 149 150 if ((ch = read()) == -1) { 151 return -1; 152 } 153 154 off = offset; 155 156 do 157 { 158 buffer[offset++] = (byte)ch; 159 } 160 while (--length > 0 && (ch = read()) != -1); 161 162 return (offset - off); 163 } 164 165 /*** Returns false. Mark is not supported. ***/ 166 @Override 167 public boolean markSupported() 168 { 169 return false; 170 } 171 172 @Override 173 public int available() throws IOException 174 { 175 int result; 176 177 result = in.available(); 178 179 if (__status == __LAST_WAS_NL) { 180 return (result + 1); 181 } 182 183 return result; 184 } 185 }