Coverage Report

Created: 2026-03-12 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/assimp/code/AssetLib/Blender/BlenderCustomData.cpp
Line
Count
Source
1
#include "BlenderCustomData.h"
2
#include "BlenderDNA.h"
3
#include <array>
4
#include <functional>
5
6
namespace Assimp {
7
namespace Blender {
8
/**
9
        *   @brief  read/convert of Structure array to memory
10
        */
11
template <typename T>
12
148
bool read(const Structure &s, T *p, const size_t cnt, const FileDatabase &db) {
13
37.2k
    for (size_t i = 0; i < cnt; ++i) {
14
37.0k
        T read;
15
37.0k
        s.Convert(read, db);
16
37.0k
        *p = read;
17
37.0k
        p++;
18
37.0k
    }
19
148
    return true;
20
148
}
bool Assimp::Blender::read<Assimp::Blender::MVert>(Assimp::Blender::Structure const&, Assimp::Blender::MVert*, unsigned long, Assimp::Blender::FileDatabase const&)
Line
Count
Source
12
42
bool read(const Structure &s, T *p, const size_t cnt, const FileDatabase &db) {
13
9.05k
    for (size_t i = 0; i < cnt; ++i) {
14
9.01k
        T read;
15
9.01k
        s.Convert(read, db);
16
9.01k
        *p = read;
17
9.01k
        p++;
18
9.01k
    }
19
42
    return true;
20
42
}
bool Assimp::Blender::read<Assimp::Blender::MEdge>(Assimp::Blender::Structure const&, Assimp::Blender::MEdge*, unsigned long, Assimp::Blender::FileDatabase const&)
Line
Count
Source
12
42
bool read(const Structure &s, T *p, const size_t cnt, const FileDatabase &db) {
13
17.0k
    for (size_t i = 0; i < cnt; ++i) {
14
16.9k
        T read;
15
16.9k
        s.Convert(read, db);
16
16.9k
        *p = read;
17
16.9k
        p++;
18
16.9k
    }
19
42
    return true;
20
42
}
bool Assimp::Blender::read<Assimp::Blender::MFace>(Assimp::Blender::Structure const&, Assimp::Blender::MFace*, unsigned long, Assimp::Blender::FileDatabase const&)
Line
Count
Source
12
31
bool read(const Structure &s, T *p, const size_t cnt, const FileDatabase &db) {
13
7.54k
    for (size_t i = 0; i < cnt; ++i) {
14
7.51k
        T read;
15
7.51k
        s.Convert(read, db);
16
7.51k
        *p = read;
17
7.51k
        p++;
18
7.51k
    }
19
31
    return true;
20
31
}
bool Assimp::Blender::read<Assimp::Blender::MTFace>(Assimp::Blender::Structure const&, Assimp::Blender::MTFace*, unsigned long, Assimp::Blender::FileDatabase const&)
Line
Count
Source
12
4
bool read(const Structure &s, T *p, const size_t cnt, const FileDatabase &db) {
13
18
    for (size_t i = 0; i < cnt; ++i) {
14
14
        T read;
15
14
        s.Convert(read, db);
16
14
        *p = read;
17
14
        p++;
18
14
    }
19
4
    return true;
20
4
}
bool Assimp::Blender::read<Assimp::Blender::MTexPoly>(Assimp::Blender::Structure const&, Assimp::Blender::MTexPoly*, unsigned long, Assimp::Blender::FileDatabase const&)
Line
Count
Source
12
3
bool read(const Structure &s, T *p, const size_t cnt, const FileDatabase &db) {
13
49
    for (size_t i = 0; i < cnt; ++i) {
14
46
        T read;
15
46
        s.Convert(read, db);
16
46
        *p = read;
17
46
        p++;
18
46
    }
19
3
    return true;
20
3
}
bool Assimp::Blender::read<Assimp::Blender::MLoopUV>(Assimp::Blender::Structure const&, Assimp::Blender::MLoopUV*, unsigned long, Assimp::Blender::FileDatabase const&)
Line
Count
Source
12
4
bool read(const Structure &s, T *p, const size_t cnt, const FileDatabase &db) {
13
168
    for (size_t i = 0; i < cnt; ++i) {
14
164
        T read;
15
164
        s.Convert(read, db);
16
164
        *p = read;
17
164
        p++;
18
164
    }
19
4
    return true;
20
4
}
Unexecuted instantiation: bool Assimp::Blender::read<Assimp::Blender::MLoopCol>(Assimp::Blender::Structure const&, Assimp::Blender::MLoopCol*, unsigned long, Assimp::Blender::FileDatabase const&)
bool Assimp::Blender::read<Assimp::Blender::MPoly>(Assimp::Blender::Structure const&, Assimp::Blender::MPoly*, unsigned long, Assimp::Blender::FileDatabase const&)
Line
Count
Source
12
11
bool read(const Structure &s, T *p, const size_t cnt, const FileDatabase &db) {
13
694
    for (size_t i = 0; i < cnt; ++i) {
14
683
        T read;
15
683
        s.Convert(read, db);
16
683
        *p = read;
17
683
        p++;
18
683
    }
19
11
    return true;
20
11
}
bool Assimp::Blender::read<Assimp::Blender::MLoop>(Assimp::Blender::Structure const&, Assimp::Blender::MLoop*, unsigned long, Assimp::Blender::FileDatabase const&)
Line
Count
Source
12
11
bool read(const Structure &s, T *p, const size_t cnt, const FileDatabase &db) {
13
2.66k
    for (size_t i = 0; i < cnt; ++i) {
14
2.65k
        T read;
15
2.65k
        s.Convert(read, db);
16
2.65k
        *p = read;
17
2.65k
        p++;
18
2.65k
    }
19
11
    return true;
20
11
}
21
22
/**
23
        *   @brief  pointer to function read memory for n CustomData types
24
        */
25
typedef bool (*PRead)(ElemBase *pOut, const size_t cnt, const FileDatabase &db);
26
typedef ElemBase *(*PCreate)(const size_t cnt);
27
typedef void (*PDestroy)(ElemBase *);
28
29
#define IMPL_STRUCT_READ(ty)                                               \
30
148
    bool read##ty(ElemBase *v, const size_t cnt, const FileDatabase &db) { \
31
148
        ty *ptr = dynamic_cast<ty *>(v);                                   \
32
148
        if (nullptr == ptr) {                                              \
33
0
            return false;                                                  \
34
0
        }                                                                  \
35
148
        return read<ty>(db.dna[#ty], ptr, cnt, db);                        \
36
148
    }
Assimp::Blender::readMVert(Assimp::Blender::ElemBase*, unsigned long, Assimp::Blender::FileDatabase const&)
Line
Count
Source
30
42
    bool read##ty(ElemBase *v, const size_t cnt, const FileDatabase &db) { \
31
42
        ty *ptr = dynamic_cast<ty *>(v);                                   \
32
42
        if (nullptr == ptr) {                                              \
33
0
            return false;                                                  \
34
0
        }                                                                  \
35
42
        return read<ty>(db.dna[#ty], ptr, cnt, db);                        \
36
42
    }
Assimp::Blender::readMEdge(Assimp::Blender::ElemBase*, unsigned long, Assimp::Blender::FileDatabase const&)
Line
Count
Source
30
42
    bool read##ty(ElemBase *v, const size_t cnt, const FileDatabase &db) { \
31
42
        ty *ptr = dynamic_cast<ty *>(v);                                   \
32
42
        if (nullptr == ptr) {                                              \
33
0
            return false;                                                  \
34
0
        }                                                                  \
35
42
        return read<ty>(db.dna[#ty], ptr, cnt, db);                        \
36
42
    }
Assimp::Blender::readMFace(Assimp::Blender::ElemBase*, unsigned long, Assimp::Blender::FileDatabase const&)
Line
Count
Source
30
31
    bool read##ty(ElemBase *v, const size_t cnt, const FileDatabase &db) { \
31
31
        ty *ptr = dynamic_cast<ty *>(v);                                   \
32
31
        if (nullptr == ptr) {                                              \
33
0
            return false;                                                  \
34
0
        }                                                                  \
35
31
        return read<ty>(db.dna[#ty], ptr, cnt, db);                        \
36
31
    }
Assimp::Blender::readMTFace(Assimp::Blender::ElemBase*, unsigned long, Assimp::Blender::FileDatabase const&)
Line
Count
Source
30
4
    bool read##ty(ElemBase *v, const size_t cnt, const FileDatabase &db) { \
31
4
        ty *ptr = dynamic_cast<ty *>(v);                                   \
32
4
        if (nullptr == ptr) {                                              \
33
0
            return false;                                                  \
34
0
        }                                                                  \
35
4
        return read<ty>(db.dna[#ty], ptr, cnt, db);                        \
36
4
    }
Assimp::Blender::readMTexPoly(Assimp::Blender::ElemBase*, unsigned long, Assimp::Blender::FileDatabase const&)
Line
Count
Source
30
3
    bool read##ty(ElemBase *v, const size_t cnt, const FileDatabase &db) { \
31
3
        ty *ptr = dynamic_cast<ty *>(v);                                   \
32
3
        if (nullptr == ptr) {                                              \
33
0
            return false;                                                  \
34
0
        }                                                                  \
35
3
        return read<ty>(db.dna[#ty], ptr, cnt, db);                        \
36
3
    }
Assimp::Blender::readMLoopUV(Assimp::Blender::ElemBase*, unsigned long, Assimp::Blender::FileDatabase const&)
Line
Count
Source
30
4
    bool read##ty(ElemBase *v, const size_t cnt, const FileDatabase &db) { \
31
4
        ty *ptr = dynamic_cast<ty *>(v);                                   \
32
4
        if (nullptr == ptr) {                                              \
33
0
            return false;                                                  \
34
0
        }                                                                  \
35
4
        return read<ty>(db.dna[#ty], ptr, cnt, db);                        \
36
4
    }
Unexecuted instantiation: Assimp::Blender::readMLoopCol(Assimp::Blender::ElemBase*, unsigned long, Assimp::Blender::FileDatabase const&)
Assimp::Blender::readMPoly(Assimp::Blender::ElemBase*, unsigned long, Assimp::Blender::FileDatabase const&)
Line
Count
Source
30
11
    bool read##ty(ElemBase *v, const size_t cnt, const FileDatabase &db) { \
31
11
        ty *ptr = dynamic_cast<ty *>(v);                                   \
32
11
        if (nullptr == ptr) {                                              \
33
0
            return false;                                                  \
34
0
        }                                                                  \
35
11
        return read<ty>(db.dna[#ty], ptr, cnt, db);                        \
36
11
    }
Assimp::Blender::readMLoop(Assimp::Blender::ElemBase*, unsigned long, Assimp::Blender::FileDatabase const&)
Line
Count
Source
30
11
    bool read##ty(ElemBase *v, const size_t cnt, const FileDatabase &db) { \
31
11
        ty *ptr = dynamic_cast<ty *>(v);                                   \
32
11
        if (nullptr == ptr) {                                              \
33
0
            return false;                                                  \
34
0
        }                                                                  \
35
11
        return read<ty>(db.dna[#ty], ptr, cnt, db);                        \
36
11
    }
37
38
#define IMPL_STRUCT_CREATE(ty)               \
39
148
    ElemBase *create##ty(const size_t cnt) { \
40
148
        return new ty[cnt];                  \
41
148
    }
Assimp::Blender::createMVert(unsigned long)
Line
Count
Source
39
42
    ElemBase *create##ty(const size_t cnt) { \
40
42
        return new ty[cnt];                  \
41
42
    }
Assimp::Blender::createMEdge(unsigned long)
Line
Count
Source
39
42
    ElemBase *create##ty(const size_t cnt) { \
40
42
        return new ty[cnt];                  \
41
42
    }
Assimp::Blender::createMFace(unsigned long)
Line
Count
Source
39
31
    ElemBase *create##ty(const size_t cnt) { \
40
31
        return new ty[cnt];                  \
41
31
    }
Assimp::Blender::createMTFace(unsigned long)
Line
Count
Source
39
4
    ElemBase *create##ty(const size_t cnt) { \
40
4
        return new ty[cnt];                  \
41
4
    }
Assimp::Blender::createMTexPoly(unsigned long)
Line
Count
Source
39
3
    ElemBase *create##ty(const size_t cnt) { \
40
3
        return new ty[cnt];                  \
41
3
    }
Assimp::Blender::createMLoopUV(unsigned long)
Line
Count
Source
39
4
    ElemBase *create##ty(const size_t cnt) { \
40
4
        return new ty[cnt];                  \
41
4
    }
Unexecuted instantiation: Assimp::Blender::createMLoopCol(unsigned long)
Assimp::Blender::createMPoly(unsigned long)
Line
Count
Source
39
11
    ElemBase *create##ty(const size_t cnt) { \
40
11
        return new ty[cnt];                  \
41
11
    }
Assimp::Blender::createMLoop(unsigned long)
Line
Count
Source
39
11
    ElemBase *create##ty(const size_t cnt) { \
40
11
        return new ty[cnt];                  \
41
11
    }
42
43
#define IMPL_STRUCT_DESTROY(ty)         \
44
148
    void destroy##ty(ElemBase *pE) {    \
45
148
        ty *p = dynamic_cast<ty *>(pE); \
46
148
        delete[] p;                     \
47
148
    }
Assimp::Blender::destroyMVert(Assimp::Blender::ElemBase*)
Line
Count
Source
44
42
    void destroy##ty(ElemBase *pE) {    \
45
42
        ty *p = dynamic_cast<ty *>(pE); \
46
42
        delete[] p;                     \
47
42
    }
Assimp::Blender::destroyMEdge(Assimp::Blender::ElemBase*)
Line
Count
Source
44
42
    void destroy##ty(ElemBase *pE) {    \
45
42
        ty *p = dynamic_cast<ty *>(pE); \
46
42
        delete[] p;                     \
47
42
    }
Assimp::Blender::destroyMFace(Assimp::Blender::ElemBase*)
Line
Count
Source
44
31
    void destroy##ty(ElemBase *pE) {    \
45
31
        ty *p = dynamic_cast<ty *>(pE); \
46
31
        delete[] p;                     \
47
31
    }
Assimp::Blender::destroyMTFace(Assimp::Blender::ElemBase*)
Line
Count
Source
44
4
    void destroy##ty(ElemBase *pE) {    \
45
4
        ty *p = dynamic_cast<ty *>(pE); \
46
4
        delete[] p;                     \
47
4
    }
Assimp::Blender::destroyMTexPoly(Assimp::Blender::ElemBase*)
Line
Count
Source
44
3
    void destroy##ty(ElemBase *pE) {    \
45
3
        ty *p = dynamic_cast<ty *>(pE); \
46
3
        delete[] p;                     \
47
3
    }
Assimp::Blender::destroyMLoopUV(Assimp::Blender::ElemBase*)
Line
Count
Source
44
4
    void destroy##ty(ElemBase *pE) {    \
45
4
        ty *p = dynamic_cast<ty *>(pE); \
46
4
        delete[] p;                     \
47
4
    }
Unexecuted instantiation: Assimp::Blender::destroyMLoopCol(Assimp::Blender::ElemBase*)
Assimp::Blender::destroyMPoly(Assimp::Blender::ElemBase*)
Line
Count
Source
44
11
    void destroy##ty(ElemBase *pE) {    \
45
11
        ty *p = dynamic_cast<ty *>(pE); \
46
11
        delete[] p;                     \
47
11
    }
Assimp::Blender::destroyMLoop(Assimp::Blender::ElemBase*)
Line
Count
Source
44
11
    void destroy##ty(ElemBase *pE) {    \
45
11
        ty *p = dynamic_cast<ty *>(pE); \
46
11
        delete[] p;                     \
47
11
    }
48
49
/**
50
        *   @brief  helper macro to define Structure functions
51
        */
52
#define IMPL_STRUCT(ty)    \
53
    IMPL_STRUCT_READ(ty)   \
54
    IMPL_STRUCT_CREATE(ty) \
55
    IMPL_STRUCT_DESTROY(ty)
56
57
// supported structures for CustomData
58
IMPL_STRUCT(MVert)
59
IMPL_STRUCT(MEdge)
60
IMPL_STRUCT(MFace)
61
IMPL_STRUCT(MTFace)
62
IMPL_STRUCT(MTexPoly)
63
IMPL_STRUCT(MLoopUV)
64
IMPL_STRUCT(MLoopCol)
65
IMPL_STRUCT(MPoly)
66
IMPL_STRUCT(MLoop)
67
68
/**
69
        *   @brief  describes the size of data and the read function to be used for single CustomerData.type
70
        */
71
struct CustomDataTypeDescription {
72
    PRead Read; ///< function to read one CustomData type element
73
    PCreate Create; ///< function to allocate n type elements
74
    PDestroy Destroy;
75
76
    CustomDataTypeDescription(PRead read, PCreate create, PDestroy destroy) :
77
588
            Read(read), Create(create), Destroy(destroy) {}
78
};
79
80
/**
81
        *   @brief  helper macro to define Structure type specific CustomDataTypeDescription
82
        *   @note   IMPL_STRUCT_READ for same ty must be used earlier to implement the typespecific read function
83
        */
84
#define DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(ty) \
85
    CustomDataTypeDescription { &read##ty, &create##ty, &destroy##ty }
86
87
/**
88
        *   @brief  helper macro to define CustomDataTypeDescription for UNSUPPORTED type
89
        */
90
#define DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION \
91
    CustomDataTypeDescription { nullptr, nullptr, nullptr }
92
93
/**
94
        *   @brief  descriptors for data pointed to from CustomDataLayer.data
95
        *   @note   some of the CustomData uses already well defined Structures
96
        *           other (like CD_ORCO, ...) uses arrays of rawtypes or even arrays of Structures
97
        *           use a special readfunction for that cases
98
        */
99
static const std::array<CustomDataTypeDescription, CD_NUMTYPES> customDataTypeDescriptions = { {
100
        DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MVert),
101
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
102
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
103
        DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MEdge),
104
        DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MFace),
105
        DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MTFace),
106
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
107
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
108
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
109
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
110
111
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
112
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
113
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
114
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
115
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
116
        DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MTexPoly),
117
        DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoopUV),
118
        DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoopCol),
119
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
120
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
121
122
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
123
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
124
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
125
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
126
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
127
        DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MPoly),
128
        DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoop),
129
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
130
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
131
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
132
133
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
134
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
135
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
136
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
137
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
138
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
139
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
140
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
141
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
142
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
143
144
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
145
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION 
146
} };
147
148
151
bool isValidCustomDataType(const int cdtype) {
149
151
    return cdtype >= 0 && cdtype < CD_NUMTYPES;
150
151
}
151
152
151
bool readCustomData(std::shared_ptr<ElemBase> &out, const int cdtype, const size_t cnt, const FileDatabase &db) {
153
151
    if (!isValidCustomDataType(cdtype)) {
154
1
        throw Error("CustomData.type ", cdtype, " out of index");
155
1
    }
156
157
150
    const CustomDataTypeDescription cdtd = customDataTypeDescriptions[cdtype];
158
150
    if (cdtd.Read && cdtd.Create && cdtd.Destroy && cnt > 0) {
159
        // allocate cnt elements and parse them from file
160
148
        out.reset(cdtd.Create(cnt), cdtd.Destroy);
161
148
        return cdtd.Read(out.get(), cnt, db);
162
148
    }
163
2
    return false;
164
150
}
165
166
2
std::shared_ptr<CustomDataLayer> getCustomDataLayer(const CustomData &customdata, const CustomDataType cdtype, const std::string &name) {
167
3
    for (auto it = customdata.layers.begin(); it != customdata.layers.end(); ++it) {
168
3
        if (it->get()->type == cdtype && name == it->get()->name) {
169
2
            return *it;
170
2
        }
171
3
    }
172
0
    return nullptr;
173
2
}
174
175
2
const ElemBase *getCustomDataLayerData(const CustomData &customdata, const CustomDataType cdtype, const std::string &name) {
176
2
    const std::shared_ptr<CustomDataLayer> pLayer = getCustomDataLayer(customdata, cdtype, name);
177
2
    if (pLayer && pLayer->data) {
178
2
        return pLayer->data.get();
179
2
    }
180
0
    return nullptr;
181
2
}
182
} // namespace Blender
183
} // namespace Assimp