Home | History | Annotate | Download | only in config
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.networkrecommendation.config;
     18 
     19 import java.io.BufferedReader;
     20 import java.io.IOException;
     21 import java.util.List;
     22 
     23 /**
     24  * Utilities for parsing and serializing Comma-Separated Value data.
     25  * See http://en.wikipedia.org/wiki/Comma-separated_values and
     26  * http://tools.ietf.org/html/rfc4180 for details of the format.
     27  */
     28 public class Csv {
     29     /** Field delimiter.  The C in CSV. */
     30     public static final String COMMA = ",";
     31 
     32     /** Record delimiter.  "Proper" CSV uses CR-LF, but that would be annoying. */
     33     public static final String NEWLINE = "\n";
     34 
     35     /**
     36      * Appends a single value to an output string.  If the value
     37      * contains quotes, commas, newlines, or leading or trailing whitespace,
     38      * the value will be written in quotes (with internal quotes doubled).
     39      * Newlines are converted to standard CR-LF form.  This function does not
     40      * write field delimiters -- append {@link COMMA} yourself between values.
     41      *
     42      * @param value to write, quoted as necessary; must be non-null.
     43      * @param output to append (possibly quoted) value to
     44      * @throws java.io.IOException if writing to 'output' fails
     45      */
     46     public static void writeValue(String value, Appendable output) throws IOException {
     47         int len = value.length();
     48         if (len == 0) return;
     49 
     50         char first = value.charAt(0);
     51         char last = value.charAt(len - 1);
     52         if (first != ' ' && first != '\t' && last != ' ' && last != '\t' &&
     53                 value.indexOf('"') < 0 && value.indexOf(',') < 0 &&
     54                 value.indexOf('\r') < 0 && value.indexOf('\n') < 0) {
     55             // No quoting needed.
     56             output.append(value);
     57             return;
     58         }
     59 
     60         output.append('"').append(value.replace("\"", "\"\"")).append('"');
     61     }
     62 
     63     /**
     64      * Parse a record of comma separated values from an input file.
     65      * May read multiple physical lines if values contain embedded newlines.
     66      *
     67      * @param reader to read one or more physical lines from
     68      * @param out array to append unquoted CSV values to
     69      * @return true if values were read, false on EOF
     70      * @throws java.io.IOException if reading from 'reader' fails
     71      */
     72     public static boolean parseLine(BufferedReader reader, List<String> out) throws IOException {
     73         String text = reader.readLine();
     74         if (text == null) return false;
     75 
     76         int pos = 0;
     77         do {
     78             StringBuilder buf = new StringBuilder();
     79             int comma;
     80             for (;;) {
     81                 comma = text.indexOf(',', pos);
     82                 int quote = text.indexOf('"', pos);
     83                 if (quote == -1 || (comma != -1 && comma < quote)) break;
     84 
     85                 if (pos > 0 && text.charAt(pos - 1) == '"') buf.append('"');
     86                 buf.append(text, pos, quote);
     87                 while ((quote = text.indexOf('"', (pos = quote + 1))) == -1) {
     88                     buf.append(text, pos, text.length()).append('\n');
     89                     text = reader.readLine();
     90                     if (text == null) {
     91                         out.add(buf.toString());
     92                         return true;
     93                     }
     94                     quote = -1;
     95                 }
     96 
     97                 buf.append(text, pos, quote);
     98                 pos = quote + 1;
     99             }
    100 
    101             buf.append(text, pos, comma == -1 ? text.length() : comma);
    102             out.add(buf.toString());
    103             pos = comma + 1;
    104         } while (pos > 0);
    105         return true;
    106     }
    107 
    108     private Csv() {}  // Do not instantiate
    109 }
    110