Coverage Report

Created: 2026-04-01 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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