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:
authorJacques Lucke <jacques@blender.org>2020-03-20 14:41:27 +0300
committerJacques Lucke <jacques@blender.org>2020-03-20 14:41:27 +0300
commit3512be55e972b167882ff2ea2490d35b3aa628e6 (patch)
tree344c9cd7c95e5724aee1ef472981294109d28d10
parent4a4a36627e807536e14534795ca6d9876c590974 (diff)
improved file name parsing
-rw-r--r--source/blender/blenlib/BLI_string_ref.h60
-rw-r--r--source/blender/editors/object/object_obj_import.cc232
2 files changed, 242 insertions, 50 deletions
diff --git a/source/blender/blenlib/BLI_string_ref.h b/source/blender/blenlib/BLI_string_ref.h
index 2389542bcea..8936ed198a6 100644
--- a/source/blender/blenlib/BLI_string_ref.h
+++ b/source/blender/blenlib/BLI_string_ref.h
@@ -33,6 +33,7 @@
#include <string>
#include "BLI_array_ref.h"
+#include "BLI_string.h"
#include "BLI_utildefines.h"
namespace BLI {
@@ -104,11 +105,14 @@ class StringRefBase {
* Returns true when the string begins with the given prefix. Otherwise false.
*/
bool startswith(StringRef prefix) const;
+ bool startswith(char c) const;
+ bool startswith_lower_ascii(StringRef prefix) const;
/**
* Returns true when the string ends with the given suffix. Otherwise false.
*/
bool endswith(StringRef suffix) const;
+ bool endswith(char c) const;
StringRef substr(uint start, uint size) const;
};
@@ -182,6 +186,18 @@ class StringRef : public StringRefBase {
BLI_assert(this->startswith(prefix));
return this->drop_prefix(prefix.size());
}
+
+ StringRef drop_suffix(uint n) const
+ {
+ BLI_assert(n < m_size);
+ return StringRef(m_data, m_size - n);
+ }
+
+ StringRef drop_suffix(StringRef suffix) const
+ {
+ BLI_assert(this->endswith(suffix));
+ return this->drop_suffix(suffix.size());
+ }
};
/* More inline functions
@@ -230,6 +246,42 @@ inline bool StringRefBase::startswith(StringRef prefix) const
return true;
}
+inline char tolower_ascii(char c)
+{
+ if (c >= 'A' && c <= 'Z') {
+ return c + ('a' - 'A');
+ }
+ return c;
+}
+
+inline bool StringRefBase::startswith_lower_ascii(StringRef prefix) const
+{
+#ifdef DEBUG
+ for (char c : prefix) {
+ char lower_c = tolower_ascii(c);
+ BLI_assert(c == lower_c);
+ }
+#endif
+ if (m_size < prefix.m_size) {
+ return false;
+ }
+ for (uint i = 0; i < prefix.m_size; i++) {
+ char c = tolower_ascii(m_data[i]);
+ if (c != prefix.m_data[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+inline bool StringRefBase::startswith(char c) const
+{
+ if (m_size == 0) {
+ return false;
+ }
+ return m_data[0] == c;
+}
+
inline bool StringRefBase::endswith(StringRef suffix) const
{
if (m_size < suffix.m_size) {
@@ -244,6 +296,14 @@ inline bool StringRefBase::endswith(StringRef suffix) const
return true;
}
+inline bool StringRefBase::endswith(char c) const
+{
+ if (m_size == 0) {
+ return false;
+ }
+ return m_data[m_size - 1] == c;
+}
+
inline StringRef StringRefBase::substr(uint start, uint size) const
{
BLI_assert(start + size <= m_size);
diff --git a/source/blender/editors/object/object_obj_import.cc b/source/blender/editors/object/object_obj_import.cc
index 27900cca998..3dbe20bcecf 100644
--- a/source/blender/editors/object/object_obj_import.cc
+++ b/source/blender/editors/object/object_obj_import.cc
@@ -7,6 +7,7 @@
#include "BKE_mesh.h"
#include "BKE_object.h"
#include "BLI_set.h"
+#include "BLI_string.h"
#include "BLI_string_ref.h"
#include "BLI_vector.h"
#include "DNA_mesh_types.h"
@@ -129,10 +130,9 @@ struct ObjFileSegment {
};
struct ObjFileSegment_mtllib : public ObjFileSegment {
- std::string file_name;
+ Vector<std::string> file_names;
- ObjFileSegment_mtllib(StringRef file_name)
- : ObjFileSegment(ObjFileSegmentType::mtllib), file_name(file_name)
+ ObjFileSegment_mtllib() : ObjFileSegment(ObjFileSegmentType::mtllib)
{
}
};
@@ -228,6 +228,11 @@ static bool is_not_newline(char c)
return c != '\n';
}
+static bool is_newline(char c)
+{
+ return c == '\n';
+}
+
static std::pair<uint, uint> find_next_word_in_line(StringRef str)
{
uint offset = 0;
@@ -249,74 +254,201 @@ static std::pair<uint, uint> find_next_word_in_line(StringRef str)
return {offset, length};
}
+class StringRefStream {
+ private:
+ const char *m_current;
+ const char *m_end;
+
+ public:
+ StringRefStream(StringRef str) : m_current(str.begin()), m_end(str.end())
+ {
+ }
+
+ bool has_remaining_chars() const
+ {
+ return m_current < m_end;
+ }
+
+ char peek_next() const
+ {
+ BLI_assert(this->has_remaining_chars());
+ return m_current[0];
+ }
+
+ StringRef remaining_str() const
+ {
+ return StringRef(m_current, m_end - m_current);
+ }
+
+ bool startswith(StringRef other) const
+ {
+ return this->remaining_str().startswith(other);
+ }
+
+ bool startswith_lower_ascii(StringRef other) const
+ {
+ return this->remaining_str().startswith_lower_ascii(other);
+ }
+
+ bool startswith_and_forward_over(StringRef other)
+ {
+ if (this->startswith(other)) {
+ m_current += other.size();
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ /* Might not end with a newline character. */
+ StringRef extract_line()
+ {
+ const char *start = m_current;
+ while (m_current < m_end && *m_current != '\n') {
+ m_current++;
+ }
+ if (m_current < m_end) {
+ m_current++;
+ }
+ return StringRef(start, m_current - start);
+ }
+
+ StringRef extract_until(char c)
+ {
+ const char *start = m_current;
+ while (m_current < m_end && *m_current != c) {
+ m_current++;
+ }
+ return StringRef(start, m_current - start);
+ }
+
+ StringRef extract_quoted_string(char quote)
+ {
+ BLI_assert(this->peek_next() == quote);
+ m_current++;
+ StringRef str = this->extract_until(quote);
+ if (m_current < m_end) {
+ m_current++;
+ }
+ return str;
+ }
+
+ void forward_over_whitespace()
+ {
+ while (m_current < m_end && is_whitespace(*m_current)) {
+ m_current++;
+ }
+ }
+
+ void forward(uint i)
+ {
+ m_current += i;
+ BLI_assert(m_current <= m_end);
+ }
+
+ StringRef extract_including_ext(StringRef ext)
+ {
+ const char *start = m_current;
+ while (m_current < m_end) {
+ if (this->startswith_lower_ascii(ext)) {
+ m_current += ext.size();
+ if (m_current == m_end || ELEM(*m_current, ' ', '\t', '\r', '\n')) {
+ return StringRef(start, m_current - start);
+ }
+ }
+ else {
+ m_current++;
+ }
+ }
+ return "";
+ }
+};
+
+static void parse_file_names(StringRef str, StringRef ext, Vector<std::string> &r_names)
+{
+ if (str.endswith('\n')) {
+ str = str.drop_suffix("\n");
+ }
+ StringRefStream stream(str);
+ while (true) {
+ stream.forward_over_whitespace();
+ if (!stream.has_remaining_chars()) {
+ return;
+ }
+ if (stream.peek_next() == '"') {
+ StringRef name = stream.extract_quoted_string('"');
+ r_names.append(name);
+ }
+ else {
+ StringRef name = stream.extract_including_ext(ext);
+ r_names.append(name);
+ }
+ }
+}
+
static std::unique_ptr<ObjFileSegments> parse_obj_lines(StringRef orig_str)
{
- uint offset = 0;
- uint total_size = orig_str.size();
+ StringRefStream stream(orig_str);
auto segments = BLI::make_unique<ObjFileSegments>();
- while (offset < total_size) {
- const char current_char = orig_str[offset];
- switch (current_char) {
+ while (stream.has_remaining_chars()) {
+ StringRef line = stream.extract_line();
+ if (line.size() == 0) {
+ continue;
+ }
+ switch (line[0]) {
case ' ':
case '\t':
case '\r': {
- offset++;
break;
}
case '#': {
- offset += count_while(orig_str.drop_prefix(offset), is_not_newline) + 1;
break;
}
case 'm': {
- StringRef str = orig_str.drop_prefix(offset);
- if (str.startswith("mtllib")) {
- str = str.drop_prefix("mtllib");
- std::pair<uint, uint> word_span = find_next_word_in_line(str);
- StringRef file_name = str.substr(word_span.first, word_span.second);
- auto segment = BLI::make_unique<ObjFileSegment_mtllib>(file_name);
- segments->segments.append(std::move(segment));
- offset += strlen("mtllib") + word_span.first + word_span.second;
+ if (line.startswith("mtllib")) {
+ auto segment = BLI::make_unique<ObjFileSegment_mtllib>();
+ parse_file_names(line.drop_prefix("mtllib"), ".mtl", segment->file_names);
+ segment->file_names.as_ref().print_as_lines("File Names");
}
-
- offset += count_while(orig_str.drop_prefix(offset), is_not_newline) + 1;
break;
}
case 'o': {
- StringRef str = orig_str.drop_prefix(offset + strlen("o"));
- std::pair<uint, uint> word_span = find_next_word_in_line(str);
- StringRef object_name = str.substr(word_span.first, word_span.second);
- auto segment = BLI::make_unique<ObjFileSegment_o>(object_name);
- segments->segments.append(std::move(segment));
- offset += strlen("0") + word_span.first + word_span.second;
-
- offset += count_while(orig_str.drop_prefix(offset), is_not_newline) + 1;
+ // StringRef str = orig_str.drop_prefix(offset + strlen("o"));
+ // std::pair<uint, uint> word_span = find_next_word_in_line(str);
+ // StringRef object_name = str.substr(word_span.first, word_span.second);
+ // auto segment = BLI::make_unique<ObjFileSegment_o>(object_name);
+ // segments->segments.append(std::move(segment));
+ // offset += strlen("0") + word_span.first + word_span.second;
+
+ // offset += count_while(orig_str.drop_prefix(offset), is_not_newline) + 1;
break;
}
case 'v': {
- StringRef str = orig_str.drop_prefix(offset);
- if (str.startswith("v ")) {
- str = str.drop_prefix(1);
-
- std::pair<uint, uint> span1 = find_next_word_in_line(str);
- StringRef str1 = str.substr(span1.first, span1.second);
- str = str.drop_prefix(span1.first + span1.second);
-
- std::pair<uint, uint> span2 = find_next_word_in_line(str);
- StringRef str2 = str.substr(span2.first, span2.second);
- str = str.drop_prefix(span2.first + span2.second);
-
- std::pair<uint, uint> span3 = find_next_word_in_line(str);
- StringRef str3 = str.substr(span3.first, span3.second);
- }
- else if (str.startswith("vt")) {
- /* TODO */
- }
- else if (str.startswith("vn")) {
- /* TODO */
- }
- offset += count_while(orig_str.drop_prefix(offset), is_not_newline) + 1;
+ // StringRef str = orig_str.drop_prefix(offset);
+ // if (str.startswith("v ")) {
+ // str = str.drop_prefix(1);
+
+ // std::pair<uint, uint> span1 = find_next_word_in_line(str);
+ // StringRef str1 = str.substr(span1.first, span1.second);
+ // str = str.drop_prefix(span1.first + span1.second);
+
+ // std::pair<uint, uint> span2 = find_next_word_in_line(str);
+ // StringRef str2 = str.substr(span2.first, span2.second);
+ // str = str.drop_prefix(span2.first + span2.second);
+
+ // std::pair<uint, uint> span3 = find_next_word_in_line(str);
+ // StringRef str3 = str.substr(span3.first, span3.second);
+ // }
+ // else if (str.startswith("vt")) {
+ // /* TODO */
+ // }
+ // else if (str.startswith("vn")) {
+ // /* TODO */
+ // }
+ // offset += count_while(orig_str.drop_prefix(offset), is_not_newline) + 1;
break;
}
default: {