1 /* 2 * Copyright (C) 2006 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the License 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 * or implied. See the License for the specific language governing permissions and limitations under 12 * the License. 13 */ 14 15 package com.google.common.io; 16 17 import static com.google.common.base.Preconditions.checkNotNull; 18 19 import com.google.common.annotations.GwtIncompatible; 20 import java.io.Closeable; 21 import java.io.Flushable; 22 import java.io.IOException; 23 import java.io.Writer; 24 import org.checkerframework.checker.nullness.compatqual.NullableDecl; 25 26 /** 27 * Writer that places all output on an {@link Appendable} target. If the target is {@link Flushable} 28 * or {@link Closeable}, flush()es and close()s will also be delegated to the target. 29 * 30 * @author Alan Green 31 * @author Sebastian Kanthak 32 * @since 1.0 33 */ 34 @GwtIncompatible 35 class AppendableWriter extends Writer { 36 private final Appendable target; 37 private boolean closed; 38 39 /** 40 * Creates a new writer that appends everything it writes to {@code target}. 41 * 42 * @param target target to which to append output 43 */ AppendableWriter(Appendable target)44 AppendableWriter(Appendable target) { 45 this.target = checkNotNull(target); 46 } 47 48 /* 49 * Abstract methods from Writer 50 */ 51 52 @Override write(char[] cbuf, int off, int len)53 public void write(char[] cbuf, int off, int len) throws IOException { 54 checkNotClosed(); 55 // It turns out that creating a new String is usually as fast, or faster 56 // than wrapping cbuf in a light-weight CharSequence. 57 target.append(new String(cbuf, off, len)); 58 } 59 60 /* 61 * Override a few functions for performance reasons to avoid creating unnecessary strings. 62 */ 63 64 @Override write(int c)65 public void write(int c) throws IOException { 66 checkNotClosed(); 67 target.append((char) c); 68 } 69 70 @Override write(@ullableDecl String str)71 public void write(@NullableDecl String str) throws IOException { 72 checkNotClosed(); 73 target.append(str); 74 } 75 76 @Override write(@ullableDecl String str, int off, int len)77 public void write(@NullableDecl String str, int off, int len) throws IOException { 78 checkNotClosed(); 79 // tricky: append takes start, end pair... 80 target.append(str, off, off + len); 81 } 82 83 @Override flush()84 public void flush() throws IOException { 85 checkNotClosed(); 86 if (target instanceof Flushable) { 87 ((Flushable) target).flush(); 88 } 89 } 90 91 @Override close()92 public void close() throws IOException { 93 this.closed = true; 94 if (target instanceof Closeable) { 95 ((Closeable) target).close(); 96 } 97 } 98 99 @Override append(char c)100 public Writer append(char c) throws IOException { 101 checkNotClosed(); 102 target.append(c); 103 return this; 104 } 105 106 @Override append(@ullableDecl CharSequence charSeq)107 public Writer append(@NullableDecl CharSequence charSeq) throws IOException { 108 checkNotClosed(); 109 target.append(charSeq); 110 return this; 111 } 112 113 @Override append(@ullableDecl CharSequence charSeq, int start, int end)114 public Writer append(@NullableDecl CharSequence charSeq, int start, int end) throws IOException { 115 checkNotClosed(); 116 target.append(charSeq, start, end); 117 return this; 118 } 119 checkNotClosed()120 private void checkNotClosed() throws IOException { 121 if (closed) { 122 throw new IOException("Cannot write to a closed writer."); 123 } 124 } 125 } 126