Parent

Class Index [+]

Quicksearch

TaskJuggler::CSVFile

This is a very lightweight version of the Ruby library class CSV. That class changed significantly from 1.8 to 1.9 and is a compatibility nightmare. Hence we use our own class.

Attributes

data[R]

Public Class Methods

new(data = nil, separator = ';', quote = '"') click to toggle source

At construction time you need to specify the data container. This is an Array of Arrays that holds the table. Optionally, you can specify a separator and a quote string for the CSV file.

    # File lib/reports/CSVFile.rb, line 27
27:     def initialize(data = nil, separator = ';', quote = '"')
28:       @data = data
29:       raise "Illegal separator: #{separator}" if '."'.include?(separator)
30:       @separator = separator
31:       raise "Illegal quote: #{separator}" if quote == '.'
32:       @quote = quote
33:     end
strToNative(str) click to toggle source

Utility function that tries to convert a String into a native type that is supported by the CSVFile generator. If no native type is found, the input String str will be returned unmodified. nil is returned as nil.

     # File lib/reports/CSVFile.rb, line 182
182:     def CSVFile.strToNative(str)
183:       if str.nil?
184:         nil
185:       elsif /^[-+]?\d+$/ =~ str
186:         # field is a Fixnum
187:         str.to_i
188:       elsif /^[-+]?\d*\.?\d+([eE][-+]?\d+)?$/ =~ str
189:         # field is a Float
190:         str.to_f
191:       else
192:         # Everything else is kept as String
193:         str
194:       end
195:     end

Public Instance Methods

parse(str) click to toggle source

Read the data as Array of Arrays from a CSV formated String str.

     # File lib/reports/CSVFile.rb, line 84
 84:     def parse(str)
 85:       @data = []
 86:       state = :startOfRecord
 87:       fields = field = quoted = nil
 88: 
 89:       # Make sure the input is terminated with a record end.
 90:       str += "\n" unless str[1] == \n\
 91: 
 92:       str.each_utf8_char do |c|
 93:         #puts "c: #{c}  State: #{state}"
 94:         case state
 95:         when :startOfRecord
 96:           # This will store the fields of a record
 97:           fields = []
 98:           state = :startOfField
 99:           redo
100:         when :startOfField
101:           field = ''
102:           quoted = false
103:           if c == @quote
104:             # We've found the start of a quoted field.
105:             state = :inQuotedField
106:             quoted = true
107:           elsif c == @separator || c == "\n"
108:             # We've found an empty field
109:             field = nil
110:             state = :fieldEnd
111:             redo
112:           else
113:             # We've found the first character of an unquoted field
114:             field << c
115:             state = :inUnquotedField
116:           end
117:         when :inQuotedField
118:           # We are processing the content of a quoted field
119:           if c == @quote
120:             # This could be then end of the field or a quoted quote.
121:             state = :quoteInQuotedField
122:           else
123:             # We've found a normal character of the quoted field
124:             field << c
125:           end
126:         when :quoteInQuotedField
127:           # We are processing a quoted quote or the end of a quoted field
128:           if c == @quote
129:             # We've found a quoted quote
130:             field << c
131:             state = :inQuotedField
132:           elsif c == @separator || c == "\n"
133:             state = :fieldEnd
134:             redo
135:           else
136:             raise "Unexpected character #{c} in CSV"
137:           end
138:         when :inUnquotedField
139:           # We are processing an unquoted field
140:           if c == @separator || c == "\n"
141:             # We've found the end of a unquoted field
142:             state = :fieldEnd
143:             redo
144:           else
145:             # A normal character of an unquoted field
146:             field << c
147:           end
148:         when :fieldEnd
149:           # We've completed processing a field. Add the field to the list of
150:           # fields. Convert Fixnums and Floats in native types.
151:           fields << unMarshal(field, quoted)
152: 
153:           if c == "\n"
154:             # The field end is an end of a record as well.
155:             state = :recordEnd
156:             redo
157:           else
158:             # Get the next field.
159:             state = :startOfField
160:           end
161:         when :recordEnd
162:           # We've found the end of a record. Add fields to the @data
163:           # structure.
164:           @data << fields
165:           # Look for a new record.
166:           state = :startOfRecord
167:         else
168:           raise "Unknown state #{state}"
169:         end
170:       end
171: 
172:       unless state == :startOfRecord
173:         raise "CSV state machine error in state #{state}"
174:       end
175: 
176:       @data
177:     end
read(fileName) click to toggle source

Read the data as Array of Arrays from a CSV formated file fileName. In case ’.’ is used for the fileName the data is read from $stdin.

    # File lib/reports/CSVFile.rb, line 51
51:     def read(fileName)
52:       if (fileName == '.')
53:         file = $stdin
54:       else
55:         file = File.open(fileName, 'r')
56:       end
57: 
58:       parse(file.read)
59: 
60:       file.close unless fileName == '.'
61:       @data
62:     end
to_s() click to toggle source

Convert the CSV data into a CSV formatted String.

    # File lib/reports/CSVFile.rb, line 65
65:     def to_s
66:       s = ''
67:       @data.each do |line|
68:         first = true
69:         line.each do |field|
70:           # Don't output a separator before the first field of the line.
71:            if first
72:              first = false
73:            else
74:              s << @separator
75:            end
76:            s << marshal(field)
77:         end
78:         s << "\n"
79:       end
80:       s
81:     end
write(fileName) click to toggle source

Use this function to write the table into a CSV file fileName. ’.’ can be used to write to $stdout.

    # File lib/reports/CSVFile.rb, line 37
37:     def write(fileName)
38:       if (fileName == '.')
39:         file = $stdout
40:       else
41:         file = File.open(fileName, 'w')
42:       end
43: 
44:       file.write(to_s)
45: 
46:       file.close unless fileName == '.'
47:     end

Private Instance Methods

marshal(field) click to toggle source

This function is used to properly quote @quote and @separation characters contained in the field.

     # File lib/reports/CSVFile.rb, line 201
201:     def marshal(field)
202:       if field.nil?
203:         ''
204:       elsif field.is_a?(Fixnum) || field.is_a?(Float)
205:         # Numbers don't have to be quoted.
206:         field.to_s
207:       else
208:         # Duplicate quote characters.
209:         f = field.gsub(/@quote/, "#{@quote * 2}")
210:         # Enclose the field in quote characters
211:         @quote + f.to_s + @quote
212:       end
213:     end
unMarshal(field, quoted) click to toggle source

Convert the String field into a native Ruby type. If field was quoted, the result is always the String.

     # File lib/reports/CSVFile.rb, line 217
217:     def unMarshal(field, quoted)
218:       # Quoted Strings and nil are returned verbatim.
219:       if quoted || field.nil?
220:         field
221:       else
222:         # Unquoted fields are inspected for special types
223:         CSVFile.strToNative(field)
224:       end
225:     end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.