Skip to content

Commit 7ac1ae7

Browse files
committed
Merge remote-tracking branch 'origin/delimiter-separated-values' into 2.10.0
2 parents 7c6a7fd + 66b439d commit 7ac1ae7

14 files changed

+392
-241
lines changed

Makefile

+5-5
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ all: \
2020
d3.svg.js \
2121
d3.behavior.js \
2222
d3.layout.js \
23-
d3.csv.js \
23+
d3.dsv.js \
2424
d3.geo.js \
2525
d3.geom.js \
2626
d3.time.js \
@@ -189,10 +189,10 @@ d3.geo.js: \
189189
src/geo/greatArc.js \
190190
src/geo/greatCircle.js
191191

192-
d3.csv.js: \
193-
src/csv/csv.js \
194-
src/csv/parse.js \
195-
src/csv/format.js
192+
d3.dsv.js: \
193+
src/dsv/dsv.js \
194+
src/dsv/csv.js \
195+
src/dsv/tsv.js
196196

197197
d3.time.js: \
198198
src/time/time.js \

d3.v2.js

+73-67
Original file line numberDiff line numberDiff line change
@@ -4937,80 +4937,86 @@
49374937
dy: dy
49384938
};
49394939
}
4940-
d3.csv = function(url, callback) {
4941-
d3.text(url, "text/csv", function(text) {
4942-
callback(text && d3.csv.parse(text));
4943-
});
4944-
};
4945-
d3.csv.parse = function(text) {
4946-
var header;
4947-
return d3.csv.parseRows(text, function(row, i) {
4948-
if (i) {
4949-
var o = {}, j = -1, m = header.length;
4950-
while (++j < m) o[header[j]] = row[j];
4951-
return o;
4952-
} else {
4953-
header = row;
4954-
return null;
4955-
}
4956-
});
4957-
};
4958-
d3.csv.parseRows = function(text, f) {
4959-
var EOL = {}, EOF = {}, rows = [], re = /\r\n|[,\r\n]/g, n = 0, t, eol;
4960-
re.lastIndex = 0;
4961-
function token() {
4962-
if (re.lastIndex >= text.length) return EOF;
4963-
if (eol) {
4964-
eol = false;
4965-
return EOL;
4966-
}
4967-
var j = re.lastIndex;
4968-
if (text.charCodeAt(j) === 34) {
4969-
var i = j;
4970-
while (i++ < text.length) {
4971-
if (text.charCodeAt(i) === 34) {
4972-
if (text.charCodeAt(i + 1) !== 34) break;
4973-
i++;
4940+
function d3_dsv(delimiter, mimeType) {
4941+
var reParse = new RegExp("\r\n|[" + delimiter + "\r\n]", "g"), reFormat = new RegExp('["' + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0);
4942+
function dsv(url, callback) {
4943+
d3.text(url, mimeType, function(text) {
4944+
callback(text && dsv.parse(text));
4945+
});
4946+
}
4947+
dsv.parse = function(text) {
4948+
var header;
4949+
return dsv.parseRows(text, function(row, i) {
4950+
if (i) {
4951+
var o = {}, j = -1, m = header.length;
4952+
while (++j < m) o[header[j]] = row[j];
4953+
return o;
4954+
} else {
4955+
header = row;
4956+
return null;
4957+
}
4958+
});
4959+
};
4960+
dsv.parseRows = function(text, f) {
4961+
var EOL = {}, EOF = {}, rows = [], n = 0, t, eol;
4962+
reParse.lastIndex = 0;
4963+
function token() {
4964+
if (reParse.lastIndex >= text.length) return EOF;
4965+
if (eol) {
4966+
eol = false;
4967+
return EOL;
4968+
}
4969+
var j = reParse.lastIndex;
4970+
if (text.charCodeAt(j) === 34) {
4971+
var i = j;
4972+
while (i++ < text.length) {
4973+
if (text.charCodeAt(i) === 34) {
4974+
if (text.charCodeAt(i + 1) !== 34) break;
4975+
i++;
4976+
}
49744977
}
4978+
reParse.lastIndex = i + 2;
4979+
var c = text.charCodeAt(i + 1);
4980+
if (c === 13) {
4981+
eol = true;
4982+
if (text.charCodeAt(i + 2) === 10) reParse.lastIndex++;
4983+
} else if (c === 10) {
4984+
eol = true;
4985+
}
4986+
return text.substring(j + 1, i).replace(/""/g, '"');
49754987
}
4976-
re.lastIndex = i + 2;
4977-
var c = text.charCodeAt(i + 1);
4978-
if (c === 13) {
4979-
eol = true;
4980-
if (text.charCodeAt(i + 2) === 10) re.lastIndex++;
4981-
} else if (c === 10) {
4982-
eol = true;
4988+
var m = reParse.exec(text);
4989+
if (m) {
4990+
eol = m[0].charCodeAt(0) !== delimiterCode;
4991+
return text.substring(j, m.index);
49834992
}
4984-
return text.substring(j + 1, i).replace(/""/g, '"');
4985-
}
4986-
var m = re.exec(text);
4987-
if (m) {
4988-
eol = m[0].charCodeAt(0) !== 44;
4989-
return text.substring(j, m.index);
4993+
reParse.lastIndex = text.length;
4994+
return text.substring(j);
4995+
}
4996+
while ((t = token()) !== EOF) {
4997+
var a = [];
4998+
while (t !== EOL && t !== EOF) {
4999+
a.push(t);
5000+
t = token();
5001+
}
5002+
if (f && !(a = f(a, n++))) continue;
5003+
rows.push(a);
49905004
}
4991-
re.lastIndex = text.length;
4992-
return text.substring(j);
5005+
return rows;
5006+
};
5007+
dsv.format = function(rows) {
5008+
return rows.map(formatRow).join("\n");
5009+
};
5010+
function formatRow(row) {
5011+
return row.map(formatValue).join(delimiter);
49935012
}
4994-
while ((t = token()) !== EOF) {
4995-
var a = [];
4996-
while (t !== EOL && t !== EOF) {
4997-
a.push(t);
4998-
t = token();
4999-
}
5000-
if (f && !(a = f(a, n++))) continue;
5001-
rows.push(a);
5013+
function formatValue(text) {
5014+
return reFormat.test(text) ? '"' + text.replace(/\"/g, '""') + '"' : text;
50025015
}
5003-
return rows;
5004-
};
5005-
d3.csv.format = function(rows) {
5006-
return rows.map(d3_csv_formatRow).join("\n");
5007-
};
5008-
function d3_csv_formatRow(row) {
5009-
return row.map(d3_csv_formatValue).join(",");
5010-
}
5011-
function d3_csv_formatValue(text) {
5012-
return /[",\n]/.test(text) ? '"' + text.replace(/\"/g, '""') + '"' : text;
5016+
return dsv;
50135017
}
5018+
d3.csv = d3_dsv(",", "text/csv");
5019+
d3.tsv = d3_dsv("\t", "text/tab-separated-values");
50145020
d3.geo = {};
50155021
var d3_geo_radians = Math.PI / 180;
50165022
d3.geo.azimuthal = function() {

d3.v2.min.js

+4-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/data/sample.tsv

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Hello World
2+
42 """fish"""

src/csv/csv.js

-5
This file was deleted.

src/csv/format.js

-13
This file was deleted.

src/csv/parse.js

-73
This file was deleted.

src/dsv/csv.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
d3.csv = d3_dsv(",", "text/csv");

src/dsv/dsv.js

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
function d3_dsv(delimiter, mimeType) {
2+
var reParse = new RegExp("\r\n|[" + delimiter + "\r\n]", "g"), // field separator regex
3+
reFormat = new RegExp("[\"" + delimiter + "\n]"),
4+
delimiterCode = delimiter.charCodeAt(0);
5+
6+
function dsv(url, callback) {
7+
d3.text(url, mimeType, function(text) {
8+
callback(text && dsv.parse(text));
9+
});
10+
}
11+
12+
dsv.parse = function(text) {
13+
var header;
14+
return dsv.parseRows(text, function(row, i) {
15+
if (i) {
16+
var o = {}, j = -1, m = header.length;
17+
while (++j < m) o[header[j]] = row[j];
18+
return o;
19+
} else {
20+
header = row;
21+
return null;
22+
}
23+
});
24+
};
25+
26+
dsv.parseRows = function(text, f) {
27+
var EOL = {}, // sentinel value for end-of-line
28+
EOF = {}, // sentinel value for end-of-file
29+
rows = [], // output rows
30+
n = 0, // the current line number
31+
t, // the current token
32+
eol; // is the current token followed by EOL?
33+
34+
reParse.lastIndex = 0; // work-around bug in FF 3.6
35+
36+
function token() {
37+
if (reParse.lastIndex >= text.length) return EOF; // special case: end of file
38+
if (eol) { eol = false; return EOL; } // special case: end of line
39+
40+
// special case: quotes
41+
var j = reParse.lastIndex;
42+
if (text.charCodeAt(j) === 34) {
43+
var i = j;
44+
while (i++ < text.length) {
45+
if (text.charCodeAt(i) === 34) {
46+
if (text.charCodeAt(i + 1) !== 34) break;
47+
i++;
48+
}
49+
}
50+
reParse.lastIndex = i + 2;
51+
var c = text.charCodeAt(i + 1);
52+
if (c === 13) {
53+
eol = true;
54+
if (text.charCodeAt(i + 2) === 10) reParse.lastIndex++;
55+
} else if (c === 10) {
56+
eol = true;
57+
}
58+
return text.substring(j + 1, i).replace(/""/g, "\"");
59+
}
60+
61+
// common case
62+
var m = reParse.exec(text);
63+
if (m) {
64+
eol = m[0].charCodeAt(0) !== delimiterCode;
65+
return text.substring(j, m.index);
66+
}
67+
reParse.lastIndex = text.length;
68+
return text.substring(j);
69+
}
70+
71+
while ((t = token()) !== EOF) {
72+
var a = [];
73+
while ((t !== EOL) && (t !== EOF)) {
74+
a.push(t);
75+
t = token();
76+
}
77+
if (f && !(a = f(a, n++))) continue;
78+
rows.push(a);
79+
}
80+
81+
return rows;
82+
};
83+
84+
dsv.format = function(rows) {
85+
return rows.map(formatRow).join("\n");
86+
};
87+
88+
function formatRow(row) {
89+
return row.map(formatValue).join(delimiter);
90+
}
91+
92+
function formatValue(text) {
93+
return reFormat.test(text) ? "\"" + text.replace(/\"/g, "\"\"") + "\"" : text;
94+
}
95+
96+
return dsv;
97+
}

src/dsv/tsv.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
d3.tsv = d3_dsv("\t", "text/tab-separated-values");

0 commit comments

Comments
 (0)