commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jaco...@apache.org
Subject svn commit: r1065950 [1/3] - in /commons/sandbox/csv/trunk/src: java/org/apache/commons/csv/ java/org/apache/commons/csv/writer/ test/org/apache/commons/csv/ test/org/apache/commons/csv/writer/
Date Tue, 01 Feb 2011 08:46:01 GMT
Author: jacopoc
Date: Tue Feb  1 08:46:00 2011
New Revision: 1065950

URL: http://svn.apache.org/viewvc?rev=1065950&view=rev
Log:
No functional changes are contained in this commit: reformatted Java code to fix several formatting inconsistencies (between classes and within the same class); sorry for the big commit, but I have preferred to isolate into one commit all the formatting changes.

Modified:
    commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/CSVParser.java
    commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/CSVPrinter.java
    commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/CSVStrategy.java
    commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/CSVUtils.java
    commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/CharBuffer.java
    commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/ExtendedBufferedReader.java
    commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/writer/CSVConfig.java
    commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/writer/CSVConfigGuesser.java
    commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/writer/CSVField.java
    commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/writer/CSVWriter.java
    commons/sandbox/csv/trunk/src/test/org/apache/commons/csv/CSVParserTest.java
    commons/sandbox/csv/trunk/src/test/org/apache/commons/csv/CSVPrinterTest.java
    commons/sandbox/csv/trunk/src/test/org/apache/commons/csv/CSVStrategyTest.java
    commons/sandbox/csv/trunk/src/test/org/apache/commons/csv/CSVUtilsTest.java
    commons/sandbox/csv/trunk/src/test/org/apache/commons/csv/CharBufferTest.java
    commons/sandbox/csv/trunk/src/test/org/apache/commons/csv/ExtendedBufferedReaderTest.java
    commons/sandbox/csv/trunk/src/test/org/apache/commons/csv/writer/CSVConfigGuesserTest.java
    commons/sandbox/csv/trunk/src/test/org/apache/commons/csv/writer/CSVConfigTest.java
    commons/sandbox/csv/trunk/src/test/org/apache/commons/csv/writer/CSVFieldTest.java
    commons/sandbox/csv/trunk/src/test/org/apache/commons/csv/writer/CSVWriterTest.java

Modified: commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/CSVParser.java
URL: http://svn.apache.org/viewvc/commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/CSVParser.java?rev=1065950&r1=1065949&r2=1065950&view=diff
==============================================================================
--- commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/CSVParser.java (original)
+++ commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/CSVParser.java Tue Feb  1 08:46:00 2011
@@ -28,578 +28,609 @@ import java.util.ArrayList;
  *
  * Because CSV appears in many different dialects, the parser supports many
  * configuration settings by allowing the specification of a {@link CSVStrategy}.
- * 
+ *
  * <p>Parsing of a csv-string having tabs as separators,
  * '"' as an optional value encapsulator, and comments starting with '#':</p>
  * <pre>
- *  String[][] data = 
+ *  String[][] data =
  *   (new CSVParser(new StringReader("a\tb\nc\td"), new CSVStrategy('\t','"','#'))).getAllValues();
  * </pre>
- * 
+ *
  * <p>Parsing of a csv-string in Excel CSV format</p>
  * <pre>
  *  String[][] data =
  *   (new CSVParser(new StringReader("a;b\nc;d"), CSVStrategy.EXCEL_STRATEGY)).getAllValues();
  * </pre>
- * 
+ *
  * <p>
  * Internal parser state is completely covered by the strategy
  * and the reader-state.</p>
- * 
- * <p>see <a href="package-summary.html">package documentation</a> 
+ *
+ * <p>see <a href="package-summary.html">package documentation</a>
  * for more details</p>
  */
 public class CSVParser {
 
-  /** length of the initial token (content-)buffer */
-  private static final int INITIAL_TOKEN_LENGTH = 50;
-  
-  // the token types
-  /** Token has no valid content, i.e. is in its initialized state. */
-  protected static final int TT_INVALID = -1;
-  /** Token with content, at beginning or in the middle of a line. */
-  protected static final int TT_TOKEN = 0;
-  /** Token (which can have content) when end of file is reached. */
-  protected static final int TT_EOF = 1;
-  /** Token with content when end of a line is reached. */
-  protected static final int TT_EORECORD = 2;
-
-  /** Immutable empty String array. */
-  private static final String[] EMPTY_STRING_ARRAY = new String[0];
-   
-  // the input stream
-  private final ExtendedBufferedReader in;
-
-  private final CSVStrategy strategy;
-  
-  // the following objects are shared to reduce garbage 
-  /** A record buffer for getLine(). Grows as necessary and is reused. */
-  private final ArrayList record = new ArrayList();
-  private final Token reusableToken = new Token();
-  private final CharBuffer wsBuf = new CharBuffer();
-  private final CharBuffer code = new CharBuffer(4);
-
-  
-  /**
-   * Token is an internal token representation.
-   * 
-   * It is used as contract between the lexer and the parser. 
-   */
-  static class Token {
-    /** Token type, see TT_xxx constants. */
-    int type = TT_INVALID;
-    /** The content buffer. */
-    CharBuffer content = new CharBuffer(INITIAL_TOKEN_LENGTH);
-    /** Token ready flag: indicates a valid token with content (ready for the parser). */
-    boolean isReady;
-    
-    Token reset() {
-        content.clear();
-        type = TT_INVALID;
-        isReady = false;
-        return this;
-    }
-  }
-  
-  // ======================================================
-  //  the constructor
-  // ======================================================
-  
-  /**
-   * Default strategy for the parser follows the default {@link CSVStrategy}.
-   * 
-   * @param input an InputStream containing "csv-formatted" stream
-   * @deprecated use {@link #CSVParser(Reader)}.
-   */
-  public CSVParser(InputStream input) {
-    this(new InputStreamReader(input));
-  }
-  
-  /**
-   * CSV parser using the default {@link CSVStrategy}.
-   * 
-   * @param input a Reader containing "csv-formatted" input
-   */
-  public CSVParser(Reader input) {
-    this(input, (CSVStrategy)CSVStrategy.DEFAULT_STRATEGY.clone());
-  }
-  
-  /**
-   * Customized value delimiter parser.
-   * 
-   * The parser follows the default {@link CSVStrategy}
-   * except for the delimiter setting.
-   * 
-   * @param input a Reader based on "csv-formatted" input
-   * @param delimiter a Char used for value separation
-   * @deprecated use {@link #CSVParser(Reader,CSVStrategy)}.
-   */
-  public CSVParser(Reader input, char delimiter) {
-    this(input, delimiter, '"', CSVStrategy.COMMENTS_DISABLED);
-  }
-  
-  /**
-   * Customized csv parser.
-   * 
-   * The parser parses according to the given CSV dialect settings.
-   * Leading whitespaces are truncated, unicode escapes are
-   * not interpreted and empty lines are ignored.
-   * 
-   * @param input a Reader based on "csv-formatted" input
-   * @param delimiter a Char used for value separation
-   * @param encapsulator a Char used as value encapsulation marker
-   * @param commentStart a Char used for comment identification
-   * @deprecated use {@link #CSVParser(Reader,CSVStrategy)}.
-   */
-  public CSVParser(Reader input, char delimiter, char encapsulator, char commentStart) {
-    this(input, new CSVStrategy(delimiter, encapsulator, commentStart));
-  }
-
-  /**
-   * Customized CSV parser using the given {@link CSVStrategy}
-   *
-   * @param input a Reader containing "csv-formatted" input
-   * @param strategy the CSVStrategy used for CSV parsing
-   */
-  public CSVParser(Reader input, CSVStrategy strategy) {
-    this.in = new ExtendedBufferedReader(input);
-    this.strategy = strategy;
-  }
-  
-  // ======================================================
-  //  the parser
-  // ======================================================
-  
-  /**
-   * Parses the CSV according to the given strategy
-   * and returns the content as an array of records
-   * (whereas records are arrays of single values).
-   * <p>
-   * The returned content starts at the current parse-position in
-   * the stream.
-   * 
-   * @return matrix of records x values ('null' when end of file)
-   * @throws IOException on parse error or input read-failure
-   */
-  public String[][] getAllValues() throws IOException {
-    ArrayList records = new ArrayList();
-    String[] values;
-    String[][] ret = null;
-    while ((values = getLine()) != null)  {
-      records.add(values);
-    }
-    if (records.size() > 0) {
-      ret = new String[records.size()][];
-      records.toArray(ret);
-    }
-    return ret;
-  }
-  
-  /**
-   * Parses the CSV according to the given strategy
-   * and returns the next csv-value as string.
-   * 
-   * @return next value in the input stream ('null' when end of file)
-   * @throws IOException on parse error or input read-failure
-   */
-  public String nextValue() throws IOException {
-    Token tkn = nextToken();
-    String ret = null;
-    switch (tkn.type) {
-      case TT_TOKEN:
-      case TT_EORECORD: 
-        ret = tkn.content.toString();
-        break;
-      case TT_EOF:
-        ret = null;
-        break;
-      case TT_INVALID:
-      default:
-        // error no token available (or error)
-        throw new IOException(
-          "(line " + getLineNumber() 
-          + ") invalid parse sequence");
-        // unreachable: break;
-    }
-    return ret;
-  }
-  
-  /**
-   * Parses from the current point in the stream til
-   * the end of the current line.
-   * 
-   * @return array of values til end of line 
-   *        ('null' when end of file has been reached)
-   * @throws IOException on parse error or input read-failure
-   */
-  public String[] getLine() throws IOException {
-    String[] ret = EMPTY_STRING_ARRAY;
-    record.clear();
-    while (true) {
-        reusableToken.reset();
-        nextToken(reusableToken);
-        switch (reusableToken.type) {
+    /**
+     * length of the initial token (content-)buffer
+     */
+    private static final int INITIAL_TOKEN_LENGTH = 50;
+
+    // the token types
+    /**
+     * Token has no valid content, i.e. is in its initialized state.
+     */
+    protected static final int TT_INVALID = -1;
+    /**
+     * Token with content, at beginning or in the middle of a line.
+     */
+    protected static final int TT_TOKEN = 0;
+    /**
+     * Token (which can have content) when end of file is reached.
+     */
+    protected static final int TT_EOF = 1;
+    /**
+     * Token with content when end of a line is reached.
+     */
+    protected static final int TT_EORECORD = 2;
+
+    /**
+     * Immutable empty String array.
+     */
+    private static final String[] EMPTY_STRING_ARRAY = new String[0];
+
+    // the input stream
+    private final ExtendedBufferedReader in;
+
+    private final CSVStrategy strategy;
+
+    // the following objects are shared to reduce garbage
+    /**
+     * A record buffer for getLine(). Grows as necessary and is reused.
+     */
+    private final ArrayList record = new ArrayList();
+    private final Token reusableToken = new Token();
+    private final CharBuffer wsBuf = new CharBuffer();
+    private final CharBuffer code = new CharBuffer(4);
+
+
+    /**
+     * Token is an internal token representation.
+     * <p/>
+     * It is used as contract between the lexer and the parser.
+     */
+    static class Token {
+        /**
+         * Token type, see TT_xxx constants.
+         */
+        int type = TT_INVALID;
+        /**
+         * The content buffer.
+         */
+        CharBuffer content = new CharBuffer(INITIAL_TOKEN_LENGTH);
+        /**
+         * Token ready flag: indicates a valid token with content (ready for the parser).
+         */
+        boolean isReady;
+
+        Token reset() {
+            content.clear();
+            type = TT_INVALID;
+            isReady = false;
+            return this;
+        }
+    }
+
+    // ======================================================
+    //  the constructor
+    // ======================================================
+
+    /**
+     * Default strategy for the parser follows the default {@link CSVStrategy}.
+     *
+     * @param input an InputStream containing "csv-formatted" stream
+     * @deprecated use {@link #CSVParser(Reader)}.
+     */
+    public CSVParser(InputStream input) {
+        this(new InputStreamReader(input));
+    }
+
+    /**
+     * CSV parser using the default {@link CSVStrategy}.
+     *
+     * @param input a Reader containing "csv-formatted" input
+     */
+    public CSVParser(Reader input) {
+        this(input, (CSVStrategy) CSVStrategy.DEFAULT_STRATEGY.clone());
+    }
+
+    /**
+     * Customized value delimiter parser.
+     * <p/>
+     * The parser follows the default {@link CSVStrategy}
+     * except for the delimiter setting.
+     *
+     * @param input     a Reader based on "csv-formatted" input
+     * @param delimiter a Char used for value separation
+     * @deprecated use {@link #CSVParser(Reader, CSVStrategy)}.
+     */
+    public CSVParser(Reader input, char delimiter) {
+        this(input, delimiter, '"', CSVStrategy.COMMENTS_DISABLED);
+    }
+
+    /**
+     * Customized csv parser.
+     * <p/>
+     * The parser parses according to the given CSV dialect settings.
+     * Leading whitespaces are truncated, unicode escapes are
+     * not interpreted and empty lines are ignored.
+     *
+     * @param input        a Reader based on "csv-formatted" input
+     * @param delimiter    a Char used for value separation
+     * @param encapsulator a Char used as value encapsulation marker
+     * @param commentStart a Char used for comment identification
+     * @deprecated use {@link #CSVParser(Reader, CSVStrategy)}.
+     */
+    public CSVParser(Reader input, char delimiter, char encapsulator, char commentStart) {
+        this(input, new CSVStrategy(delimiter, encapsulator, commentStart));
+    }
+
+    /**
+     * Customized CSV parser using the given {@link CSVStrategy}
+     *
+     * @param input    a Reader containing "csv-formatted" input
+     * @param strategy the CSVStrategy used for CSV parsing
+     */
+    public CSVParser(Reader input, CSVStrategy strategy) {
+        this.in = new ExtendedBufferedReader(input);
+        this.strategy = strategy;
+    }
+
+    // ======================================================
+    //  the parser
+    // ======================================================
+
+    /**
+     * Parses the CSV according to the given strategy
+     * and returns the content as an array of records
+     * (whereas records are arrays of single values).
+     * <p/>
+     * The returned content starts at the current parse-position in
+     * the stream.
+     *
+     * @return matrix of records x values ('null' when end of file)
+     * @throws IOException on parse error or input read-failure
+     */
+    public String[][] getAllValues() throws IOException {
+        ArrayList records = new ArrayList();
+        String[] values;
+        String[][] ret = null;
+        while ((values = getLine()) != null) {
+            records.add(values);
+        }
+        if (records.size() > 0) {
+            ret = new String[records.size()][];
+            records.toArray(ret);
+        }
+        return ret;
+    }
+
+    /**
+     * Parses the CSV according to the given strategy
+     * and returns the next csv-value as string.
+     *
+     * @return next value in the input stream ('null' when end of file)
+     * @throws IOException on parse error or input read-failure
+     */
+    public String nextValue() throws IOException {
+        Token tkn = nextToken();
+        String ret = null;
+        switch (tkn.type) {
             case TT_TOKEN:
-                record.add(reusableToken.content.toString());
-                break;
             case TT_EORECORD:
-                record.add(reusableToken.content.toString());
+                ret = tkn.content.toString();
                 break;
             case TT_EOF:
-                if (reusableToken.isReady) {
-                    record.add(reusableToken.content.toString());
-                } else {
-                    ret = null;
-                }
+                ret = null;
                 break;
             case TT_INVALID:
             default:
-                // error: throw IOException
-                throw new IOException("(line " + getLineNumber() + ") invalid parse sequence");
-            // unreachable: break;
-        }
-        if (reusableToken.type != TT_TOKEN) {
-            break;
-        }
-    }
-    if (!record.isEmpty()) {
-      ret = (String[]) record.toArray(new String[record.size()]);
-    }
-    return ret;
-  }
-  
-  /**
-   * Returns the current line number in the input stream.
-   * 
-   * ATTENTION: in case your csv has multiline-values the returned
-   *            number does not correspond to the record-number
-   * 
-   * @return  current line number
-   */
-  public int getLineNumber() {
-    return in.getLineNumber();  
-  }
-  
-  // ======================================================
-  //  the lexer(s)
-  // ======================================================
- 
-  /**
-   * Convenience method for <code>nextToken(null)</code>.
-   */
-  protected Token nextToken() throws IOException {
-      return nextToken(new Token());
-  }
-  
- /**
-   * Returns the next token.
-   * 
-   * A token corresponds to a term, a record change or an
-   * end-of-file indicator.
-   * 
-   * @param tkn an existing Token object to reuse. The caller is responsible to initialize the
-   * Token.
-   * @return the next token found
-   * @throws IOException on stream access error
-   */
-  protected Token nextToken(Token tkn) throws IOException {
-    wsBuf.clear(); // reuse
-    
-    // get the last read char (required for empty line detection)
-    int lastChar = in.readAgain();
-    
-    //  read the next char and set eol
-    /* note: unfortunately isEndOfLine may consumes a character silently.
-     *       this has no effect outside of the method. so a simple workaround
-     *       is to call 'readAgain' on the stream...
-     *       uh: might using objects instead of base-types (jdk1.5 autoboxing!)
-     */
-    int c = in.read();
-    boolean eol = isEndOfLine(c);
-    c = in.readAgain();
-     
-    //  empty line detection: eol AND (last char was EOL or beginning)
-    while (strategy.getIgnoreEmptyLines() && eol 
-      && (lastChar == '\n' 
-      || lastChar == '\r' 
-      || lastChar == ExtendedBufferedReader.UNDEFINED) 
-      && !isEndOfFile(lastChar)) {
-      // go on char ahead ...
-      lastChar = c;
-      c = in.read();
-      eol = isEndOfLine(c);
-      c = in.readAgain();
-      // reached end of file without any content (empty line at the end)
-      if (isEndOfFile(c)) {
-        tkn.type = TT_EOF;
+                // error no token available (or error)
+                throw new IOException(
+                        "(line " + getLineNumber()
+                                + ") invalid parse sequence");
+                // unreachable: break;
+        }
+        return ret;
+    }
+
+    /**
+     * Parses from the current point in the stream til
+     * the end of the current line.
+     *
+     * @return array of values til end of line
+     *         ('null' when end of file has been reached)
+     * @throws IOException on parse error or input read-failure
+     */
+    public String[] getLine() throws IOException {
+        String[] ret = EMPTY_STRING_ARRAY;
+        record.clear();
+        while (true) {
+            reusableToken.reset();
+            nextToken(reusableToken);
+            switch (reusableToken.type) {
+                case TT_TOKEN:
+                    record.add(reusableToken.content.toString());
+                    break;
+                case TT_EORECORD:
+                    record.add(reusableToken.content.toString());
+                    break;
+                case TT_EOF:
+                    if (reusableToken.isReady) {
+                        record.add(reusableToken.content.toString());
+                    } else {
+                        ret = null;
+                    }
+                    break;
+                case TT_INVALID:
+                default:
+                    // error: throw IOException
+                    throw new IOException("(line " + getLineNumber() + ") invalid parse sequence");
+                    // unreachable: break;
+            }
+            if (reusableToken.type != TT_TOKEN) {
+                break;
+            }
+        }
+        if (!record.isEmpty()) {
+            ret = (String[]) record.toArray(new String[record.size()]);
+        }
+        return ret;
+    }
+
+    /**
+     * Returns the current line number in the input stream.
+     * <p/>
+     * ATTENTION: in case your csv has multiline-values the returned
+     * number does not correspond to the record-number
+     *
+     * @return current line number
+     */
+    public int getLineNumber() {
+        return in.getLineNumber();
+    }
+
+    // ======================================================
+    //  the lexer(s)
+    // ======================================================
+
+    /**
+     * Convenience method for <code>nextToken(null)</code>.
+     */
+    protected Token nextToken() throws IOException {
+        return nextToken(new Token());
+    }
+
+    /**
+     * Returns the next token.
+     * <p/>
+     * A token corresponds to a term, a record change or an
+     * end-of-file indicator.
+     *
+     * @param tkn an existing Token object to reuse. The caller is responsible to initialize the
+     *            Token.
+     * @return the next token found
+     * @throws IOException on stream access error
+     */
+    protected Token nextToken(Token tkn) throws IOException {
+        wsBuf.clear(); // reuse
+
+        // get the last read char (required for empty line detection)
+        int lastChar = in.readAgain();
+
+        //  read the next char and set eol
+        /* note: unfortunately isEndOfLine may consumes a character silently.
+        *       this has no effect outside of the method. so a simple workaround
+        *       is to call 'readAgain' on the stream...
+        *       uh: might using objects instead of base-types (jdk1.5 autoboxing!)
+        */
+        int c = in.read();
+        boolean eol = isEndOfLine(c);
+        c = in.readAgain();
+
+        //  empty line detection: eol AND (last char was EOL or beginning)
+        while (strategy.getIgnoreEmptyLines() && eol
+                && (lastChar == '\n'
+                || lastChar == '\r'
+                || lastChar == ExtendedBufferedReader.UNDEFINED)
+                && !isEndOfFile(lastChar)) {
+            // go on char ahead ...
+            lastChar = c;
+            c = in.read();
+            eol = isEndOfLine(c);
+            c = in.readAgain();
+            // reached end of file without any content (empty line at the end)
+            if (isEndOfFile(c)) {
+                tkn.type = TT_EOF;
+                return tkn;
+            }
+        }
+
+        // did we reach eof during the last iteration already ? TT_EOF
+        if (isEndOfFile(lastChar) || (lastChar != strategy.getDelimiter() && isEndOfFile(c))) {
+            tkn.type = TT_EOF;
+            return tkn;
+        }
+
+        //  important: make sure a new char gets consumed in each iteration
+        while (!tkn.isReady && tkn.type != TT_EOF) {
+            // ignore whitespaces at beginning of a token
+            while (strategy.getIgnoreLeadingWhitespaces() && isWhitespace(c) && !eol) {
+                wsBuf.append((char) c);
+                c = in.read();
+                eol = isEndOfLine(c);
+            }
+            // ok, start of token reached: comment, encapsulated, or token
+            if (c == strategy.getCommentStart()) {
+                // ignore everything till end of line and continue (incr linecount)
+                in.readLine();
+                tkn = nextToken(tkn.reset());
+            } else if (c == strategy.getDelimiter()) {
+                // empty token return TT_TOKEN("")
+                tkn.type = TT_TOKEN;
+                tkn.isReady = true;
+            } else if (eol) {
+                // empty token return TT_EORECORD("")
+                //noop: tkn.content.append("");
+                tkn.type = TT_EORECORD;
+                tkn.isReady = true;
+            } else if (c == strategy.getEncapsulator()) {
+                // consume encapsulated token
+                encapsulatedTokenLexer(tkn, c);
+            } else if (isEndOfFile(c)) {
+                // end of file return TT_EOF()
+                //noop: tkn.content.append("");
+                tkn.type = TT_EOF;
+                tkn.isReady = true;
+            } else {
+                // next token must be a simple token
+                // add removed blanks when not ignoring whitespace chars...
+                if (!strategy.getIgnoreLeadingWhitespaces()) {
+                    tkn.content.append(wsBuf);
+                }
+                simpleTokenLexer(tkn, c);
+            }
+        }
         return tkn;
-      }
     }
 
-    // did we reach eof during the last iteration already ? TT_EOF
-    if (isEndOfFile(lastChar) || (lastChar != strategy.getDelimiter() && isEndOfFile(c))) {
-      tkn.type = TT_EOF;
-      return tkn;
-    } 
-    
-    //  important: make sure a new char gets consumed in each iteration
-    while (!tkn.isReady && tkn.type != TT_EOF) {
-      // ignore whitespaces at beginning of a token
-      while (strategy.getIgnoreLeadingWhitespaces() && isWhitespace(c) && !eol) {
-        wsBuf.append((char) c);
-        c = in.read();
-        eol = isEndOfLine(c);
-      }
-      // ok, start of token reached: comment, encapsulated, or token
-      if (c == strategy.getCommentStart()) {
-        // ignore everything till end of line and continue (incr linecount)
-        in.readLine();
-        tkn = nextToken(tkn.reset());
-      } else if (c == strategy.getDelimiter()) {
-        // empty token return TT_TOKEN("")
-        tkn.type = TT_TOKEN;
-        tkn.isReady = true;
-      } else if (eol) {
-        // empty token return TT_EORECORD("")
-        //noop: tkn.content.append("");
-        tkn.type = TT_EORECORD;
-        tkn.isReady = true;
-      } else if (c == strategy.getEncapsulator()) {
-        // consume encapsulated token
-        encapsulatedTokenLexer(tkn, c);
-      } else if (isEndOfFile(c)) {
-        // end of file return TT_EOF()
-        //noop: tkn.content.append("");
-        tkn.type = TT_EOF;
-        tkn.isReady = true;
-      } else {
-        // next token must be a simple token
-        // add removed blanks when not ignoring whitespace chars...
-        if (!strategy.getIgnoreLeadingWhitespaces()) {
-          tkn.content.append(wsBuf);
-        }
-        simpleTokenLexer(tkn, c);
-      }
-    }
-    return tkn;  
-  }
-  
-  /**
-   * A simple token lexer
-   * 
-   * Simple token are tokens which are not surrounded by encapsulators.
-   * A simple token might contain escaped delimiters (as \, or \;). The
-   * token is finished when one of the following conditions become true:
-   * <ul>
-   *   <li>end of line has been reached (TT_EORECORD)</li>
-   *   <li>end of stream has been reached (TT_EOF)</li>
-   *   <li>an unescaped delimiter has been reached (TT_TOKEN)</li>
-   * </ul>
-   *  
-   * @param tkn  the current token
-   * @param c    the current character
-   * @return the filled token
-   * 
-   * @throws IOException on stream access error
-   */
-  private Token simpleTokenLexer(Token tkn, int c) throws IOException {
-    for (;;) {
-      if (isEndOfLine(c)) {
-        // end of record
-        tkn.type = TT_EORECORD;
-        tkn.isReady = true;
-        break;
-      } else if (isEndOfFile(c)) {
-        // end of file
-        tkn.type = TT_EOF;
-        tkn.isReady = true;
-        break;
-      } else if (c == strategy.getDelimiter()) {
-        // end of token
-        tkn.type = TT_TOKEN;
-        tkn.isReady = true;
-        break;
-      } else if (c == '\\' && strategy.getUnicodeEscapeInterpretation() && in.lookAhead() == 'u') {
-        // interpret unicode escaped chars (like \u0070 -> p)
-        tkn.content.append((char) unicodeEscapeLexer(c));
-      } else if (c == strategy.getEscape()) {
-        tkn.content.append((char)readEscape(c));
-      } else {
-        tkn.content.append((char) c);
-      }
-      
-      c = in.read();
-    }
-
-    if (strategy.getIgnoreTrailingWhitespaces()) {
-      tkn.content.trimTrailingWhitespace();
-    }
-
-    return tkn;
-  }
-  
-  
-  /**
-   * An encapsulated token lexer
-   * 
-   * Encapsulated tokens are surrounded by the given encapsulating-string.
-   * The encapsulator itself might be included in the token using a
-   * doubling syntax (as "", '') or using escaping (as in \", \').
-   * Whitespaces before and after an encapsulated token are ignored.
-   * 
-   * @param tkn    the current token
-   * @param c      the current character
-   * @return a valid token object
-   * @throws IOException on invalid state
-   */
-  private Token encapsulatedTokenLexer(Token tkn, int c) throws IOException {
-    // save current line
-    int startLineNumber = getLineNumber();
-    // ignore the given delimiter
-    // assert c == delimiter;
-    for (;;) {
-      c = in.read();
-
-      if (c == '\\' && strategy.getUnicodeEscapeInterpretation() && in.lookAhead()=='u') {
-        tkn.content.append((char) unicodeEscapeLexer(c));
-      } else if (c == strategy.getEscape()) {
-        tkn.content.append((char)readEscape(c));
-      } else if (c == strategy.getEncapsulator()) {
-        if (in.lookAhead() == strategy.getEncapsulator()) {
-          // double or escaped encapsulator -> add single encapsulator to token
-          c = in.read();
-          tkn.content.append((char) c);
-        } else {
-          // token finish mark (encapsulator) reached: ignore whitespace till delimiter
-          for (;;) {
+    /**
+     * A simple token lexer
+     * <p/>
+     * Simple token are tokens which are not surrounded by encapsulators.
+     * A simple token might contain escaped delimiters (as \, or \;). The
+     * token is finished when one of the following conditions become true:
+     * <ul>
+     * <li>end of line has been reached (TT_EORECORD)</li>
+     * <li>end of stream has been reached (TT_EOF)</li>
+     * <li>an unescaped delimiter has been reached (TT_TOKEN)</li>
+     * </ul>
+     *
+     * @param tkn the current token
+     * @param c   the current character
+     * @return the filled token
+     * @throws IOException on stream access error
+     */
+    private Token simpleTokenLexer(Token tkn, int c) throws IOException {
+        for (; ;) {
+            if (isEndOfLine(c)) {
+                // end of record
+                tkn.type = TT_EORECORD;
+                tkn.isReady = true;
+                break;
+            } else if (isEndOfFile(c)) {
+                // end of file
+                tkn.type = TT_EOF;
+                tkn.isReady = true;
+                break;
+            } else if (c == strategy.getDelimiter()) {
+                // end of token
+                tkn.type = TT_TOKEN;
+                tkn.isReady = true;
+                break;
+            } else if (c == '\\' && strategy.getUnicodeEscapeInterpretation() && in.lookAhead() == 'u') {
+                // interpret unicode escaped chars (like \u0070 -> p)
+                tkn.content.append((char) unicodeEscapeLexer(c));
+            } else if (c == strategy.getEscape()) {
+                tkn.content.append((char) readEscape(c));
+            } else {
+                tkn.content.append((char) c);
+            }
+
             c = in.read();
-            if (c == strategy.getDelimiter()) {
-              tkn.type = TT_TOKEN;
-              tkn.isReady = true;
-              return tkn;
+        }
+
+        if (strategy.getIgnoreTrailingWhitespaces()) {
+            tkn.content.trimTrailingWhitespace();
+        }
+
+        return tkn;
+    }
+
+
+    /**
+     * An encapsulated token lexer
+     * <p/>
+     * Encapsulated tokens are surrounded by the given encapsulating-string.
+     * The encapsulator itself might be included in the token using a
+     * doubling syntax (as "", '') or using escaping (as in \", \').
+     * Whitespaces before and after an encapsulated token are ignored.
+     *
+     * @param tkn the current token
+     * @param c   the current character
+     * @return a valid token object
+     * @throws IOException on invalid state
+     */
+    private Token encapsulatedTokenLexer(Token tkn, int c) throws IOException {
+        // save current line
+        int startLineNumber = getLineNumber();
+        // ignore the given delimiter
+        // assert c == delimiter;
+        for (; ;) {
+            c = in.read();
+
+            if (c == '\\' && strategy.getUnicodeEscapeInterpretation() && in.lookAhead() == 'u') {
+                tkn.content.append((char) unicodeEscapeLexer(c));
+            } else if (c == strategy.getEscape()) {
+                tkn.content.append((char) readEscape(c));
+            } else if (c == strategy.getEncapsulator()) {
+                if (in.lookAhead() == strategy.getEncapsulator()) {
+                    // double or escaped encapsulator -> add single encapsulator to token
+                    c = in.read();
+                    tkn.content.append((char) c);
+                } else {
+                    // token finish mark (encapsulator) reached: ignore whitespace till delimiter
+                    for (; ;) {
+                        c = in.read();
+                        if (c == strategy.getDelimiter()) {
+                            tkn.type = TT_TOKEN;
+                            tkn.isReady = true;
+                            return tkn;
+                        } else if (isEndOfFile(c)) {
+                            tkn.type = TT_EOF;
+                            tkn.isReady = true;
+                            return tkn;
+                        } else if (isEndOfLine(c)) {
+                            // ok eo token reached
+                            tkn.type = TT_EORECORD;
+                            tkn.isReady = true;
+                            return tkn;
+                        } else if (!isWhitespace(c)) {
+                            // error invalid char between token and next delimiter
+                            throw new IOException(
+                                    "(line " + getLineNumber()
+                                            + ") invalid char between encapsulated token end delimiter"
+                            );
+                        }
+                    }
+                }
             } else if (isEndOfFile(c)) {
-              tkn.type = TT_EOF;
-              tkn.isReady = true;
-              return tkn;
-            } else if (isEndOfLine(c)) {
-              // ok eo token reached
-              tkn.type = TT_EORECORD;
-              tkn.isReady = true;
-              return tkn;
-            } else if (!isWhitespace(c)) {
-              // error invalid char between token and next delimiter
-              throw new IOException(
-                      "(line " + getLineNumber()
-                              + ") invalid char between encapsulated token end delimiter"
-              );
+                // error condition (end of file before end of token)
+                throw new IOException(
+                        "(startline " + startLineNumber + ")"
+                                + "eof reached before encapsulated token finished"
+                );
+            } else {
+                // consume character
+                tkn.content.append((char) c);
+            }
+        }
+    }
+
+
+    /**
+     * Decodes Unicode escapes.
+     * <p/>
+     * Interpretation of "\\uXXXX" escape sequences
+     * where XXXX is a hex-number.
+     *
+     * @param c current char which is discarded because it's the "\\" of "\\uXXXX"
+     * @return the decoded character
+     * @throws IOException on wrong unicode escape sequence or read error
+     */
+    protected int unicodeEscapeLexer(int c) throws IOException {
+        int ret = 0;
+        // ignore 'u' (assume c==\ now) and read 4 hex digits
+        c = in.read();
+        code.clear();
+        try {
+            for (int i = 0; i < 4; i++) {
+                c = in.read();
+                if (isEndOfFile(c) || isEndOfLine(c)) {
+                    throw new NumberFormatException("number too short");
+                }
+                code.append((char) c);
             }
-          }
+            ret = Integer.parseInt(code.toString(), 16);
+        } catch (NumberFormatException e) {
+            throw new IOException(
+                    "(line " + getLineNumber() + ") Wrong unicode escape sequence found '"
+                            + code.toString() + "'" + e.toString());
         }
-      } else if (isEndOfFile(c)) {
-        // error condition (end of file before end of token)
-        throw new IOException(
-                "(startline " + startLineNumber + ")"
-                        + "eof reached before encapsulated token finished"
-        );
-      } else {
-        // consume character
-        tkn.content.append((char) c);
-      }
-    }
-  }
-  
-  
-  /**
-   * Decodes Unicode escapes.
-   * 
-   * Interpretation of "\\uXXXX" escape sequences
-   * where XXXX is a hex-number.
-   * @param c current char which is discarded because it's the "\\" of "\\uXXXX"
-   * @return the decoded character
-   * @throws IOException on wrong unicode escape sequence or read error
-   */
-  protected int unicodeEscapeLexer(int c) throws IOException {
-    int ret = 0;
-    // ignore 'u' (assume c==\ now) and read 4 hex digits
-    c = in.read();
-    code.clear();
-    try {
-      for (int i = 0; i < 4; i++) {
-        c  = in.read();
-        if (isEndOfFile(c) || isEndOfLine(c)) {
-          throw new NumberFormatException("number too short");
-        }
-        code.append((char) c);
-      }
-      ret = Integer.parseInt(code.toString(), 16);
-    } catch (NumberFormatException e) {
-      throw new IOException(
-        "(line " + getLineNumber() + ") Wrong unicode escape sequence found '" 
-        + code.toString() + "'" + e.toString());
-    }
-    return ret;
-  }
-
-  private int readEscape(int c) throws IOException {
-    // assume c is the escape char (normally a backslash)
-    c = in.read();
-    int out;
-    switch (c) {
-      case 'r': out='\r'; break;
-      case 'n': out='\n'; break;
-      case 't': out='\t'; break;
-      case 'b': out='\b'; break;
-      case 'f': out='\f'; break;
-      default : out=c;
-    }
-    return out;
-  }
-  
-  // ======================================================
-  //  strategies
-  // ======================================================
-  
-  /**
-   * Obtain the specified CSV Strategy.  This should not be modified.
-   * 
-   * @return strategy currently being used
-   */
-  public CSVStrategy getStrategy() {
-    return this.strategy;
-  }
-  
-  // ======================================================
-  //  Character class checker
-  // ======================================================
-  
-  /**
-   * @return true if the given char is a whitespace character
-   */
-  private boolean isWhitespace(int c) {
-    return Character.isWhitespace((char) c) && (c != strategy.getDelimiter());
-  }
-  
-  /**
-   * Greedy - accepts \n, \r and \r\n 
-   * This checker consumes silently the second control-character...
-   * 
-   * @return true if the given character is a line-terminator
-   */
-  private boolean isEndOfLine(int c) throws IOException {
-    // check if we have \r\n...
-    if (c == '\r') {
-      if (in.lookAhead() == '\n') {
-        // note: does not change c outside of this method !!
+        return ret;
+    }
+
+    private int readEscape(int c) throws IOException {
+        // assume c is the escape char (normally a backslash)
         c = in.read();
-      }
+        int out;
+        switch (c) {
+            case 'r':
+                out = '\r';
+                break;
+            case 'n':
+                out = '\n';
+                break;
+            case 't':
+                out = '\t';
+                break;
+            case 'b':
+                out = '\b';
+                break;
+            case 'f':
+                out = '\f';
+                break;
+            default:
+                out = c;
+        }
+        return out;
+    }
+
+    // ======================================================
+    //  strategies
+    // ======================================================
+
+    /**
+     * Obtain the specified CSV Strategy.  This should not be modified.
+     *
+     * @return strategy currently being used
+     */
+    public CSVStrategy getStrategy() {
+        return this.strategy;
+    }
+
+    // ======================================================
+    //  Character class checker
+    // ======================================================
+
+    /**
+     * @return true if the given char is a whitespace character
+     */
+    private boolean isWhitespace(int c) {
+        return Character.isWhitespace((char) c) && (c != strategy.getDelimiter());
+    }
+
+    /**
+     * Greedy - accepts \n, \r and \r\n
+     * This checker consumes silently the second control-character...
+     *
+     * @return true if the given character is a line-terminator
+     */
+    private boolean isEndOfLine(int c) throws IOException {
+        // check if we have \r\n...
+        if (c == '\r') {
+            if (in.lookAhead() == '\n') {
+                // note: does not change c outside of this method !!
+                c = in.read();
+            }
+        }
+        return (c == '\n' || c == '\r');
+    }
+
+    /**
+     * @return true if the given character indicates end of file
+     */
+    private boolean isEndOfFile(int c) {
+        return c == ExtendedBufferedReader.END_OF_STREAM;
     }
-    return (c == '\n' || c == '\r');
-  }
-  
-  /**
-   * @return true if the given character indicates end of file
-   */
-  private boolean isEndOfFile(int c) {
-    return c == ExtendedBufferedReader.END_OF_STREAM;
-  }
 }

Modified: commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/CSVPrinter.java
URL: http://svn.apache.org/viewvc/commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/CSVPrinter.java?rev=1065950&r1=1065949&r2=1065950&view=diff
==============================================================================
--- commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/CSVPrinter.java (original)
+++ commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/CSVPrinter.java Tue Feb  1 08:46:00 2011
@@ -26,282 +26,289 @@ import java.io.Writer;
  */
 public class CSVPrinter {
 
-  /** The place that the values get written. */
-  protected final Writer out;
-  protected final CSVStrategy strategy;
-
-  /** True if we just began a new line. */
-  protected boolean newLine = true;
-
-  protected char[] buf = new char[0];  // temporary buffer
-
-  /**
-   * Create a printer that will print values to the given
-   * stream following the CSVStrategy.
-   *
-   * Currently, only a pure encapsulation strategy or a pure escaping strategy
-   * is supported.  Hybrid strategies (encapsulation and escaping with a different character) are not supported.
-   *
-   * @param out stream to which to print.
-   * @param strategy describes the CSV variation.
-   */
-  public CSVPrinter(Writer out, CSVStrategy strategy) {
-    this.out = out;
-    this.strategy = strategy==null ? CSVStrategy.DEFAULT_STRATEGY : strategy;
-  }
-  
-  // ======================================================
-  //  printing implementation
-  // ======================================================
-
-  /**
-   * Output a blank line
-   */
-  public void println() throws IOException {
-    out.write(strategy.getPrinterNewline());
-    newLine = true;
-  }
-
-  public void flush() throws IOException {
-    out.flush();
-  }
-
-
-  /**
-   * Print a single line of comma separated values.
-   * The values will be quoted if needed.  Quotes and
-   * newLine characters will be escaped.
-   *
-   * @param values values to be outputted.
-   */
-  public void println(String[] values) throws IOException {
-    for (int i = 0; i < values.length; i++) {
-      print(values[i]);
-    }
-    println();
-  }
-
-
-  /**
-   * Put a comment among the comma separated values.
-   * Comments will always begin on a new line and occupy a
-   * least one full line. The character specified to star
-   * comments and a space will be inserted at the beginning of
-   * each new line in the comment.
-   *
-   * @param comment the comment to output
-   */
-  public void printlnComment(String comment) throws IOException {
-    if(this.strategy.isCommentingDisabled()) {
-        return;
-    }
-    if (!newLine) {
-      println();
-    }
-    out.write(this.strategy.getCommentStart());
-    out.write(' ');
-    for (int i = 0; i < comment.length(); i++) {
-      char c = comment.charAt(i);
-      switch (c) {
-        case '\r' :
-          if (i + 1 < comment.length() && comment.charAt(i + 1) == '\n') {
-            i++;
-          }
-          // break intentionally excluded.
-        case '\n' :
-          println();
-          out.write(this.strategy.getCommentStart());
-          out.write(' ');
-          break;
-        default :
-          out.write(c);
-          break;
-      }
-    }
-    println();
-  }
-
-
-  public void print(char[] value, int offset, int len, boolean checkForEscape) throws IOException {
-    if (!checkForEscape) {
-      printSep();
-      out.write(value, offset, len);
-      return;
-    }
-
-    if (strategy.getEncapsulator() != CSVStrategy.ENCAPSULATOR_DISABLED) {
-      printAndEncapsulate(value, offset, len);
-    } else if (strategy.getEscape() != CSVStrategy.ESCAPE_DISABLED) {
-      printAndEscape(value, offset, len);
-    } else {
-      printSep();
-      out.write(value, offset, len);
-    }
-  }
-
-  void printSep() throws IOException {
-    if (newLine) {
-      newLine = false;
-    } else {
-      out.write(this.strategy.getDelimiter());
-    }
-  }
-
-  void printAndEscape(char[] value, int offset, int len) throws IOException {
-    int start = offset;
-    int pos = offset;
-    int end = offset + len;
-
-    printSep();
-
-    char delim = this.strategy.getDelimiter();
-    char escape = this.strategy.getEscape();
-
-    while (pos < end) {
-      char c = value[pos];
-      if (c == '\r' || c=='\n' || c==delim || c==escape) {
-        // write out segment up until this char
-        int l = pos-start;
-        if (l>0) {
-          out.write(value, start, l);
-        }
-        if (c=='\n') c='n';
-        else if (c=='\r') c='r';
-
-        out.write(escape);
-        out.write(c);
-
-        start = pos+1; // start on the current char after this one
-      }
-
-      pos++;
-    }
-
-    // write last segment
-    int l = pos-start;
-    if (l>0) {
-      out.write(value, start, l);      
-    }
-  }
-
-  void printAndEncapsulate(char[] value, int offset, int len) throws IOException {
-    boolean first = newLine;  // is this the first value on this line?
-    boolean quote = false;
-    int start = offset;
-    int pos = offset;
-    int end = offset + len;
-
-    printSep();    
-
-    char delim = this.strategy.getDelimiter();
-    char encapsulator = this.strategy.getEncapsulator();
-
-    if (len <= 0) {
-      // always quote an empty token that is the first
-      // on the line, as it may be the only thing on the
-      // line. If it were not quoted in that case,
-      // an empty line has no tokens.
-      if (first) {
-        quote = true;
-      }
-    } else {
-      char c = value[pos];
-
-      // Hmmm, where did this rule come from?
-      if (first
-          && (c < '0'
-          || (c > '9' && c < 'A')
-          || (c > 'Z' && c < 'a')
-          || (c > 'z'))) {
-        quote = true;
-      // } else if (c == ' ' || c == '\f' || c == '\t') {
-      } else if (c <= '#') {
-        // Some other chars at the start of a value caused the parser to fail, so for now
-        // encapsulate if we start in anything less than '#'.  We are being conservative
-        // by including the default comment char too.
-        quote = true;
-      } else {
+    /**
+     * The place that the values get written.
+     */
+    protected final Writer out;
+    protected final CSVStrategy strategy;
+
+    /**
+     * True if we just began a new line.
+     */
+    protected boolean newLine = true;
+
+    protected char[] buf = new char[0];  // temporary buffer
+
+    /**
+     * Create a printer that will print values to the given
+     * stream following the CSVStrategy.
+     * <p/>
+     * Currently, only a pure encapsulation strategy or a pure escaping strategy
+     * is supported.  Hybrid strategies (encapsulation and escaping with a different character) are not supported.
+     *
+     * @param out      stream to which to print.
+     * @param strategy describes the CSV variation.
+     */
+    public CSVPrinter(Writer out, CSVStrategy strategy) {
+        this.out = out;
+        this.strategy = strategy == null ? CSVStrategy.DEFAULT_STRATEGY : strategy;
+    }
+
+    // ======================================================
+    //  printing implementation
+    // ======================================================
+
+    /**
+     * Output a blank line
+     */
+    public void println() throws IOException {
+        out.write(strategy.getPrinterNewline());
+        newLine = true;
+    }
+
+    public void flush() throws IOException {
+        out.flush();
+    }
+
+
+    /**
+     * Print a single line of comma separated values.
+     * The values will be quoted if needed.  Quotes and
+     * newLine characters will be escaped.
+     *
+     * @param values values to be outputted.
+     */
+    public void println(String[] values) throws IOException {
+        for (int i = 0; i < values.length; i++) {
+            print(values[i]);
+        }
+        println();
+    }
+
+
+    /**
+     * Put a comment among the comma separated values.
+     * Comments will always begin on a new line and occupy a
+     * least one full line. The character specified to star
+     * comments and a space will be inserted at the beginning of
+     * each new line in the comment.
+     *
+     * @param comment the comment to output
+     */
+    public void printlnComment(String comment) throws IOException {
+        if (this.strategy.isCommentingDisabled()) {
+            return;
+        }
+        if (!newLine) {
+            println();
+        }
+        out.write(this.strategy.getCommentStart());
+        out.write(' ');
+        for (int i = 0; i < comment.length(); i++) {
+            char c = comment.charAt(i);
+            switch (c) {
+                case '\r':
+                    if (i + 1 < comment.length() && comment.charAt(i + 1) == '\n') {
+                        i++;
+                    }
+                    // break intentionally excluded.
+                case '\n':
+                    println();
+                    out.write(this.strategy.getCommentStart());
+                    out.write(' ');
+                    break;
+                default:
+                    out.write(c);
+                    break;
+            }
+        }
+        println();
+    }
+
+
+    public void print(char[] value, int offset, int len, boolean checkForEscape) throws IOException {
+        if (!checkForEscape) {
+            printSep();
+            out.write(value, offset, len);
+            return;
+        }
+
+        if (strategy.getEncapsulator() != CSVStrategy.ENCAPSULATOR_DISABLED) {
+            printAndEncapsulate(value, offset, len);
+        } else if (strategy.getEscape() != CSVStrategy.ESCAPE_DISABLED) {
+            printAndEscape(value, offset, len);
+        } else {
+            printSep();
+            out.write(value, offset, len);
+        }
+    }
+
+    void printSep() throws IOException {
+        if (newLine) {
+            newLine = false;
+        } else {
+            out.write(this.strategy.getDelimiter());
+        }
+    }
+
+    void printAndEscape(char[] value, int offset, int len) throws IOException {
+        int start = offset;
+        int pos = offset;
+        int end = offset + len;
+
+        printSep();
+
+        char delim = this.strategy.getDelimiter();
+        char escape = this.strategy.getEscape();
+
         while (pos < end) {
-          c = value[pos];
-          if (c=='\n' || c=='\r' || c==encapsulator || c==delim) {
-            quote = true;
-            break;
-          }
-          pos++;
+            char c = value[pos];
+            if (c == '\r' || c == '\n' || c == delim || c == escape) {
+                // write out segment up until this char
+                int l = pos - start;
+                if (l > 0) {
+                    out.write(value, start, l);
+                }
+                if (c == '\n') {
+                    c = 'n';
+                } else if (c == '\r') {
+                    c = 'r';
+                }
+
+                out.write(escape);
+                out.write(c);
+
+                start = pos + 1; // start on the current char after this one
+            }
+
+            pos++;
+        }
+
+        // write last segment
+        int l = pos - start;
+        if (l > 0) {
+            out.write(value, start, l);
+        }
+    }
+
+    void printAndEncapsulate(char[] value, int offset, int len) throws IOException {
+        boolean first = newLine;  // is this the first value on this line?
+        boolean quote = false;
+        int start = offset;
+        int pos = offset;
+        int end = offset + len;
+
+        printSep();
+
+        char delim = this.strategy.getDelimiter();
+        char encapsulator = this.strategy.getEncapsulator();
+
+        if (len <= 0) {
+            // always quote an empty token that is the first
+            // on the line, as it may be the only thing on the
+            // line. If it were not quoted in that case,
+            // an empty line has no tokens.
+            if (first) {
+                quote = true;
+            }
+        } else {
+            char c = value[pos];
+
+            // Hmmm, where did this rule come from?
+            if (first
+                    && (c < '0'
+                    || (c > '9' && c < 'A')
+                    || (c > 'Z' && c < 'a')
+                    || (c > 'z'))) {
+                quote = true;
+                // } else if (c == ' ' || c == '\f' || c == '\t') {
+            } else if (c <= '#') {
+                // Some other chars at the start of a value caused the parser to fail, so for now
+                // encapsulate if we start in anything less than '#'.  We are being conservative
+                // by including the default comment char too.
+                quote = true;
+            } else {
+                while (pos < end) {
+                    c = value[pos];
+                    if (c == '\n' || c == '\r' || c == encapsulator || c == delim) {
+                        quote = true;
+                        break;
+                    }
+                    pos++;
+                }
+
+                if (!quote) {
+                    pos = end - 1;
+                    c = value[pos];
+                    // if (c == ' ' || c == '\f' || c == '\t') {
+                    // Some other chars at the end caused the parser to fail, so for now
+                    // encapsulate if we end in anything less than ' '
+                    if (c <= ' ') {
+                        quote = true;
+                    }
+                }
+            }
         }
 
         if (!quote) {
-          pos = end-1;
-          c = value[pos];
-          // if (c == ' ' || c == '\f' || c == '\t') {
-          // Some other chars at the end caused the parser to fail, so for now
-          // encapsulate if we end in anything less than ' '
-          if (c <= ' ') {
-            quote = true;
-          }
-        }
-      }
-    }
-
-    if (!quote) {
-      // no encapsulation needed - write out the original value
-      out.write(value, offset, len);
-      return;
-    }
-
-    // we hit something that needed encapsulation
-    out.write(encapsulator);
-
-    // Pick up where we left off: pos should be positioned on the first character that caused
-    // the need for encapsulation.
-    while (pos<end) {
-      char c = value[pos];
-      if (c==encapsulator) {
-        // write out the chunk up until this point
-
-        // add 1 to the length to write out the encapsulator also
-        out.write(value, start, pos-start+1);
-        // put the next starting position on the encapsulator so we will
-        // write it out again with the next string (effectively doubling it)
-        start = pos;
-      }
-      pos++;
-    }
-
-    // write the last segment
-    out.write(value, start, pos-start);
-    out.write(encapsulator);    
-  }
-
-  /**
-   * Print the string as the next value on the line. The value
-   * will be escaped or encapsulated as needed if checkForEscape==true
-   *
-   * @param value value to be outputted.
-   */
-  public void print(String value, boolean checkForEscape) throws IOException {
-    if (!checkForEscape) {
-      // write directly from string
-      printSep();
-      out.write(value);
-      return;
-    }
-
-    if (buf.length < value.length()) {
-      buf = new char[value.length()];
-    }
-
-    value.getChars(0, value.length(), buf, 0);
-    print(buf, 0, value.length(), checkForEscape);
-  }
-
-  /**
-   * Print the string as the next value on the line. The value
-   * will be escaped or encapsulated as needed.
-   *
-   * @param value value to be outputted.
-   */
-  public void print(String value) throws IOException {
-    print(value, true);   
-  }
+            // no encapsulation needed - write out the original value
+            out.write(value, offset, len);
+            return;
+        }
+
+        // we hit something that needed encapsulation
+        out.write(encapsulator);
+
+        // Pick up where we left off: pos should be positioned on the first character that caused
+        // the need for encapsulation.
+        while (pos < end) {
+            char c = value[pos];
+            if (c == encapsulator) {
+                // write out the chunk up until this point
+
+                // add 1 to the length to write out the encapsulator also
+                out.write(value, start, pos - start + 1);
+                // put the next starting position on the encapsulator so we will
+                // write it out again with the next string (effectively doubling it)
+                start = pos;
+            }
+            pos++;
+        }
+
+        // write the last segment
+        out.write(value, start, pos - start);
+        out.write(encapsulator);
+    }
+
+    /**
+     * Print the string as the next value on the line. The value
+     * will be escaped or encapsulated as needed if checkForEscape==true
+     *
+     * @param value value to be outputted.
+     */
+    public void print(String value, boolean checkForEscape) throws IOException {
+        if (!checkForEscape) {
+            // write directly from string
+            printSep();
+            out.write(value);
+            return;
+        }
+
+        if (buf.length < value.length()) {
+            buf = new char[value.length()];
+        }
+
+        value.getChars(0, value.length(), buf, 0);
+        print(buf, 0, value.length(), checkForEscape);
+    }
+
+    /**
+     * Print the string as the next value on the line. The value
+     * will be escaped or encapsulated as needed.
+     *
+     * @param value value to be outputted.
+     */
+    public void print(String value) throws IOException {
+        print(value, true);
+    }
 }

Modified: commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/CSVStrategy.java
URL: http://svn.apache.org/viewvc/commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/CSVStrategy.java?rev=1065950&r1=1065949&r2=1065950&view=diff
==============================================================================
--- commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/CSVStrategy.java (original)
+++ commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/CSVStrategy.java Tue Feb  1 08:46:00 2011
@@ -20,7 +20,7 @@ import java.io.Serializable;
 
 /**
  * CSVStrategy
- * 
+ *
  * Represents the strategy for a CSV.
  */
 public class CSVStrategy implements Cloneable, Serializable {
@@ -41,47 +41,46 @@ public class CSVStrategy implements Clon
     // an EOF signal (-1), and because \ufffe in UTF-16 would be
     // encoded as two chars (using surrogates) and thus there should never
     // be a collision with a real text char.
-    public static char COMMENTS_DISABLED       = (char)-2;
-    public static char ESCAPE_DISABLED         = (char)-2;
-    public static char ENCAPSULATOR_DISABLED   = (char)-2;
-
-    public static CSVStrategy DEFAULT_STRATEGY = new CSVStrategy(',', '"', COMMENTS_DISABLED, ESCAPE_DISABLED, true, 
-                                                                 true, false, true);
-    public static CSVStrategy EXCEL_STRATEGY   = new CSVStrategy(',', '"', COMMENTS_DISABLED, ESCAPE_DISABLED, false, 
-                                                                 false, false, false);
-    public static CSVStrategy TDF_STRATEGY     = new CSVStrategy('\t', '"', COMMENTS_DISABLED, ESCAPE_DISABLED, true, 
-                                                                 true, false, true);
+    public static char COMMENTS_DISABLED = (char) -2;
+    public static char ESCAPE_DISABLED = (char) -2;
+    public static char ENCAPSULATOR_DISABLED = (char) -2;
+
+    public static CSVStrategy DEFAULT_STRATEGY = new CSVStrategy(',', '"', COMMENTS_DISABLED, ESCAPE_DISABLED, true,
+            true, false, true);
+    public static CSVStrategy EXCEL_STRATEGY = new CSVStrategy(',', '"', COMMENTS_DISABLED, ESCAPE_DISABLED, false,
+            false, false, false);
+    public static CSVStrategy TDF_STRATEGY = new CSVStrategy('\t', '"', COMMENTS_DISABLED, ESCAPE_DISABLED, true,
+            true, false, true);
 
 
     public CSVStrategy(char delimiter, char encapsulator, char commentStart) {
         this(delimiter, encapsulator, commentStart, true, false, true);
     }
-  
+
     /**
      * Customized CSV strategy setter.
      *
-     * @param delimiter a Char used for value separation
-     * @param encapsulator a Char used as value encapsulation marker
-     * @param commentStart a Char used for comment identification
-     * @param escape a Char used to escape special characters in values
-     * @param ignoreLeadingWhitespace TRUE when leading whitespaces should be
-     *                                ignored
+     * @param delimiter                a Char used for value separation
+     * @param encapsulator             a Char used as value encapsulation marker
+     * @param commentStart             a Char used for comment identification
+     * @param escape                   a Char used to escape special characters in values
+     * @param ignoreLeadingWhitespace  TRUE when leading whitespaces should be
+     *                                 ignored
      * @param ignoreTrailingWhitespace TRUE when trailing whitespaces should be
-     *                                ignored
-     * @param interpretUnicodeEscapes TRUE when unicode escapes should be
-     *                                interpreted
-     * @param ignoreEmptyLines TRUE when the parser should skip emtpy lines
+     *                                 ignored
+     * @param interpretUnicodeEscapes  TRUE when unicode escapes should be
+     *                                 interpreted
+     * @param ignoreEmptyLines         TRUE when the parser should skip emtpy lines
      */
     public CSVStrategy(
-        char delimiter, 
-        char encapsulator, 
-        char commentStart,
-        char escape,
-        boolean ignoreLeadingWhitespace, 
-        boolean ignoreTrailingWhitespace, 
-        boolean interpretUnicodeEscapes,
-        boolean ignoreEmptyLines) 
-    {
+            char delimiter,
+            char encapsulator,
+            char commentStart,
+            char escape,
+            boolean ignoreLeadingWhitespace,
+            boolean ignoreTrailingWhitespace,
+            boolean interpretUnicodeEscapes,
+            boolean ignoreEmptyLines) {
         setDelimiter(delimiter);
         setEncapsulator(encapsulator);
         setCommentStart(commentStart);
@@ -92,62 +91,101 @@ public class CSVStrategy implements Clon
         setIgnoreEmptyLines(ignoreEmptyLines);
     }
 
-    /** @deprecated */
+    /**
+     * @deprecated
+     */
     public CSVStrategy(
-        char delimiter,
-        char encapsulator,
-        char commentStart,
-        boolean ignoreLeadingWhitespace,
-        boolean interpretUnicodeEscapes,
-        boolean ignoreEmptyLines)
-    {
-        this(delimiter, encapsulator, commentStart, CSVStrategy.ESCAPE_DISABLED, ignoreLeadingWhitespace, 
-             true, interpretUnicodeEscapes, ignoreEmptyLines);
+            char delimiter,
+            char encapsulator,
+            char commentStart,
+            boolean ignoreLeadingWhitespace,
+            boolean interpretUnicodeEscapes,
+            boolean ignoreEmptyLines) {
+        this(delimiter, encapsulator, commentStart, CSVStrategy.ESCAPE_DISABLED, ignoreLeadingWhitespace,
+                true, interpretUnicodeEscapes, ignoreEmptyLines);
+    }
+
+    public void setDelimiter(char delimiter) {
+        this.delimiter = delimiter;
+    }
+
+    public char getDelimiter() {
+        return this.delimiter;
     }
 
-    public void setDelimiter(char delimiter) { this.delimiter = delimiter; }
-    public char getDelimiter() { return this.delimiter; }
+    public void setEncapsulator(char encapsulator) {
+        this.encapsulator = encapsulator;
+    }
 
-    public void setEncapsulator(char encapsulator) { this.encapsulator = encapsulator; }
-    public char getEncapsulator() { return this.encapsulator; }
+    public char getEncapsulator() {
+        return this.encapsulator;
+    }
 
-    public void setCommentStart(char commentStart) { this.commentStart = commentStart; }
-    public char getCommentStart() { return this.commentStart; }
-    public boolean isCommentingDisabled() { return this.commentStart == COMMENTS_DISABLED; }
+    public void setCommentStart(char commentStart) {
+        this.commentStart = commentStart;
+    }
 
-    public void setEscape(char escape) { this.escape = escape; }
-    public char getEscape() { return this.escape; }
+    public char getCommentStart() {
+        return this.commentStart;
+    }
 
-    public void setIgnoreLeadingWhitespaces(boolean ignoreLeadingWhitespaces) { 
-        this.ignoreLeadingWhitespaces = ignoreLeadingWhitespaces; 
+    public boolean isCommentingDisabled() {
+        return this.commentStart == COMMENTS_DISABLED;
     }
-    public boolean getIgnoreLeadingWhitespaces() { return this.ignoreLeadingWhitespaces; }
 
-    public void setIgnoreTrailingWhitespaces(boolean ignoreTrailingWhitespaces) { 
-        this.ignoreTrailingWhitespaces = ignoreTrailingWhitespaces; 
+    public void setEscape(char escape) {
+        this.escape = escape;
     }
-    public boolean getIgnoreTrailingWhitespaces() { return this.ignoreTrailingWhitespaces; }
 
-    public void setUnicodeEscapeInterpretation(boolean interpretUnicodeEscapes) { 
-        this.interpretUnicodeEscapes = interpretUnicodeEscapes; 
+    public char getEscape() {
+        return this.escape;
     }
-    public boolean getUnicodeEscapeInterpretation() { return this.interpretUnicodeEscapes; }
 
-    public void setIgnoreEmptyLines(boolean ignoreEmptyLines) { this.ignoreEmptyLines = ignoreEmptyLines; }
-    public boolean getIgnoreEmptyLines() { return this.ignoreEmptyLines; }
+    public void setIgnoreLeadingWhitespaces(boolean ignoreLeadingWhitespaces) {
+        this.ignoreLeadingWhitespaces = ignoreLeadingWhitespaces;
+    }
+
+    public boolean getIgnoreLeadingWhitespaces() {
+        return this.ignoreLeadingWhitespaces;
+    }
+
+    public void setIgnoreTrailingWhitespaces(boolean ignoreTrailingWhitespaces) {
+        this.ignoreTrailingWhitespaces = ignoreTrailingWhitespaces;
+    }
+
+    public boolean getIgnoreTrailingWhitespaces() {
+        return this.ignoreTrailingWhitespaces;
+    }
+
+    public void setUnicodeEscapeInterpretation(boolean interpretUnicodeEscapes) {
+        this.interpretUnicodeEscapes = interpretUnicodeEscapes;
+    }
+
+    public boolean getUnicodeEscapeInterpretation() {
+        return this.interpretUnicodeEscapes;
+    }
+
+    public void setIgnoreEmptyLines(boolean ignoreEmptyLines) {
+        this.ignoreEmptyLines = ignoreEmptyLines;
+    }
+
+    public boolean getIgnoreEmptyLines() {
+        return this.ignoreEmptyLines;
+    }
 
     public void setPrinterNewline(String newline) {
-      this.printerNewline = newline;
+        this.printerNewline = newline;
     }
+
     public String getPrinterNewline() {
-      return this.printerNewline;
+        return this.printerNewline;
     }
 
     public Object clone() {
-      try {
-        return super.clone();
-      } catch (CloneNotSupportedException e) {
-        throw new RuntimeException(e);  // impossible
-      }
+        try {
+            return super.clone();
+        } catch (CloneNotSupportedException e) {
+            throw new RuntimeException(e);  // impossible
+        }
     }
 }

Modified: commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/CSVUtils.java
URL: http://svn.apache.org/viewvc/commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/CSVUtils.java?rev=1065950&r1=1065949&r2=1065950&view=diff
==============================================================================
--- commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/CSVUtils.java (original)
+++ commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/CSVUtils.java Tue Feb  1 08:46:00 2011
@@ -30,14 +30,14 @@ public class CSVUtils {
 
     /**
      * <p><code>CSVUtils</code> instances should NOT be constructed in
-     * standard programming. 
+     * standard programming.
      *
      * <p>This constructor is public to permit tools that require a JavaBean
      * instance to operate.</p>
      */
     public CSVUtils() {
     }
-  
+
     /**
      * Converts an array of string values into a single CSV line. All
      * <code>null</code> values are converted to the string <code>"null"</code>,
@@ -46,13 +46,13 @@ public class CSVUtils {
      *
      * @param values the value array
      * @return the CSV string, will be an empty string if the length of the
-     * value array is 0
+     *         value array is 0
      */
     public static String printLine(String[] values, CSVStrategy strategy) {
         // set up a CSVUtils
         StringWriter stringWriter = new StringWriter();
         CSVPrinter csvPrinter = new CSVPrinter(stringWriter, strategy);
-  
+
         // check for null values an "null" as strings and convert them
         // into the strings "null" and "\"null\""
         for (int i = 0; i < values.length; i++) {
@@ -62,60 +62,60 @@ public class CSVUtils {
                 values[i] = "\"null\"";
             }
         }
-  
+
         // convert to CSV
         try {
-          csvPrinter.println(values);
+            csvPrinter.println(values);
         } catch (IOException e) {
-          // should not happen with StringWriter
+            // should not happen with StringWriter
         }
         // as the resulting string has \r\n at the end, we will trim that away
         return stringWriter.toString().trim();
     }
-  
-  // ======================================================
-  //  static parsers
-  // ======================================================
-  
-  /**
-   * Parses the given String according to the default {@link CSVStrategy}.
-   * 
-   * @param s CSV String to be parsed.
-   * @return parsed String matrix (which is never null)
-   * @throws IOException in case of error
-   */
-  public static String[][] parse(String s) throws IOException {
-    if (s == null) {
-      throw new IllegalArgumentException("Null argument not allowed.");
-    }
-    String[][] result = (new CSVParser(new StringReader(s))).getAllValues();
-    if (result == null) {
-      // since CSVStrategy ignores empty lines an empty array is returned
-      // (i.e. not "result = new String[][] {{""}};")
-      result = EMPTY_DOUBLE_STRING_ARRAY;
-    }
-    return result;
-  }
-  
-  /**
-   * Parses the first line only according to the default {@link CSVStrategy}.
-   * 
-   * Parsing empty string will be handled as valid records containing zero
-   * elements, so the following property holds: parseLine("").length == 0.
-   * 
-   * @param s CSV String to be parsed.
-   * @return parsed String vector (which is never null)
-   * @throws IOException in case of error
-   */
-  public static String[] parseLine(String s) throws IOException {
-    if (s == null) {
-      throw new IllegalArgumentException("Null argument not allowed.");
+
+    // ======================================================
+    //  static parsers
+    // ======================================================
+
+    /**
+     * Parses the given String according to the default {@link CSVStrategy}.
+     *
+     * @param s CSV String to be parsed.
+     * @return parsed String matrix (which is never null)
+     * @throws IOException in case of error
+     */
+    public static String[][] parse(String s) throws IOException {
+        if (s == null) {
+            throw new IllegalArgumentException("Null argument not allowed.");
+        }
+        String[][] result = (new CSVParser(new StringReader(s))).getAllValues();
+        if (result == null) {
+            // since CSVStrategy ignores empty lines an empty array is returned
+            // (i.e. not "result = new String[][] {{""}};")
+            result = EMPTY_DOUBLE_STRING_ARRAY;
+        }
+        return result;
     }
-    // uh,jh: make sure that parseLine("").length == 0
-    if (s.length() == 0) {
-      return EMPTY_STRING_ARRAY;
+
+    /**
+     * Parses the first line only according to the default {@link CSVStrategy}.
+     *
+     * Parsing empty string will be handled as valid records containing zero
+     * elements, so the following property holds: parseLine("").length == 0.
+     *
+     * @param s CSV String to be parsed.
+     * @return parsed String vector (which is never null)
+     * @throws IOException in case of error
+     */
+    public static String[] parseLine(String s) throws IOException {
+        if (s == null) {
+            throw new IllegalArgumentException("Null argument not allowed.");
+        }
+        // uh,jh: make sure that parseLine("").length == 0
+        if (s.length() == 0) {
+            return EMPTY_STRING_ARRAY;
+        }
+        return (new CSVParser(new StringReader(s))).getLine();
     }
-    return (new CSVParser(new StringReader(s))).getLine();
-  }
-  
+
 }

Modified: commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/CharBuffer.java
URL: http://svn.apache.org/viewvc/commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/CharBuffer.java?rev=1065950&r1=1065949&r2=1065950&view=diff
==============================================================================
--- commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/CharBuffer.java (original)
+++ commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/CharBuffer.java Tue Feb  1 08:46:00 2011
@@ -19,11 +19,11 @@
 package org.apache.commons.csv;
 
 /**
- * A simple StringBuffer replacement that aims to 
+ * A simple StringBuffer replacement that aims to
  * reduce copying as much as possible. The buffer
  * grows as necessary.
  * This class is not thread safe.
- * 
+ *
  * @author Ortwin Gl�ck
  */
 public class CharBuffer {
@@ -31,21 +31,21 @@ public class CharBuffer {
     private char[] c;
 
     /**
-     * Actually used number of characters in the array. 
+     * Actually used number of characters in the array.
      * It is also the index at which
-     * a new character will be inserted into <code>c</code>. 
-     */ 
+     * a new character will be inserted into <code>c</code>.
+     */
     private int length;
-    
+
     /**
      * Creates a new CharBuffer with an initial capacity of 32 characters.
      */
     public CharBuffer() {
         this(32);
     }
-    
+
     /**
-     * Creates a new CharBuffer with an initial capacity 
+     * Creates a new CharBuffer with an initial capacity
      * of <code>length</code> characters.
      */
     public CharBuffer(final int length) {
@@ -54,16 +54,17 @@ public class CharBuffer {
         }
         this.c = new char[length];
     }
-    
+
     /**
      * Empties the buffer. The capacity still remains the same, so no memory is freed.
      */
     public void clear() {
         length = 0;
     }
-    
+
     /**
      * Returns the number of characters in the buffer.
+     *
      * @return the number of characters
      */
     public int length() {
@@ -72,16 +73,18 @@ public class CharBuffer {
 
     /**
      * Returns the current capacity of the buffer.
+     *
      * @return the maximum number of characters that can be stored in this buffer without
-     * resizing it.
+     *         resizing it.
      */
     public int capacity() {
         return c.length;
     }
 
-    
+
     /**
      * Appends the contents of <code>cb</code> to the end of this CharBuffer.
+     *
      * @param cb the CharBuffer to append or null
      */
     public void append(final CharBuffer cb) {
@@ -92,10 +95,11 @@ public class CharBuffer {
         System.arraycopy(cb.c, 0, c, length, cb.length);
         length += cb.length;
     }
-    
+
     /**
      * Appends <code>s</code> to the end of this CharBuffer.
      * This method involves copying the new data once!
+     *
      * @param s the String to append or null
      */
     public void append(final String s) {
@@ -104,10 +108,11 @@ public class CharBuffer {
         }
         append(s.toCharArray());
     }
-    
+
     /**
      * Appends <code>sb</code> to the end of this CharBuffer.
      * This method involves copying the new data once!
+     *
      * @param sb the StringBuffer to append or null
      */
     public void append(final StringBuffer sb) {
@@ -118,10 +123,11 @@ public class CharBuffer {
         sb.getChars(0, sb.length(), c, length);
         length += sb.length();
     }
-    
+
     /**
      * Appends <code>data</code> to the end of this CharBuffer.
      * This method involves copying the new data once!
+     *
      * @param data the char[] to append or null
      */
     public void append(final char[] data) {
@@ -132,10 +138,11 @@ public class CharBuffer {
         System.arraycopy(data, 0, c, length, data.length);
         length += data.length;
     }
-    
+
     /**
      * Appends a single character to the end of this CharBuffer.
      * This method involves copying the new data once!
+     *
      * @param data the char to append
      */
     public void append(final char data) {
@@ -143,7 +150,7 @@ public class CharBuffer {
         c[length] = data;
         length++;
     }
-    
+
     /**
      * Shrinks the capacity of the buffer to the current length if necessary.
      * This method involves copying the data once!
@@ -157,13 +164,13 @@ public class CharBuffer {
         c = newc;
     }
 
-   /**
-    * Removes trailing whitespace.
-    */
+    /**
+     * Removes trailing whitespace.
+     */
     public void trimTrailingWhitespace() {
-      while (length>0 && Character.isWhitespace(c[length-1])) {
-        length--;
-      }
+        while (length > 0 && Character.isWhitespace(c[length - 1])) {
+            length--;
+        }
     }
 
     /**
@@ -172,6 +179,7 @@ public class CharBuffer {
      * modifying it.
      * This method allows to avoid copying if the caller knows the exact capacity
      * before.
+     *
      * @return
      */
     public char[] getCharacters() {
@@ -183,16 +191,17 @@ public class CharBuffer {
         return chars;
     }
 
-   /**
-    * Returns the character at the specified position.
-    */
+    /**
+     * Returns the character at the specified position.
+     */
     public char charAt(int pos) {
-      return c[pos];
-   }
+        return c[pos];
+    }
 
     /**
      * Converts the contents of the buffer into a StringBuffer.
      * This method involves copying the new data once!
+     *
      * @return
      */
     public StringBuffer toStringBuffer() {
@@ -200,25 +209,27 @@ public class CharBuffer {
         sb.append(c, 0, length);
         return sb;
     }
-    
+
     /**
      * Converts the contents of the buffer into a StringBuffer.
      * This method involves copying the new data once!
+     *
      * @return
      */
     public String toString() {
         return new String(c, 0, length);
     }
-    
+
     /**
      * Copies the data into a new array of at least <code>capacity</code> size.
+     *
      * @param capacity
      */
     public void provideCapacity(final int capacity) {
         if (c.length >= capacity) {
             return;
         }
-        int newcapacity = ((capacity*3)>>1) + 1;
+        int newcapacity = ((capacity * 3) >> 1) + 1;
         char[] newc = new char[newcapacity];
         System.arraycopy(c, 0, newc, 0, length);
         c = newc;



Mime
View raw message