Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright 2013, Google Inc.
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are
      7  * met:
      8  *
      9  *     * Redistributions of source code must retain the above copyright
     10  * notice, this list of conditions and the following disclaimer.
     11  *     * Redistributions in binary form must reproduce the above
     12  * copyright notice, this list of conditions and the following disclaimer
     13  * in the documentation and/or other materials provided with the
     14  * distribution.
     15  *     * Neither the name of Google Inc. nor the names of its
     16  * contributors may be used to endorse or promote products derived from
     17  * this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 package org.jf.util;
     33 
     34 import java.io.FilterWriter;
     35 import java.io.IOException;
     36 import java.io.Writer;
     37 
     38 /**
     39  * Writer that wraps another writer and passes width-limited and
     40  * optionally-prefixed output to its subordinate. When lines are
     41  * wrapped they are automatically indented based on the start of the
     42  * line.
     43  */
     44 public final class OldWrappedIndentingWriter extends FilterWriter {
     45     /** null-ok; optional prefix for every line */
     46     private final String prefix;
     47 
     48     /** > 0; the maximum output width */
     49     private final int width;
     50 
     51     /** > 0; the maximum indent */
     52     private final int maxIndent;
     53 
     54     /** >= 0; current output column (zero-based) */
     55     private int column;
     56 
     57     /** whether indent spaces are currently being collected */
     58     private boolean collectingIndent;
     59 
     60     /** >= 0; current indent amount */
     61     private int indent;
     62 
     63     /**
     64      * Constructs an instance.
     65      *
     66      * @param out non-null; writer to send final output to
     67      * @param width >= 0; the maximum output width (not including
     68      * <code>prefix</code>), or <code>0</code> for no maximum
     69      * @param prefix non-null; the prefix for each line
     70      */
     71     public OldWrappedIndentingWriter(Writer out, int width, String prefix) {
     72         super(out);
     73 
     74         if (out == null) {
     75             throw new NullPointerException("out == null");
     76         }
     77 
     78         if (width < 0) {
     79             throw new IllegalArgumentException("width < 0");
     80         }
     81 
     82         if (prefix == null) {
     83             throw new NullPointerException("prefix == null");
     84         }
     85 
     86         this.width = (width != 0) ? width : Integer.MAX_VALUE;
     87         this.maxIndent = width >> 1;
     88         this.prefix = (prefix.length() == 0) ? null : prefix;
     89 
     90         bol();
     91     }
     92 
     93     /**
     94      * Constructs a no-prefix instance.
     95      *
     96      * @param out non-null; writer to send final output to
     97      * @param width &gt;= 0; the maximum output width (not including
     98      * <code>prefix</code>), or <code>0</code> for no maximum
     99      */
    100     public OldWrappedIndentingWriter(Writer out, int width) {
    101         this(out, width, "");
    102     }
    103 
    104     /** {@inheritDoc} */
    105     @Override
    106     public void write(int c) throws IOException {
    107         synchronized (lock) {
    108             if (collectingIndent) {
    109                 if (c == ' ') {
    110                     indent++;
    111                     if (indent >= maxIndent) {
    112                         indent = maxIndent;
    113                         collectingIndent = false;
    114                     }
    115                 } else {
    116                     collectingIndent = false;
    117                 }
    118             }
    119 
    120             if ((column == width) && (c != '\n')) {
    121                 out.write('\n');
    122                 column = 0;
    123                 /*
    124                  * Note: No else, so this should fall through to the next
    125                  * if statement.
    126                  */
    127             }
    128 
    129             if (column == 0) {
    130                 if (prefix != null) {
    131                     out.write(prefix);
    132                 }
    133 
    134                 if (!collectingIndent) {
    135                     for (int i = 0; i < indent; i++) {
    136                         out.write(' ');
    137                     }
    138                     column = indent;
    139                 }
    140             }
    141 
    142             out.write(c);
    143 
    144             if (c == '\n') {
    145                 bol();
    146             } else {
    147                 column++;
    148             }
    149         }
    150     }
    151 
    152     /** {@inheritDoc} */
    153     @Override
    154     public void write(char[] cbuf, int off, int len) throws IOException {
    155         synchronized (lock) {
    156             while (len > 0) {
    157                 write(cbuf[off]);
    158                 off++;
    159                 len--;
    160             }
    161         }
    162     }
    163 
    164     /** {@inheritDoc} */
    165     @Override
    166     public void write(String str, int off, int len) throws IOException {
    167         synchronized (lock) {
    168             while (len > 0) {
    169                 write(str.charAt(off));
    170                 off++;
    171                 len--;
    172             }
    173         }
    174     }
    175 
    176     /**
    177      * Indicates that output is at the beginning of a line.
    178      */
    179     private void bol() {
    180         column = 0;
    181         collectingIndent = (maxIndent != 0);
    182         indent = 0;
    183     }
    184 }
    185