Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/io/common/IO_string_utils.hh11
-rw-r--r--source/blender/io/common/intern/string_utils.cc26
-rw-r--r--source/blender/io/common/intern/string_utils_test.cc23
-rw-r--r--source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc9
4 files changed, 54 insertions, 15 deletions
diff --git a/source/blender/io/common/IO_string_utils.hh b/source/blender/io/common/IO_string_utils.hh
index 25f1f01c6ed..23cb5ec7d84 100644
--- a/source/blender/io/common/IO_string_utils.hh
+++ b/source/blender/io/common/IO_string_utils.hh
@@ -16,21 +16,22 @@ namespace blender::io {
* The returned line will not have '\n' characters at the end;
* the `buffer` is modified to contain remaining text without
* the input line.
- *
- * Note that backslash (\) character is treated as a line
- * continuation, similar to OBJ file format or a C preprocessor.
*/
StringRef read_next_line(StringRef &buffer);
/**
+ * Fix up OBJ line continuations by replacing backslash (\) and the
+ * following newline with spaces.
+ */
+void fixup_line_continuations(char *p, char *end);
+
+/**
* Drop leading white-space from a StringRef.
- * Note that backslash character is considered white-space.
*/
StringRef drop_whitespace(StringRef str);
/**
* Drop leading non-white-space from a StringRef.
- * Note that backslash character is considered white-space.
*/
StringRef drop_non_whitespace(StringRef str);
diff --git a/source/blender/io/common/intern/string_utils.cc b/source/blender/io/common/intern/string_utils.cc
index 3a12250e14b..eff50e40f13 100644
--- a/source/blender/io/common/intern/string_utils.cc
+++ b/source/blender/io/common/intern/string_utils.cc
@@ -18,14 +18,12 @@ StringRef read_next_line(StringRef &buffer)
const char *start = buffer.begin();
const char *end = buffer.end();
size_t len = 0;
- char prev = 0;
const char *ptr = start;
while (ptr < end) {
char c = *ptr++;
- if (c == '\n' && prev != '\\') {
+ if (c == '\n') {
break;
}
- prev = c;
++len;
}
@@ -35,7 +33,27 @@ StringRef read_next_line(StringRef &buffer)
static bool is_whitespace(char c)
{
- return c <= ' ' || c == '\\';
+ return c <= ' ';
+}
+
+void fixup_line_continuations(char *p, char *end)
+{
+ while (true) {
+ /* Find next backslash, if any. */
+ char *backslash = std::find(p, end, '\\');
+ if (backslash == end)
+ break;
+ /* Skip over possible whitespace right after it. */
+ p = backslash + 1;
+ while (p < end && is_whitespace(*p) && *p != '\n')
+ ++p;
+ /* If then we have a newline, turn both backslash
+ * and the newline into regular spaces. */
+ if (p < end && *p == '\n') {
+ *backslash = ' ';
+ *p = ' ';
+ }
+ }
}
StringRef drop_whitespace(StringRef str)
diff --git a/source/blender/io/common/intern/string_utils_test.cc b/source/blender/io/common/intern/string_utils_test.cc
index a78bd7ab8a3..91b94d22fb9 100644
--- a/source/blender/io/common/intern/string_utils_test.cc
+++ b/source/blender/io/common/intern/string_utils_test.cc
@@ -10,17 +10,34 @@ namespace blender::io {
TEST(string_utils, read_next_line)
{
- std::string str = "abc\n \n\nline with \\\ncontinuation\nCRLF ending:\r\na";
+ std::string str = "abc\n \n\nline with \t spaces\nCRLF ending:\r\na";
StringRef s = str;
EXPECT_STRREF_EQ("abc", read_next_line(s));
EXPECT_STRREF_EQ(" ", read_next_line(s));
EXPECT_STRREF_EQ("", read_next_line(s));
- EXPECT_STRREF_EQ("line with \\\ncontinuation", read_next_line(s));
+ EXPECT_STRREF_EQ("line with \t spaces", read_next_line(s));
EXPECT_STRREF_EQ("CRLF ending:\r", read_next_line(s));
EXPECT_STRREF_EQ("a", read_next_line(s));
EXPECT_TRUE(s.is_empty());
}
+TEST(string_utils, fixup_line_continuations)
+{
+ const char *str =
+ "backslash \\\n eol\n"
+ "backslash spaces \\ \n eol\n"
+ "without eol \\ is \\\\ \\ left intact\n"
+ "\\";
+ const char *exp =
+ "backslash eol\n"
+ "backslash spaces eol\n"
+ "without eol \\ is \\\\ \\ left intact\n"
+ "\\";
+ std::string buf(str);
+ fixup_line_continuations(buf.data(), buf.data() + buf.size());
+ EXPECT_STRREF_EQ(exp, buf);
+}
+
TEST(string_utils, drop_whitespace)
{
/* Empty */
@@ -36,7 +53,7 @@ TEST(string_utils, drop_whitespace)
/* No leading whitespace */
EXPECT_STRREF_EQ("c", drop_whitespace("c"));
/* Case with backslash, should be treated as whitespace */
- EXPECT_STRREF_EQ("d", drop_whitespace(" \\ d"));
+ EXPECT_STRREF_EQ("d", drop_whitespace(" \t d"));
}
TEST(string_utils, parse_int_valid)
diff --git a/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc b/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc
index 94d723cacf5..f801bb1d3fa 100644
--- a/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc
+++ b/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc
@@ -375,6 +375,11 @@ void OBJParser::parse(Vector<std::unique_ptr<Geometry>> &r_all_geometries,
break; /* No more data to read. */
}
+ /* Take care of line continuations now (turn them into spaces);
+ * the rest of the parsing code does not need to worry about them anymore. */
+ fixup_line_continuations(buffer.data() + buffer_offset,
+ buffer.data() + buffer_offset + bytes_read);
+
/* Ensure buffer ends in a newline. */
if (bytes_read < read_buffer_size_) {
if (bytes_read == 0 || buffer[buffer_offset + bytes_read - 1] != '\n') {
@@ -393,9 +398,7 @@ void OBJParser::parse(Vector<std::unique_ptr<Geometry>> &r_all_geometries,
while (last_nl > 0) {
--last_nl;
if (buffer[last_nl] == '\n') {
- if (last_nl < 1 || buffer[last_nl - 1] != '\\') {
- break;
- }
+ break;
}
}
if (buffer[last_nl] != '\n') {