class Csv
class Csv
lib/csv.tya:2
Csv provides the csv/Csv standard library API.
Source
# Csv provides the csv/Csv standard library API.
class Csv
# Csv.SEPARATOR provides the default CSV field separator.
# @type String
SEPARATOR: ","
# Csv.headers stores the header order used for dictionary rows.
# @type Array<String>
headers: []
# Csv.options stores CSV parsing and stringifying options.
# @type Dict
# @option options.separator String field separator.
# @option options.header Boolean whether the first row is a header.
options: { separator: Self.SEPARATOR, header: false }
# Csv.rows stores the CSV rows held by this object.
# @type Array
rows: []
# Csv.initialize applies optional CSV options.
# @param options Dict? CSV parsing and stringifying options.
# @option options.separator String field separator.
# @option options.header Boolean whether the first row is a header.
initialize: options = nil ->
self.apply_options(options)
# Csv.dump provides the csv/Csv standard library operation.
# @param options Dict? CSV stringifying options.
# @option options.separator String field separator.
# @option options.header Boolean whether to include dictionary headers.
# @return String serialized CSV text.
dump: options = nil ->
self.stringify(options)
# Csv.parse provides the csv/Csv standard library operation.
# @param text String? CSV text to parse; nil returns current rows.
# @param options Dict? CSV parsing options.
# @option options.separator String field separator.
# @option options.header Boolean whether the first row is a header.
# @return Array parsed rows.
parse: text = nil, options = nil ->
if text == nil
return self.rows
self.apply_options(options)
rows = self.parse_rows(text)
if not self.options["header"]
self.rows = rows
return rows
if rows.len() == 0
self.rows = []
return []
header = rows[0]
self.headers = header
out = []
i = 1
while i < rows.len()
r = rows[i]
d = {}
j = 0
while j < header.len()
if j < r.len()
d[header[j]] = r[j]
else
d[header[j]] = ""
j = j + 1
out.push(d)
i = i + 1
self.rows = out
out
# Csv.stringify provides the csv/Csv standard library operation.
# @param options Dict? CSV stringifying options.
# @option options.separator String field separator.
# @option options.header Boolean whether to include dictionary headers.
# @return String serialized CSV text.
stringify: options = nil ->
self.apply_options(options)
if self.rows.len() == 0
return ""
if self.rows[0].class == Array
return self.dump_array_rows()
if self.rows[0].class == Dict
header = self.headers
if header.len() == 0
header = self.rows[0].keys()
self.headers = header
out = ""
if self.options["header"]
j = 0
while j < header.len()
if j > 0
out = out + self.options["separator"]
out = out + self.escape_field(header[j])
j = j + 1
out = out + "\n"
i = 0
while i < self.rows.len()
r = self.rows[i]
j = 0
while j < header.len()
if j > 0
out = out + self.options["separator"]
v = ""
if r.has(header[j])
raw = r[header[j]]
if raw.class != String
raise error("csv.dump: row values must be strings")
v = raw
out = out + self.escape_field(v)
j = j + 1
out = out + "\n"
i = i + 1
return out
raise error("csv.dump: rows must be array of arrays or array of dicts")
private apply_options: options ->
if options == nil
return nil
self.options.update(options)
private dump_array_rows: ->
out = ""
i = 0
while i < self.rows.len()
r = self.rows[i]
j = 0
while j < r.len()
if j > 0
out = out + self.options["separator"]
if r[j].class != String
raise error("csv.dump: row values must be strings")
out = out + self.escape_field(r[j])
j = j + 1
out = out + "\n"
i = i + 1
out
private escape_field: field ->
separator = self.options["separator"]
needs_quote = field.sequence().any?(
c -> c == separator or c == "\"" or c == "\n" or c == chr(13)
)
if not needs_quote
return field
"\"" + field.replace("\"", "\"\"") + "\""
private parse_rows: text ->
rows = []
n = text.byte_len()
i = 0
cr = chr(13)
while i < n
row = []
field = ""
in_quote = false
ended = false
while i < n and not ended
c = text[i]
if in_quote
if c == "\""
if i + 1 < n and text[i + 1] == "\""
field = field + "\""
i = i + 2
else
in_quote = false
i = i + 1
else
field = field + c
i = i + 1
elseif c == "\""
in_quote = true
i = i + 1
else
if c == self.options["separator"]
row.push(field)
field = ""
i = i + 1
elseif c == "\n"
row.push(field)
i = i + 1
ended = true
else
if c == cr
row.push(field)
i = i + 1
if i < n and text[i] == "\n"
i = i + 1
ended = true
else
field = field + c
i = i + 1
if in_quote
raise error("csv.parse: unterminated quoted field")
if not ended
row.push(field)
rows.push(row)
rows
Class Constants
SEPARATOR
Csv.SEPARATOR
lib/csv.tya:5
Csv.SEPARATOR provides the default CSV field separator.
Source
# Csv.SEPARATOR provides the default CSV field separator.
# @type String
SEPARATOR: ","
Instance Variables
headers
Csv.headers
lib/csv.tya:9
Csv.headers stores the header order used for dictionary rows.
Source
# Csv.headers stores the header order used for dictionary rows.
# @type Array<String>
headers: []
options
Csv.options
lib/csv.tya:15
Csv.options stores CSV parsing and stringifying options.
Source
# Csv.options stores CSV parsing and stringifying options.
# @type Dict
# @option options.separator String field separator.
# @option options.header Boolean whether the first row is a header.
options: { separator: Self.SEPARATOR, header: false }
rows
Csv.rows
lib/csv.tya:19
Csv.rows stores the CSV rows held by this object.
Source
# Csv.rows stores the CSV rows held by this object.
# @type Array
rows: []
Methods
dump
Csv.dump(options = nil)
lib/csv.tya:33
Csv.dump provides the csv/Csv standard library operation.
Source
# Csv.dump provides the csv/Csv standard library operation.
# @param options Dict? CSV stringifying options.
# @option options.separator String field separator.
# @option options.header Boolean whether to include dictionary headers.
# @return String serialized CSV text.
dump: options = nil ->
self.stringify(options)
initialize
Csv.initialize(options = nil)
lib/csv.tya:25
Csv.initialize applies optional CSV options.
Source
# Csv.initialize applies optional CSV options.
# @param options Dict? CSV parsing and stringifying options.
# @option options.separator String field separator.
# @option options.header Boolean whether the first row is a header.
initialize: options = nil ->
self.apply_options(options)
parse
Csv.parse(text = nil, options = nil)
lib/csv.tya:42
Csv.parse provides the csv/Csv standard library operation.
Source
# Csv.parse provides the csv/Csv standard library operation.
# @param text String? CSV text to parse; nil returns current rows.
# @param options Dict? CSV parsing options.
# @option options.separator String field separator.
# @option options.header Boolean whether the first row is a header.
# @return Array parsed rows.
parse: text = nil, options = nil ->
if text == nil
return self.rows
self.apply_options(options)
rows = self.parse_rows(text)
if not self.options["header"]
self.rows = rows
return rows
if rows.len() == 0
self.rows = []
return []
header = rows[0]
self.headers = header
out = []
i = 1
while i < rows.len()
r = rows[i]
d = {}
j = 0
while j < header.len()
if j < r.len()
d[header[j]] = r[j]
else
d[header[j]] = ""
j = j + 1
out.push(d)
i = i + 1
self.rows = out
out
stringify
Csv.stringify(options = nil)
lib/csv.tya:77
Csv.stringify provides the csv/Csv standard library operation.
Source
# Csv.stringify provides the csv/Csv standard library operation.
# @param options Dict? CSV stringifying options.
# @option options.separator String field separator.
# @option options.header Boolean whether to include dictionary headers.
# @return String serialized CSV text.
stringify: options = nil ->
self.apply_options(options)
if self.rows.len() == 0
return ""
if self.rows[0].class == Array
return self.dump_array_rows()
if self.rows[0].class == Dict
header = self.headers
if header.len() == 0
header = self.rows[0].keys()
self.headers = header
out = ""
if self.options["header"]
j = 0
while j < header.len()
if j > 0
out = out + self.options["separator"]
out = out + self.escape_field(header[j])
j = j + 1
out = out + "\n"
i = 0
while i < self.rows.len()
r = self.rows[i]
j = 0
while j < header.len()
if j > 0
out = out + self.options["separator"]
v = ""
if r.has(header[j])
raw = r[header[j]]
if raw.class != String
raise error("csv.dump: row values must be strings")
v = raw
out = out + self.escape_field(v)
j = j + 1
out = out + "\n"
i = i + 1
return out
raise error("csv.dump: rows must be array of arrays or array of dicts")