/* * Copyright 2010 netling project <http://netling.org> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file may incorporate work covered by the following copyright and * permission notice: * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.netling.io; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; /*** * This class wraps an input stream, replacing all singly occurring * <LF> (linefeed) characters with <CR><LF> (carriage return * followed by linefeed), which is the NETASCII standard for representing * a newline. * You would use this class to implement ASCII file transfers requiring * conversion to NETASCII. ***/ public final class ToNetASCIIInputStream extends FilterInputStream { private static final int NOTHING_SPECIAL = 0; private static final int LAST_WAS_CR = 1; private static final int LAST_WAS_NL = 2; private int status; /*** * Creates a ToNetASCIIInputStream instance that wraps an existing * InputStream. * <p> * @param input The InputStream to . ***/ public ToNetASCIIInputStream(InputStream input) { super(input); status = NOTHING_SPECIAL; } /*** * Reads and returns the next byte in the stream. If the end of the * message has been reached, returns -1. * <p> * @return The next character in the stream. Returns -1 if the end of the * stream has been reached. * @exception IOException If an error occurs while reading the underlying * stream. ***/ @Override public int read() throws IOException { int ch; if (status == LAST_WAS_NL) { status = NOTHING_SPECIAL; return '\n'; } ch = in.read(); switch (ch) { case '\r': status = LAST_WAS_CR; return '\r'; case '\n': if (status != LAST_WAS_CR) { status = LAST_WAS_NL; return '\r'; } //$FALL-THROUGH$ default: status = NOTHING_SPECIAL; return ch; } // statement not reached //return ch; } /*** * Reads the next number of bytes from the stream into an array and * returns the number of bytes read. Returns -1 if the end of the * stream has been reached. * <p> * @param buffer The byte array in which to store the data. * @return The number of bytes read. Returns -1 if the * end of the message has been reached. * @exception IOException If an error occurs in reading the underlying * stream. ***/ @Override public int read(byte buffer[]) throws IOException { return read(buffer, 0, buffer.length); } /*** * Reads the next number of bytes from the stream into an array and returns * the number of bytes read. Returns -1 if the end of the * message has been reached. The characters are stored in the array * starting from the given offset and up to the length specified. * <p> * @param buffer The byte array in which to store the data. * @param offset The offset into the array at which to start storing data. * @param length The number of bytes to read. * @return The number of bytes read. Returns -1 if the * end of the stream has been reached. * @exception IOException If an error occurs while reading the underlying * stream. ***/ @Override public int read(byte buffer[], int offset, int length) throws IOException { int ch, off; if (length < 1) return 0; ch = available(); if (length > ch) length = ch; // If nothing is available, block to read only one character if (length < 1) length = 1; if ((ch = read()) == -1) return -1; off = offset; do { buffer[offset++] = (byte)ch; } while (--length > 0 && (ch = read()) != -1); return (offset - off); } /*** Returns false. Mark is not supported. ***/ @Override public boolean markSupported() { return false; } @Override public int available() throws IOException { int result; result = in.available(); if (status == LAST_WAS_NL) return (result + 1); return result; } }