001 /*
002 * Copyright 2001-2005 The Apache Software Foundation
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.apache.commons.net.io;
017
018 import java.io.FilterInputStream;
019 import java.io.IOException;
020 import java.io.InputStream;
021
022 /***
023 * This class wraps an input stream, replacing all singly occurring
024 * <LF> (linefeed) characters with <CR><LF> (carriage return
025 * followed by linefeed), which is the NETASCII standard for representing
026 * a newline.
027 * You would use this class to implement ASCII file transfers requiring
028 * conversion to NETASCII.
029 * <p>
030 * <p>
031 * @author Daniel F. Savarese
032 ***/
033
034 public final class ToNetASCIIInputStream extends FilterInputStream
035 {
036 private static final int __NOTHING_SPECIAL = 0;
037 private static final int __LAST_WAS_CR = 1;
038 private static final int __LAST_WAS_NL = 2;
039 private int __status;
040
041 /***
042 * Creates a ToNetASCIIInputStream instance that wraps an existing
043 * InputStream.
044 * <p>
045 * @param input The InputStream to .
046 ***/
047 public ToNetASCIIInputStream(InputStream input)
048 {
049 super(input);
050 __status = __NOTHING_SPECIAL;
051 }
052
053
054 /***
055 * Reads and returns the next byte in the stream. If the end of the
056 * message has been reached, returns -1.
057 * <p>
058 * @return The next character in the stream. Returns -1 if the end of the
059 * stream has been reached.
060 * @exception IOException If an error occurs while reading the underlying
061 * stream.
062 ***/
063 public int read() throws IOException
064 {
065 int ch;
066
067 if (__status == __LAST_WAS_NL)
068 {
069 __status = __NOTHING_SPECIAL;
070 return '\n';
071 }
072
073 ch = in.read();
074
075 switch (ch)
076 {
077 case '\r':
078 __status = __LAST_WAS_CR;
079 return '\r';
080 case '\n':
081 if (__status != __LAST_WAS_CR)
082 {
083 __status = __LAST_WAS_NL;
084 return '\r';
085 }
086 // else fall through
087 default:
088 __status = __NOTHING_SPECIAL;
089 return ch;
090 }
091 // statement not reached
092 //return ch;
093 }
094
095
096 /***
097 * Reads the next number of bytes from the stream into an array and
098 * returns the number of bytes read. Returns -1 if the end of the
099 * stream has been reached.
100 * <p>
101 * @param buffer The byte array in which to store the data.
102 * @return The number of bytes read. Returns -1 if the
103 * end of the message has been reached.
104 * @exception IOException If an error occurs in reading the underlying
105 * stream.
106 ***/
107 public int read(byte buffer[]) throws IOException
108 {
109 return read(buffer, 0, buffer.length);
110 }
111
112
113 /***
114 * Reads the next number of bytes from the stream into an array and returns
115 * the number of bytes read. Returns -1 if the end of the
116 * message has been reached. The characters are stored in the array
117 * starting from the given offset and up to the length specified.
118 * <p>
119 * @param buffer The byte array in which to store the data.
120 * @param offset The offset into the array at which to start storing data.
121 * @param length The number of bytes to read.
122 * @return The number of bytes read. Returns -1 if the
123 * end of the stream has been reached.
124 * @exception IOException If an error occurs while reading the underlying
125 * stream.
126 ***/
127 public int read(byte buffer[], int offset, int length) throws IOException
128 {
129 int ch, off;
130
131 if (length < 1)
132 return 0;
133
134 ch = available();
135
136 if (length > ch)
137 length = ch;
138
139 // If nothing is available, block to read only one character
140 if (length < 1)
141 length = 1;
142
143 if ((ch = read()) == -1)
144 return -1;
145
146 off = offset;
147
148 do
149 {
150 buffer[offset++] = (byte)ch;
151 }
152 while (--length > 0 && (ch = read()) != -1);
153
154 return (offset - off);
155 }
156
157 /*** Returns false. Mark is not supported. ***/
158 public boolean markSupported()
159 {
160 return false;
161 }
162
163 public int available() throws IOException
164 {
165 int result;
166
167 result = in.available();
168
169 if (__status == __LAST_WAS_NL)
170 return (result + 1);
171
172 return result;
173 }
174 }