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/taskjuggler/reports/CSVFile.rb, line 28
28:     def initialize(data = nil, separator = ';', quote = '"')
29:       @data = data
30:       raise "Illegal separator: #{separator}" if '."'.include?(separator)
31:       @separator = separator
32:       raise "Illegal quote: #{separator}" if quote == '.'
33:       @quote = quote
34:     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/taskjuggler/reports/CSVFile.rb, line 183
183:     def CSVFile.strToNative(str)
184:       if str.nil?
185:         nil
186:       elsif /^[-+]?\d+$/ =~ str
187:         # field is a Fixnum
188:         str.to_i
189:       elsif /^[-+]?\d*\.?\d+([eE][-+]?\d+)?$/ =~ str
190:         # field is a Float
191:         str.to_f
192:       else
193:         # Everything else is kept as String
194:         str
195:       end
196:     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/taskjuggler/reports/CSVFile.rb, line 85
 85:     def parse(str)
 86:       @data = []
 87:       state = :startOfRecord
 88:       fields = field = quoted = nil
 89: 
 90:       # Make sure the input is terminated with a record end.
 91:       str += "\n" unless str[1] == \n\
 92: 
 93:       str.each_utf8_char do |c|
 94:         #puts "c: #{c}  State: #{state}"
 95:         case state
 96:         when :startOfRecord
 97:           # This will store the fields of a record
 98:           fields = []
 99:           state = :startOfField
100:           redo
101:         when :startOfField
102:           field = ''
103:           quoted = false
104:           if c == @quote
105:             # We've found the start of a quoted field.
106:             state = :inQuotedField
107:             quoted = true
108:           elsif c == @separator || c == "\n"
109:             # We've found an empty field
110:             field = nil
111:             state = :fieldEnd
112:             redo
113:           else
114:             # We've found the first character of an unquoted field
115:             field << c
116:             state = :inUnquotedField
117:           end
118:         when :inQuotedField
119:           # We are processing the content of a quoted field
120:           if c == @quote
121:             # This could be then end of the field or a quoted quote.
122:             state = :quoteInQuotedField
123:           else
124:             # We've found a normal character of the quoted field
125:             field << c
126:           end
127:         when :quoteInQuotedField
128:           # We are processing a quoted quote or the end of a quoted field
129:           if c == @quote
130:             # We've found a quoted quote
131:             field << c
132:             state = :inQuotedField
133:           elsif c == @separator || c == "\n"
134:             state = :fieldEnd
135:             redo
136:           else
137:             raise "Unexpected character #{c} in CSV"
138:           end
139:         when :inUnquotedField
140:           # We are processing an unquoted field
141:           if c == @separator || c == "\n"
142:             # We've found the end of a unquoted field
143:             state = :fieldEnd
144:             redo
145:           else
146:             # A normal character of an unquoted field
147:             field << c
148:           end
149:         when :fieldEnd
150:           # We've completed processing a field. Add the field to the list of
151:           # fields. Convert Fixnums and Floats in native types.
152:           fields << unMarshal(field, quoted)
153: 
154:           if c == "\n"
155:             # The field end is an end of a record as well.
156:             state = :recordEnd
157:             redo
158:           else
159:             # Get the next field.
160:             state = :startOfField
161:           end
162:         when :recordEnd
163:           # We've found the end of a record. Add fields to the @data
164:           # structure.
165:           @data << fields
166:           # Look for a new record.
167:           state = :startOfRecord
168:         else
169:           raise "Unknown state #{state}"
170:         end
171:       end
172: 
173:       unless state == :startOfRecord
174:         raise "CSV state machine error in state #{state}"
175:       end
176: 
177:       @data
178:     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/taskjuggler/reports/CSVFile.rb, line 52
52:     def read(fileName)
53:       if (fileName == '.')
54:         file = $stdin
55:       else
56:         file = File.open(fileName, 'r')
57:       end
58: 
59:       parse(file.read)
60: 
61:       file.close unless fileName == '.'
62:       @data
63:     end
to_s() click to toggle source

Convert the CSV data into a CSV formatted String.

    # File lib/taskjuggler/reports/CSVFile.rb, line 66
66:     def to_s
67:       s = ''
68:       @data.each do |line|
69:         first = true
70:         line.each do |field|
71:           # Don't output a separator before the first field of the line.
72:            if first
73:              first = false
74:            else
75:              s << @separator
76:            end
77:            s << marshal(field)
78:         end
79:         s << "\n"
80:       end
81:       s
82:     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/taskjuggler/reports/CSVFile.rb, line 38
38:     def write(fileName)
39:       if (fileName == '.')
40:         file = $stdout
41:       else
42:         file = File.open(fileName, 'w')
43:       end
44: 
45:       file.write(to_s)
46: 
47:       file.close unless fileName == '.'
48:     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/taskjuggler/reports/CSVFile.rb, line 202
202:     def marshal(field)
203:       if field.nil?
204:         ''
205:       elsif field.is_a?(Fixnum) || field.is_a?(Float) || field.is_a?(Bignum)
206:         # Numbers don't have to be quoted.
207:         field.to_s
208:       else
209:         # Duplicate quote characters.
210:         f = field.gsub(/@quote/, "#{@quote * 2}")
211:         # Enclose the field in quote characters
212:         @quote + f.to_s + @quote
213:       end
214:     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/taskjuggler/reports/CSVFile.rb, line 218
218:     def unMarshal(field, quoted)
219:       # Quoted Strings and nil are returned verbatim.
220:       if quoted || field.nil?
221:         field
222:       else
223:         # Unquoted fields are inspected for special types
224:         CSVFile.strToNative(field)
225:       end
226:     end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.