coffeescript-ui
Version:
Coffeescript User Interface System
283 lines (226 loc) • 5.62 kB
text/coffeescript
class CUI.CSVData extends CUI.Element
initOpts: ->
super()
rows:
check: (v) ->
CUI.util.isArray(v) and v.length > 0
readOpts: ->
super()
= 0
if
=
else
= []
return
# makes sure, all rows have the same length
giveAllRowsSameNumberOfColumns: ->
= 0
for row in
col_count = row.length
if col_count >
= col_count
for row in
if row.length <
for idx in [row.length...]
row[idx] = ""
return
getMaxColumnCount: ->
getRows: ->
getRow: (row_i) ->
[row_i]
getRowsCount: ->
.length
debug: ->
console.debug "rows:",
toText: (_opts={}) ->
opts = CUI.Element.readOpts _opts, "CSVData.toText",
delimiter:
mandatory: true
default: ";"
check: (v) =>
CUI.util.isString(v) and v.length > 0
quotechar:
mandatory: true
default: '"'
check: (v) =>
CUI.util.isString(v) and v.length > 0
always_quote:
mandatory: true
default: true
check: Boolean
equal_columns:
mandatory: true
default: true
check: Boolean
newline:
mandatory: true
default: String.fromCharCode(10)
check: (v) =>
CUI.util.isString(v) and v.length > 0
if opts.equal_columns
nl = String.fromCharCode(10)
cr = String.fromCharCode(13)
_rows = []
for row in
_row = []
for col, idx in row
if idx > 0
_row.push(opts.delimiter)
if CUI.util.isEmpty(col)
str = ""
else
str = ""+col
if opts.always_quote
quote = true
else if str.indexOf(opts.delimiter) > -1
quote = true
else if str.indexOf(opts.quotechar) > -1
quote = true
else if str.indexOf(nl) > -1
quote = true
else if str.indexOf(cr) > -1
quote = true
else
quote = false
if quote
_row.push(CUI.CSVData.quote(str, opts.quotechar))
else
_row.push(str)
_rows.push(_row.join(""))
_rows.join(opts.newline)
# parse csv info array
parse: (_opts={}) ->
opts = CUI.Element.readOpts _opts, "CSVData.parse",
text:
mandatory: true
check: String
delimiter:
check: String
quotechar:
check: String
defer:
mandatory: true
default: true
check: Boolean
= []
text = opts.text
columns = []
column_idx = 0
column_chars = []
len = text.length
idx = 0
in_quotes = false
lines = 0
space_chars = [' ']
auto_quotechars = ['"',"'"]
auto_delimiters = [",",";","\t"]
# space_chars = [" "]
if opts.delimiter != undefined
delimiter = opts.delimiter
else
delimiter = null
if opts.quotechar != undefined
quotechar = opts.quotechar
else
quotechar = null
# console.info("CUI.CSV.parse:", len, "chars. delimiter:", delimiter or "detect", "quotechar:", quotechar or "detect")
if opts.defer
dfr = new CUI.Deferred()
do_work = =>
end_column = =>
columns[column_idx] = column_chars.join("")
column_chars.splice(0)
column_idx = column_idx + 1
return
end_row = =>
if columns.length > 0
lines = lines + 1
.push(columns)
columns = []
column_idx = 0
return
while (idx < len)
char = text.charAt(idx)
# console.debug "char:", idx, char, text.charCodeAt(idx)
if column_chars.length == 0 and not in_quotes and char in space_chars
# ignore spaces outside quotes at the beginning of a column
idx = idx + 1
continue
if quotechar == null and char in auto_quotechars
quotechar = char
# console.info("CSVData.parse: detected quotechar:", quotechar)
if delimiter == null and char in auto_delimiters
delimiter = char
# console.info("CSVData.parse: detected delimiter:", delimiter)
if char == quotechar and (column_chars.length == 0 or in_quotes)
if in_quotes
if text[idx+1] == quotechar
column_chars.push(char)
idx = idx + 2
continue
else
# end quote
in_quotes = false
idx = idx + 1
continue
else
in_quotes = true
idx = idx + 1
continue
if char == delimiter
if in_quotes
column_chars.push(char)
idx = idx + 1
continue
else
end_column()
idx = idx + 1
continue
charCode = text.charCodeAt(idx)
nextCharCode = text.charCodeAt(idx+1)
# do we have a line ending
if charCode == 13 or charCode == 10
if (charCode == 13 and nextCharCode == 10)
idx = idx + 2
else
idx = idx + 1
if in_quotes
column_chars.push(String.fromCharCode(10))
else
end_column()
end_row()
if lines%1000==0 and opts.defer
dfr.notify(row_count: lines, file_read_idx: idx, file_length: len)
CUI.setTimeout
ms: 10
call: do_work
return
continue
column_chars.push(char)
idx = idx + 1
if column_chars.length > 0
end_column()
if columns.length > 0
end_row()
info = row_count: lines, file_length: len, rows:
if opts.defer
dfr.resolve(info)
else
return info
if opts.defer
CUI.setTimeout
ms: 0
call: do_work
dfr.done =>
; #
return dfr.promise()
else
return do_work()
: (str, quotechar = '"') ->
quotechar+str.replace(new RegExp(CUI.util.escapeRegExp(quotechar), "g"), quotechar+quotechar)+quotechar