/src/assimp/code/AssetLib/Obj/ObjTools.h
Line | Count | Source |
1 | | /* |
2 | | Open Asset Import Library (assimp) |
3 | | ---------------------------------------------------------------------- |
4 | | |
5 | | Copyright (c) 2006-2026, assimp team |
6 | | |
7 | | All rights reserved. |
8 | | |
9 | | Redistribution and use of this software in source and binary forms, |
10 | | with or without modification, are permitted provided that the |
11 | | following conditions are met: |
12 | | |
13 | | * Redistributions of source code must retain the above |
14 | | copyright notice, this list of conditions and the |
15 | | following disclaimer. |
16 | | |
17 | | * Redistributions in binary form must reproduce the above |
18 | | copyright notice, this list of conditions and the |
19 | | following disclaimer in the documentation and/or other |
20 | | materials provided with the distribution. |
21 | | |
22 | | * Neither the name of the assimp team, nor the names of its |
23 | | contributors may be used to endorse or promote products |
24 | | derived from this software without specific prior |
25 | | written permission of the assimp team. |
26 | | |
27 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
28 | | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
29 | | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
30 | | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
31 | | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
32 | | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
33 | | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
34 | | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
35 | | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
36 | | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
37 | | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
38 | | |
39 | | ---------------------------------------------------------------------- |
40 | | */ |
41 | | |
42 | | /** @file ObjTools.h |
43 | | * @brief Some helpful templates for text parsing |
44 | | */ |
45 | | #ifndef OBJ_TOOLS_H_INC |
46 | | #define OBJ_TOOLS_H_INC |
47 | | |
48 | | #include <assimp/ParsingUtils.h> |
49 | | #include <assimp/fast_atof.h> |
50 | | #include <vector> |
51 | | |
52 | | namespace Assimp { |
53 | | |
54 | | /** |
55 | | * @brief Returns true, if the last entry of the buffer is reached. |
56 | | * @param[in] it Iterator of current position. |
57 | | * @param[in] end Iterator with end of buffer. |
58 | | * @return true, if the end of the buffer is reached. |
59 | | */ |
60 | | template <class char_t> |
61 | 137M | inline bool isEndOfBuffer(char_t it, char_t end) { |
62 | 137M | if (it == end) { |
63 | 0 | return true; |
64 | 0 | } |
65 | 137M | --end; |
66 | | |
67 | 137M | return (it == end); |
68 | 137M | } |
69 | | |
70 | | /** |
71 | | * @brief Returns next word separated by a space |
72 | | * @param[in] pBuffer Pointer to data buffer |
73 | | * @param[in] pEnd Pointer to end of buffer |
74 | | * @return Pointer to next space |
75 | | */ |
76 | | template <class Char_T> |
77 | 4.08M | inline Char_T getNextWord(Char_T pBuffer, Char_T pEnd) { |
78 | 11.4M | while (!isEndOfBuffer(pBuffer, pEnd)) { |
79 | 11.4M | if (!IsSpaceOrNewLine(*pBuffer) || IsLineEnd(*pBuffer)) { |
80 | 4.08M | break; |
81 | 4.08M | } |
82 | 7.32M | ++pBuffer; |
83 | 7.32M | } |
84 | | |
85 | 4.08M | return pBuffer; |
86 | 4.08M | } |
87 | | |
88 | | /** |
89 | | * @brief Returns next space |
90 | | * @param[in] pBuffer Pointer to data buffer |
91 | | * @param[in] pEnd Pointer to end of buffer |
92 | | * @return Pointer to next space |
93 | | */ |
94 | | template <class Char_T> |
95 | 4.01M | inline Char_T getNextDelimiter(Char_T pBuffer, Char_T pEnd) { |
96 | 34.7M | while (!isEndOfBuffer(pBuffer, pEnd)) { |
97 | 34.7M | if (IsSpaceOrNewLine(*pBuffer)) { |
98 | 4.01M | break; |
99 | 4.01M | } |
100 | 30.6M | ++pBuffer; |
101 | 30.6M | } |
102 | 4.01M | return pBuffer; |
103 | 4.01M | } |
104 | | |
105 | | /** |
106 | | * @brief Returns pointer a next token |
107 | | * @param[in] pBuffer Pointer to data buffer |
108 | | * @param[in] pEnd Pointer to end of buffer |
109 | | * @return Pointer to next token |
110 | | */ |
111 | | template <class Char_T> |
112 | 357k | inline Char_T getNextToken(Char_T pBuffer, Char_T pEnd) { |
113 | 357k | pBuffer = getNextDelimiter(pBuffer, pEnd); |
114 | 357k | return getNextWord(pBuffer, pEnd); |
115 | 357k | } |
116 | | |
117 | | /** |
118 | | * @brief Skips a line |
119 | | * @param[in] it Iterator set to current position |
120 | | * @param[in] end Iterator set to end of scratch buffer for readout |
121 | | * @param[out] uiLine Current line number in format |
122 | | * @return Current-iterator with new position |
123 | | */ |
124 | | template <class char_t> |
125 | 6.84M | inline char_t skipLine(char_t it, char_t end, unsigned int &uiLine) { |
126 | 6.84M | if (it >= end) { |
127 | 1.59k | return it; |
128 | 1.59k | } |
129 | | |
130 | 87.5M | while (!isEndOfBuffer(it, end) && !IsLineEnd(*it)) { |
131 | 80.7M | ++it; |
132 | 80.7M | } |
133 | | |
134 | 6.84M | if (it != end) { |
135 | 6.84M | ++it; |
136 | 6.84M | ++uiLine; |
137 | 6.84M | } |
138 | | // fix .. from time to time there are spaces at the beginning of a material line |
139 | 7.38M | while (it != end && (*it == '\t' || *it == ' ')) { |
140 | 539k | ++it; |
141 | 539k | } |
142 | | |
143 | 6.84M | return it; |
144 | 6.84M | } |
145 | | |
146 | | /** |
147 | | * @brief Get a name from the current line. Preserve space in the middle, |
148 | | * but trim it at the end. |
149 | | * @param[in] it set to current position |
150 | | * @param[in] end set to end of scratch buffer for readout |
151 | | * @param[out] name Separated name |
152 | | * @return Current-iterator with new position |
153 | | */ |
154 | | template <class char_t> |
155 | 260k | inline char_t getName(char_t it, char_t end, std::string &name) { |
156 | 260k | name = ""; |
157 | 260k | if (isEndOfBuffer(it, end)) { |
158 | 1.59k | return end; |
159 | 1.59k | } |
160 | | |
161 | 258k | char *pStart = &(*it); |
162 | 2.98M | while (!isEndOfBuffer(it, end) && !IsLineEnd(*it)) { |
163 | 2.72M | ++it; |
164 | 2.72M | } |
165 | | |
166 | 258k | while (IsSpace(*it)) { |
167 | 0 | --it; |
168 | 0 | } |
169 | | // Get name |
170 | | // if there is no name, and the previous char is a separator, come back to start |
171 | 258k | while (&(*it) < pStart) { |
172 | 0 | ++it; |
173 | 0 | } |
174 | 258k | std::string strName(pStart, &(*it)); |
175 | 258k | if (!strName.empty()) { |
176 | 247k | name = strName; |
177 | 247k | } |
178 | | |
179 | | |
180 | 258k | return it; |
181 | 260k | } |
182 | | |
183 | | /** |
184 | | * @brief Get a name from the current line. Do not preserve space |
185 | | * in the middle, but trim it at the end. |
186 | | * @param it set to current position |
187 | | * @param end set to end of scratch buffer for readout |
188 | | * @param name Separated name |
189 | | * @return Current-iterator with new position |
190 | | */ |
191 | | template <class char_t> |
192 | 12.7k | inline char_t getNameNoSpace(char_t it, char_t end, std::string &name) { |
193 | 12.7k | name = ""; |
194 | 12.7k | if (isEndOfBuffer(it, end)) { |
195 | 0 | return end; |
196 | 0 | } |
197 | | |
198 | 12.7k | char *pStart = &(*it); |
199 | 114k | while (!isEndOfBuffer(it, end) && !IsLineEnd(*it) && !IsSpaceOrNewLine(*it)) { |
200 | 101k | ++it; |
201 | 101k | } |
202 | | |
203 | 25.4k | while (isEndOfBuffer(it, end) || IsLineEnd(*it) || IsSpaceOrNewLine(*it)) { |
204 | 12.7k | --it; |
205 | 12.7k | } |
206 | 12.7k | ++it; |
207 | | |
208 | | // Get name |
209 | | // if there is no name, and the previous char is a separator, come back to start |
210 | 12.7k | while (&(*it) < pStart) { |
211 | 0 | ++it; |
212 | 0 | } |
213 | 12.7k | std::string strName(pStart, &(*it)); |
214 | 12.7k | if (!strName.empty()) { |
215 | 12.7k | name = strName; |
216 | 12.7k | } |
217 | | |
218 | 12.7k | return it; |
219 | 12.7k | } |
220 | | |
221 | | /** |
222 | | * @brief Get next word from given line |
223 | | * @param[in] it set to current position |
224 | | * @param[in] end set to end of scratch buffer for readout |
225 | | * @param[in] pBuffer Buffer for next word |
226 | | * @param[in] length Buffer length |
227 | | * @return Current-iterator with new position |
228 | | */ |
229 | | template <class char_t> |
230 | 17.8k | inline char_t CopyNextWord(char_t it, char_t end, char *pBuffer, size_t length) { |
231 | 17.8k | size_t index = 0; |
232 | 17.8k | it = getNextWord<char_t>(it, end); |
233 | 142k | while (!IsSpaceOrNewLine(*it) && !isEndOfBuffer(it, end)) { |
234 | 125k | pBuffer[index] = *it; |
235 | 125k | ++index; |
236 | 125k | if (index == length - 1) { |
237 | 542 | break; |
238 | 542 | } |
239 | 125k | ++it; |
240 | 125k | } |
241 | 17.8k | pBuffer[index] = '\0'; |
242 | 17.8k | return it; |
243 | 17.8k | } |
244 | | |
245 | | /** |
246 | | * @brief Get next float from given line |
247 | | * @param[in] it set to current position |
248 | | * @param[in] end set to end of scratch buffer for readout |
249 | | * @param[out] value Separated float value. |
250 | | * @return Current-iterator with new position |
251 | | */ |
252 | | template <class char_t> |
253 | 840 | inline char_t getFloat(char_t it, char_t end, ai_real &value) { |
254 | 840 | static const size_t BUFFERSIZE = 1024; |
255 | 840 | char buffer[BUFFERSIZE] = {}; |
256 | 840 | it = CopyNextWord<char_t>(it, end, buffer, BUFFERSIZE); |
257 | 840 | value = (ai_real)fast_atof(buffer); |
258 | | |
259 | 840 | return it; |
260 | 840 | } |
261 | | |
262 | | /** |
263 | | * @brief Checks for a line-end. |
264 | | * @param[in] it Current iterator in string. |
265 | | * @param[in] end End of the string. |
266 | | * @return The trimmed string. |
267 | | */ |
268 | | template <class T> |
269 | | bool hasLineEnd(T it, T end) { |
270 | | bool hasLineEnd = false; |
271 | | while (!isEndOfBuffer(it, end)) { |
272 | | ++it; |
273 | | if (IsLineEnd(it)) { |
274 | | hasLineEnd = true; |
275 | | break; |
276 | | } |
277 | | } |
278 | | |
279 | | return hasLineEnd; |
280 | | } |
281 | | |
282 | | } // Namespace Assimp |
283 | | |
284 | | #endif // OBJ_TOOLS_H_INC |