Coverage Report

Created: 2026-07-30 07:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/assimp/code/AssetLib/Ply/PlyParser.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 Defines the helper data structures for importing PLY files  */
43
#pragma once
44
#ifndef AI_PLYFILEHELPER_H_INC
45
#define AI_PLYFILEHELPER_H_INC
46
47
#include <assimp/ParsingUtils.h>
48
#include <assimp/IOStreamBuffer.h>
49
#include <vector>
50
51
namespace Assimp {
52
53
//pre-declaration
54
class PLYImporter;
55
56
// http://local.wasp.uwa.edu.au/~pbourke/dataformats/ply/
57
// http://w3.impa.br/~lvelho/outgoing/sossai/old/ViHAP_D4.4.2_PLY_format_v1.1.pdf
58
// http://www.okino.com/conv/exp_ply.htm
59
namespace PLY {
60
61
// ---------------------------------------------------------------------------------
62
/*
63
name        type        number of bytes
64
---------------------------------------
65
char       character                 1
66
uchar      unsigned character        1
67
short      short integer             2
68
ushort     unsigned short integer    2
69
int        integer                   4
70
uint       unsigned integer          4
71
float      single-precision float    4
72
double     double-precision float    8
73
74
int8
75
int16
76
uint8 ... forms are also used
77
*/
78
enum EDataType {
79
    EDT_Char = 0x0u,
80
    EDT_UChar,
81
    EDT_Short,
82
    EDT_UShort,
83
    EDT_Int,
84
    EDT_UInt,
85
    EDT_Float,
86
    EDT_Double,
87
88
    // Marks invalid entries
89
    EDT_INVALID
90
};
91
92
// ---------------------------------------------------------------------------------
93
/** \brief Specifies semantics for PLY element properties
94
 *
95
 * Semantics define the usage of a property, e.g. x coordinate
96
*/
97
enum ESemantic {
98
    //! vertex position x coordinate
99
    EST_XCoord = 0x0u,
100
    //! vertex position x coordinate
101
    EST_YCoord,
102
    //! vertex position x coordinate
103
    EST_ZCoord,
104
105
    //! vertex normal x coordinate
106
    EST_XNormal,
107
    //! vertex normal y coordinate
108
    EST_YNormal,
109
    //! vertex normal z coordinate
110
    EST_ZNormal,
111
112
    //! u texture coordinate
113
    EST_UTextureCoord,
114
    //! v texture coordinate
115
    EST_VTextureCoord,
116
117
    //! vertex colors, red channel
118
    EST_Red,
119
    //! vertex colors, green channel
120
    EST_Green,
121
    //! vertex colors, blue channel
122
    EST_Blue,
123
    //! vertex colors, alpha channel
124
    EST_Alpha,
125
126
    //! vertex index list
127
    EST_VertexIndex,
128
129
    //! texture index
130
    EST_TextureIndex,
131
132
    //! texture coordinates (stored as element of a face)
133
    EST_TextureCoordinates,
134
135
    //! material index
136
    EST_MaterialIndex,
137
138
    //! ambient color, red channel
139
    EST_AmbientRed,
140
    //! ambient color, green channel
141
    EST_AmbientGreen,
142
    //! ambient color, blue channel
143
    EST_AmbientBlue,
144
    //! ambient color, alpha channel
145
    EST_AmbientAlpha,
146
147
    //! diffuse color, red channel
148
    EST_DiffuseRed,
149
    //! diffuse color, green channel
150
    EST_DiffuseGreen,
151
    //! diffuse color, blue channel
152
    EST_DiffuseBlue,
153
    //! diffuse color, alpha channel
154
    EST_DiffuseAlpha,
155
156
    //! specular color, red channel
157
    EST_SpecularRed,
158
    //! specular color, green channel
159
    EST_SpecularGreen,
160
    //! specular color, blue channel
161
    EST_SpecularBlue,
162
    //! specular color, alpha channel
163
    EST_SpecularAlpha,
164
165
    //! specular power for phong shading
166
    EST_PhongPower,
167
168
    //! opacity between 0 and 1
169
    EST_Opacity,
170
171
    //! Marks invalid entries
172
    EST_INVALID
173
};
174
175
// ---------------------------------------------------------------------------------
176
/** \brief Specifies semantics for PLY elements
177
 *
178
 * Semantics define the usage of an element, e.g. vertex or material
179
*/
180
enum EElementSemantic {
181
    //! The element is a vertex
182
    EEST_Vertex = 0x0u,
183
184
    //! The element is a face description (index table)
185
    EEST_Face,
186
187
    //! The element is a triangle-strip description (index table)
188
    EEST_TriStrip,
189
190
    //! The element is an edge description (ignored)
191
    EEST_Edge,
192
193
    //! The element is a material description
194
    EEST_Material,
195
196
    //! texture path
197
    EEST_TextureFile,
198
199
    //! Marks invalid entries
200
    EEST_INVALID
201
};
202
203
// ---------------------------------------------------------------------------------
204
/** \brief Helper class for a property in a PLY file.
205
 *
206
 * This can e.g. be a part of the vertex declaration
207
 */
208
class Property {
209
public:
210
    //! Default constructor
211
    Property() AI_NO_EXCEPT
212
7.77k
    : eType (EDT_Int)
213
    , Semantic()
214
7.77k
    , bIsList(false)
215
7.77k
    , eFirstType(EDT_UChar) {
216
        // empty
217
7.77k
    }
218
219
    //! Data type of the property
220
    EDataType eType;
221
222
    //! Semantical meaning of the property
223
    ESemantic Semantic;
224
225
    //! Of the semantic of the property could not be parsed:
226
    //! Contains the semantic specified in the file
227
    std::string szName;
228
229
    //! Specifies whether the data type is a list where
230
    //! the first element specifies the size of the list
231
    bool bIsList;
232
    EDataType eFirstType;
233
234
    // -------------------------------------------------------------------
235
    //! Parse a property from a string. The end of the
236
    //! string is either '\n', '\r' or '\0'. Return value is false
237
    //! if the input string is NOT a valid property (E.g. does
238
    //! not start with the "property" keyword)
239
    static bool ParseProperty(std::vector<char> &buffer, Property* pOut);
240
241
    // -------------------------------------------------------------------
242
    //! Parse a data type from a string
243
    static EDataType ParseDataType(std::vector<char> &buffer);
244
245
    // -------------------------------------------------------------------
246
    //! Parse a semantic from a string
247
    static ESemantic ParseSemantic(std::vector<char> &buffer);
248
};
249
250
// ---------------------------------------------------------------------------------
251
/** \brief Helper class for an element in a PLY file.
252
 *
253
 * This can e.g. be the vertex declaration. Elements contain a
254
 * well-defined number of properties.
255
 */
256
class Element {
257
public:
258
    //! Default constructor
259
    Element() AI_NO_EXCEPT
260
49.0k
    : eSemantic (EEST_INVALID)
261
49.0k
    , NumOccur(0) {
262
        // empty
263
49.0k
    }
264
265
    //! List of properties assigned to the element
266
    //! std::vector to support operator[]
267
    std::vector<Property> alProperties;
268
269
    //! Semantic of the element
270
    EElementSemantic eSemantic;
271
272
    //! Of the semantic of the element could not be parsed:
273
    //! Contains the semantic specified in the file
274
    std::string szName;
275
276
    //! How many times will the element occur?
277
    unsigned int NumOccur;
278
279
280
    // -------------------------------------------------------------------
281
    //! Parse an element from a string.
282
    //! The function will parse all properties contained in the
283
    //! element, too.
284
    static bool ParseElement(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, Element* pOut);
285
286
    // -------------------------------------------------------------------
287
    //! Parse a semantic from a string
288
    static EElementSemantic ParseSemantic(std::vector<char> &buffer);
289
};
290
291
// ---------------------------------------------------------------------------------
292
/** \brief Instance of a property in a PLY file
293
 */
294
class PropertyInstance {
295
public:
296
    //! Default constructor
297
1.05M
    PropertyInstance() AI_NO_EXCEPT = default;
298
299
    union ValueUnion
300
    {
301
        //! uInt32 representation of the property. All
302
        // uint types are automatically converted to uint32
303
        uint32_t iUInt;
304
305
        //! Int32 representation of the property. All
306
        // int types are automatically converted to int32
307
        int32_t iInt;
308
309
        //! Float32 representation of the property
310
        float fFloat;
311
312
        //! Float64 representation of the property
313
        double fDouble;
314
315
    };
316
317
    // -------------------------------------------------------------------
318
    //! List of all values parsed. Contains only one value
319
    // for non-list properties
320
    std::vector<ValueUnion> avList;
321
322
    // -------------------------------------------------------------------
323
    //! Parse a property instance
324
    static bool ParseInstance(const char* &pCur, const char *end,
325
        const Property* prop, PropertyInstance* p_pcOut);
326
327
    // -------------------------------------------------------------------
328
    //! Parse a property instance in binary format
329
    static bool ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
330
        const char* &pCur, unsigned int &bufferSize, const Property* prop, PropertyInstance* p_pcOut, bool p_bBE);
331
332
    // -------------------------------------------------------------------
333
    //! Get the default value for a given data type
334
    static ValueUnion DefaultValue(EDataType eType);
335
336
    // -------------------------------------------------------------------
337
    //! Parse a value
338
    static bool ParseValue(const char* &pCur, EDataType eType, ValueUnion* out);
339
340
    // -------------------------------------------------------------------
341
    //! Parse a binary value
342
    static bool ParseValueBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
343
        const char* &pCur, unsigned int &bufferSize, EDataType eType, ValueUnion* out, bool p_bBE);
344
345
    // -------------------------------------------------------------------
346
    //! Convert a property value to a given type TYPE
347
    template <typename TYPE>
348
    static TYPE ConvertTo(ValueUnion v, EDataType eType);
349
};
350
351
using PropertyInstVec = std::vector<PropertyInstance::ValueUnion>;
352
353
// ---------------------------------------------------------------------------------
354
/// @brief Class for an element instance in a PLY file
355
// ---------------------------------------------------------------------------------
356
class ElementInstance {
357
public:
358
    //! Default constructor
359
553k
    ElementInstance() AI_NO_EXCEPT = default;
360
361
    //! List of all parsed properties
362
    std::vector< PropertyInstance > alProperties;
363
364
    // -------------------------------------------------------------------
365
    //! Parse an element instance
366
    static bool ParseInstance(const char *&pCur, const char *end,
367
        const Element* pcElement, ElementInstance* p_pcOut);
368
369
    // -------------------------------------------------------------------
370
    //! Parse a binary element instance
371
    static bool ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
372
        const char* &pCur, unsigned int &bufferSize, const Element* pcElement, ElementInstance* p_pcOut, bool p_bBE);
373
};
374
375
// ---------------------------------------------------------------------------------
376
/// @brief Class for an element instance list in a PLY file
377
// ---------------------------------------------------------------------------------
378
class ElementInstanceList {
379
public:
380
    /// Default constructor
381
747
    ElementInstanceList() AI_NO_EXCEPT = default;
382
383
    /// List of all element instances
384
    std::vector< ElementInstance > alInstances;
385
386
    // -------------------------------------------------------------------
387
    /// Parse an element instance list
388
    static bool ParseInstanceList(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
389
        const Element* pcElement, ElementInstanceList* p_pcOut, PLYImporter* loader);
390
391
    // -------------------------------------------------------------------
392
    //! Parse a binary element instance list
393
    static bool ParseInstanceListBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
394
        const char* &pCur, unsigned int &bufferSize, const Element* pcElement, ElementInstanceList* p_pcOut, PLYImporter* loader, bool p_bBE);
395
};
396
// ---------------------------------------------------------------------------------
397
/** \brief Class to represent the document object model of an ASCII or binary
398
 * (both little and big-endian) PLY file
399
 */
400
class DOM {
401
public:
402
    /// Default constructor
403
883
    DOM() AI_NO_EXCEPT = default;
404
405
406
    /// Contains all elements of the file format
407
    std::vector<Element> alElements;
408
    /// Contains the real data of each element's instance list
409
    std::vector<ElementInstanceList> alElementData;
410
411
    //! Parse the DOM for a PLY file. The input string is assumed
412
    //! to be terminated with zero
413
    static bool ParseInstance(IOStreamBuffer<char> &streamBuffer, DOM* p_pcOut, PLYImporter* loader);
414
    static bool ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, DOM* p_pcOut, PLYImporter* loader, bool p_bBE);
415
416
    //! Skip all comment lines after this
417
    static bool SkipComments(std::vector<char> buffer);
418
419
    static bool SkipSpaces(std::vector<char> &buffer);
420
421
    static bool SkipLine(std::vector<char> &buffer);
422
423
    static bool TokenMatch(std::vector<char> &buffer, const char* token, unsigned int len);
424
425
    static bool SkipSpacesAndLineEnd(std::vector<char> &buffer);
426
427
private:
428
429
    // -------------------------------------------------------------------
430
    //! Handle the file header and read all element descriptions
431
    bool ParseHeader(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, bool p_bBE);
432
433
    // -------------------------------------------------------------------
434
    //! Read in all element instance lists
435
    bool ParseElementInstanceLists(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, PLYImporter* loader);
436
437
    // -------------------------------------------------------------------
438
    //! Read in all element instance lists for a binary file format
439
    bool ParseElementInstanceListsBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, const char* &pCur, unsigned int &bufferSize, PLYImporter* loader, bool p_bBE);
440
};
441
442
// ---------------------------------------------------------------------------------
443
template <typename TYPE>
444
896k
inline TYPE PLY::PropertyInstance::ConvertTo(PLY::PropertyInstance::ValueUnion v, PLY::EDataType eType) {
445
896k
    switch (eType) {
446
568k
    case EDT_Float:
447
568k
        return (TYPE)v.fFloat;
448
113
    case EDT_Double:
449
113
        return (TYPE)v.fDouble;
450
451
33.5k
    case EDT_UInt:
452
33.6k
    case EDT_UShort:
453
323k
    case EDT_UChar:
454
323k
        return (TYPE)v.iUInt;
455
456
4.90k
    case EDT_Int:
457
4.90k
    case EDT_Short:
458
4.90k
    case EDT_Char:
459
4.90k
        return (TYPE)v.iInt;
460
0
    default: ;
461
896k
    };
462
0
    return (TYPE)0;
463
896k
}
float Assimp::PLY::PropertyInstance::ConvertTo<float>(Assimp::PLY::PropertyInstance::ValueUnion, Assimp::PLY::EDataType)
Line
Count
Source
444
568k
inline TYPE PLY::PropertyInstance::ConvertTo(PLY::PropertyInstance::ValueUnion v, PLY::EDataType eType) {
445
568k
    switch (eType) {
446
568k
    case EDT_Float:
447
568k
        return (TYPE)v.fFloat;
448
113
    case EDT_Double:
449
113
        return (TYPE)v.fDouble;
450
451
0
    case EDT_UInt:
452
0
    case EDT_UShort:
453
0
    case EDT_UChar:
454
0
        return (TYPE)v.iUInt;
455
456
0
    case EDT_Int:
457
0
    case EDT_Short:
458
0
    case EDT_Char:
459
0
        return (TYPE)v.iInt;
460
0
    default: ;
461
568k
    };
462
0
    return (TYPE)0;
463
568k
}
unsigned int Assimp::PLY::PropertyInstance::ConvertTo<unsigned int>(Assimp::PLY::PropertyInstance::ValueUnion, Assimp::PLY::EDataType)
Line
Count
Source
444
328k
inline TYPE PLY::PropertyInstance::ConvertTo(PLY::PropertyInstance::ValueUnion v, PLY::EDataType eType) {
445
328k
    switch (eType) {
446
0
    case EDT_Float:
447
0
        return (TYPE)v.fFloat;
448
0
    case EDT_Double:
449
0
        return (TYPE)v.fDouble;
450
451
33.5k
    case EDT_UInt:
452
33.6k
    case EDT_UShort:
453
323k
    case EDT_UChar:
454
323k
        return (TYPE)v.iUInt;
455
456
4.90k
    case EDT_Int:
457
4.90k
    case EDT_Short:
458
4.90k
    case EDT_Char:
459
4.90k
        return (TYPE)v.iInt;
460
0
    default: ;
461
328k
    };
462
0
    return (TYPE)0;
463
328k
}
Unexecuted instantiation: int Assimp::PLY::PropertyInstance::ConvertTo<int>(Assimp::PLY::PropertyInstance::ValueUnion, Assimp::PLY::EDataType)
464
465
} // Namespace PLY
466
} // Namespace AssImp
467
468
#endif // !! include guard