Blender V4.3
obj_import_string_utils.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
6
7/* NOTE: we could use C++17 <charconv> from_chars to parse
8 * floats, but even if some compilers claim full support,
9 * their standard libraries are not quite there yet.
10 * LLVM/libc++ only has a float parser since LLVM 14,
11 * and gcc/libstdc++ since 11.1. So until at least these are
12 * the minimum spec, use an external library. */
13#include "fast_float.h"
14#include <charconv>
15
16namespace blender::io::obj {
17
19{
20 const char *start = buffer.begin();
21 const char *end = buffer.end();
22 size_t len = 0;
23 const char *ptr = start;
24 while (ptr < end) {
25 char c = *ptr++;
26 if (c == '\n') {
27 break;
28 }
29 ++len;
30 }
31
32 buffer = StringRef(ptr, end);
33 return StringRef(start, len);
34}
35
36static bool is_whitespace(char c)
37{
38 return c <= ' ';
39}
40
41void fixup_line_continuations(char *p, char *end)
42{
43 while (true) {
44 /* Find next backslash, if any. */
45 char *backslash = std::find(p, end, '\\');
46 if (backslash == end) {
47 break;
48 }
49 /* Skip over possible whitespace right after it. */
50 p = backslash + 1;
51 while (p < end && is_whitespace(*p) && *p != '\n') {
52 ++p;
53 }
54 /* If then we have a newline, turn both backslash
55 * and the newline into regular spaces. */
56 if (p < end && *p == '\n') {
57 *backslash = ' ';
58 *p = ' ';
59 }
60 }
61}
62
63const char *drop_whitespace(const char *p, const char *end)
64{
65 while (p < end && is_whitespace(*p)) {
66 ++p;
67 }
68 return p;
69}
70
71const char *drop_non_whitespace(const char *p, const char *end)
72{
73 while (p < end && !is_whitespace(*p)) {
74 ++p;
75 }
76 return p;
77}
78
79static const char *drop_plus(const char *p, const char *end)
80{
81 if (p < end && *p == '+') {
82 ++p;
83 }
84 return p;
85}
86
87const char *parse_float(const char *p,
88 const char *end,
89 float fallback,
90 float &dst,
91 bool skip_space,
92 bool require_trailing_space)
93{
94 if (skip_space) {
95 p = drop_whitespace(p, end);
96 }
97 p = drop_plus(p, end);
98 fast_float::from_chars_result res = fast_float::from_chars(p, end, dst);
99 if (ELEM(res.ec, std::errc::invalid_argument, std::errc::result_out_of_range)) {
100 dst = fallback;
101 }
102 else if (require_trailing_space && res.ptr < end && !is_whitespace(*res.ptr)) {
103 /* If there are trailing non-space characters, do not eat up the number. */
104 dst = fallback;
105 return p;
106 }
107 return res.ptr;
108}
109
110const char *parse_floats(const char *p,
111 const char *end,
112 float fallback,
113 float *dst,
114 int count,
115 bool require_trailing_space)
116{
117 for (int i = 0; i < count; ++i) {
118 p = parse_float(p, end, fallback, dst[i], true, require_trailing_space);
119 }
120 return p;
121}
122
123const char *parse_int(const char *p, const char *end, int fallback, int &dst, bool skip_space)
124{
125 if (skip_space) {
126 p = drop_whitespace(p, end);
127 }
128 p = drop_plus(p, end);
129 std::from_chars_result res = std::from_chars(p, end, dst);
130 if (ELEM(res.ec, std::errc::invalid_argument, std::errc::result_out_of_range)) {
131 dst = fallback;
132 }
133 return res.ptr;
134}
135
136} // namespace blender::io::obj
#define ELEM(...)
constexpr const char * begin() const
constexpr const char * end() const
int len
int count
static bool is_whitespace(char c)
static const char * drop_plus(const char *p, const char *end)
const char * parse_floats(const char *p, const char *end, float fallback, float *dst, int count, bool require_trailing_space)
void fixup_line_continuations(char *p, char *end)
const char * drop_non_whitespace(const char *p, const char *end)
const char * parse_int(const char *p, const char *end, int fallback, int &dst, bool skip_space)
const char * drop_whitespace(const char *p, const char *end)
StringRef read_next_line(StringRef &buffer)
const char * parse_float(const char *p, const char *end, float fallback, float &dst, bool skip_space, bool require_trailing_space)
PointerRNA * ptr
Definition wm_files.cc:4126