summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorRémi Verschelde <rverschelde@gmail.com>2021-08-04 11:20:36 +0200
committerRémi Verschelde <rverschelde@gmail.com>2021-08-04 11:53:21 +0200
commitb8c08ba5add1406783cec2333d6ad7011a29e01f (patch)
tree39aea7f59113483e99af2dc885a81755f0fe7b51 /core
parent7eedc2c34822f9b14f04e6866e73626959f6d647 (diff)
Tests: Improve coverage for `File::get_csv_line()`
Adds a few more complex edge cases which are supported. Also adds some documentation, simplifies the code a bit and forbids using double quotes as a delimiter.
Diffstat (limited to 'core')
-rw-r--r--core/io/file_access.cpp37
1 files changed, 19 insertions, 18 deletions
diff --git a/core/io/file_access.cpp b/core/io/file_access.cpp
index d21c0bd9a2..e6e79dff8a 100644
--- a/core/io/file_access.cpp
+++ b/core/io/file_access.cpp
@@ -316,52 +316,53 @@ String FileAccess::get_line() const {
}
Vector<String> FileAccess::get_csv_line(const String &p_delim) const {
- ERR_FAIL_COND_V(p_delim.length() != 1, Vector<String>());
+ ERR_FAIL_COND_V_MSG(p_delim.length() != 1, Vector<String>(), "Only single character delimiters are supported to parse CSV lines.");
+ ERR_FAIL_COND_V_MSG(p_delim[0] == '"', Vector<String>(), "The double quotation mark character (\") is not supported as a delimiter for CSV lines.");
- String l;
+ String line;
+
+ // CSV can support entries with line breaks as long as they are enclosed
+ // in double quotes. So our "line" might be more than a single line in the
+ // text file.
int qc = 0;
do {
if (eof_reached()) {
break;
}
-
- l += get_line() + "\n";
+ line += get_line() + "\n";
qc = 0;
- for (int i = 0; i < l.length(); i++) {
- if (l[i] == '"') {
+ for (int i = 0; i < line.length(); i++) {
+ if (line[i] == '"') {
qc++;
}
}
-
} while (qc % 2);
- l = l.substr(0, l.length() - 1);
+ // Remove the extraneous newline we've added above.
+ line = line.substr(0, line.length() - 1);
Vector<String> strings;
bool in_quote = false;
String current;
- for (int i = 0; i < l.length(); i++) {
- char32_t c = l[i];
- char32_t s[2] = { 0, 0 };
-
+ for (int i = 0; i < line.length(); i++) {
+ char32_t c = line[i];
+ // A delimiter ends the current entry, unless it's in a quoted string.
if (!in_quote && c == p_delim[0]) {
strings.push_back(current);
current = String();
} else if (c == '"') {
- if (l[i + 1] == '"' && in_quote) {
- s[0] = '"';
- current += s;
+ // Doubled quotes are escapes for intentional quotes in the string.
+ if (line[i + 1] == '"' && in_quote) {
+ current += '"';
i++;
} else {
in_quote = !in_quote;
}
} else {
- s[0] = c;
- current += s;
+ current += c;
}
}
-
strings.push_back(current);
return strings;