~ubuntu-branches/ubuntu/vivid/golang/vivid

« back to all changes in this revision

Viewing changes to src/pkg/csv/writer.go

  • Committer: Bazaar Package Importer
  • Author(s): Ondřej Surý
  • Date: 2011-08-03 17:04:59 UTC
  • mfrom: (14.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20110803170459-wzd99m3567y80ila
Tags: 1:59-1
* Imported Upstream version 59
* Refresh patches to a new release
* Fix FTBFS on ARM (Closes: #634270)
* Update version.bash to work with Debian packaging and not hg
  repository

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2011 The Go Authors. All rights reserved.
 
2
// Use of this source code is governed by a BSD-style
 
3
// license that can be found in the LICENSE file.
 
4
 
 
5
package csv
 
6
 
 
7
import (
 
8
        "bufio"
 
9
        "io"
 
10
        "os"
 
11
        "strings"
 
12
        "unicode"
 
13
        "utf8"
 
14
)
 
15
 
 
16
// A Writer writes records to a CSV encoded file.
 
17
//
 
18
// As returned by NewWriter, a Writer writes records terminated by a
 
19
// newline and uses ',' as the field delimiter.  The exported fields can be
 
20
// changed to customize the details before the first call to Write or WriteAll.
 
21
//
 
22
// Comma is the field delimiter.
 
23
//
 
24
// If UseCRLF is true, the Writer ends each record with \r\n instead of \n.
 
25
// just \n is written.
 
26
type Writer struct {
 
27
        Comma   int  // Field delimiter (set to to ',' by NewWriter)
 
28
        UseCRLF bool // True to use \r\n as the line terminator
 
29
        w       *bufio.Writer
 
30
}
 
31
 
 
32
// NewWriter returns a new Writer that writes to w.
 
33
func NewWriter(w io.Writer) *Writer {
 
34
        return &Writer{
 
35
                Comma: ',',
 
36
                w:     bufio.NewWriter(w),
 
37
        }
 
38
}
 
39
 
 
40
// Writer writes a single CSV record to w along with any necessary quoting.
 
41
// A record is a slice of strings with each string being one field.
 
42
func (w *Writer) Write(record []string) (err os.Error) {
 
43
        for n, field := range record {
 
44
                if n > 0 {
 
45
                        if _, err = w.w.WriteRune(w.Comma); err != nil {
 
46
                                return
 
47
                        }
 
48
                }
 
49
 
 
50
                // If we don't have to have a quoted field then just
 
51
                // write out the field and continue to the next field.
 
52
                if !w.fieldNeedsQuotes(field) {
 
53
                        if _, err = w.w.WriteString(field); err != nil {
 
54
                                return
 
55
                        }
 
56
                        continue
 
57
                }
 
58
                if err = w.w.WriteByte('"'); err != nil {
 
59
                        return
 
60
                }
 
61
 
 
62
                for _, rune := range field {
 
63
                        switch rune {
 
64
                        case '"':
 
65
                                _, err = w.w.WriteString(`""`)
 
66
                        case '\r':
 
67
                                if !w.UseCRLF {
 
68
                                        err = w.w.WriteByte('\r')
 
69
                                }
 
70
                        case '\n':
 
71
                                if w.UseCRLF {
 
72
                                        _, err = w.w.WriteString("\r\n")
 
73
                                } else {
 
74
                                        err = w.w.WriteByte('\n')
 
75
                                }
 
76
                        default:
 
77
                                _, err = w.w.WriteRune(rune)
 
78
                        }
 
79
                        if err != nil {
 
80
                                return
 
81
                        }
 
82
                }
 
83
 
 
84
                if err = w.w.WriteByte('"'); err != nil {
 
85
                        return
 
86
                }
 
87
        }
 
88
        if w.UseCRLF {
 
89
                _, err = w.w.WriteString("\r\n")
 
90
        } else {
 
91
                err = w.w.WriteByte('\n')
 
92
        }
 
93
        return
 
94
}
 
95
 
 
96
// Flush writes any buffered data to the underlying io.Writer.
 
97
func (w *Writer) Flush() {
 
98
        w.w.Flush()
 
99
}
 
100
 
 
101
// WriteAll writes multiple CSV records to w using Write and then calls Flush.
 
102
func (w *Writer) WriteAll(records [][]string) (err os.Error) {
 
103
        for _, record := range records {
 
104
                err = w.Write(record)
 
105
                if err != nil {
 
106
                        break
 
107
                }
 
108
        }
 
109
        w.Flush()
 
110
        return nil
 
111
}
 
112
 
 
113
// fieldNeedsQuotes returns true if our field must be enclosed in quotes.
 
114
// Empty fields, files with a Comma, fields with a quote or newline, and
 
115
// fields which start with a space must be enclosed in quotes.
 
116
func (w *Writer) fieldNeedsQuotes(field string) bool {
 
117
        if len(field) == 0 || strings.IndexRune(field, w.Comma) >= 0 || strings.IndexAny(field, "\"\r\n") >= 0 {
 
118
                return true
 
119
        }
 
120
 
 
121
        rune, _ := utf8.DecodeRuneInString(field)
 
122
        return unicode.IsSpace(rune)
 
123
}