_ZN6Assimp19Discreet3DSImporterC2Ev:
  104|  5.13k|        mStream(nullptr), mLastNodeIndex(), mCurrentNode(), mRootNode(), mScene(), mMasterScale(), bHasBG(), bIsPrj() {
  105|       |    // empty
  106|  5.13k|}
_ZNK6Assimp19Discreet3DSImporter7GetInfoEv:
  117|  5.13k|const aiImporterDesc *Discreet3DSImporter::GetInfo() const {
  118|  5.13k|    return &desc;
  119|  5.13k|}

_ZN6Assimp19Discreet3DSImporterD2Ev:
   65|  5.13k|    ~Discreet3DSImporter() override = default;

_ZNK6Assimp12D3MFImporter7GetInfoEv:
  101|  5.13k|const aiImporterDesc *D3MFImporter::GetInfo() const {
  102|  5.13k|    return &desc;
  103|  5.13k|}

_ZN6Assimp12D3MFImporterC2Ev:
   59|  5.13k|    D3MFImporter() = default;

_ZN6Assimp12AC3DImporterC2Ev:
  161|  5.13k|        mBuffer(),
  162|       |        configSplitBFCull(),
  163|       |        configEvalSubdivision(),
  164|       |        mNumMeshes(),
  165|       |        mLights(),
  166|  5.13k|        mLightsCounter(0),
  167|  5.13k|        mGroupsCounter(0),
  168|  5.13k|        mPolysCounter(0),
  169|  5.13k|        mWorldsCounter(0) {
  170|       |    // nothing to be done here
  171|  5.13k|}
_ZNK6Assimp12AC3DImporter7GetInfoEv:
  182|  5.13k|const aiImporterDesc *AC3DImporter::GetInfo() const {
  183|  5.13k|    return &desc;
  184|  5.13k|}

_ZN6Assimp11AMFImporter5ClearEv:
   69|  5.13k|void AMFImporter::Clear() {
   70|  5.13k|    mNodeElement_Cur = nullptr;
   71|  5.13k|    mUnit.clear();
   72|  5.13k|    mMaterial_Converted.clear();
   73|  5.13k|    mTexture_Converted.clear();
   74|       |    // Delete all elements
   75|  5.13k|    if (!mNodeElement_List.empty()) {
  ------------------
  |  Branch (75:9): [True: 0, False: 5.13k]
  ------------------
   76|      0|        for (AMFNodeElementBase *ne : mNodeElement_List) {
  ------------------
  |  Branch (76:37): [True: 0, False: 0]
  ------------------
   77|      0|            delete ne;
   78|      0|        }
   79|       |
   80|      0|        mNodeElement_List.clear();
   81|      0|    }
   82|  5.13k|}
_ZN6Assimp11AMFImporterC2Ev:
   85|  5.13k|        mNodeElement_Cur(nullptr),
   86|  5.13k|        mXmlParser(nullptr) {
   87|       |    // empty
   88|  5.13k|}
_ZN6Assimp11AMFImporterD2Ev:
   90|  5.13k|AMFImporter::~AMFImporter() {
   91|  5.13k|    delete mXmlParser;
   92|       |    // Clear() is accounting if data already is deleted. So, just check again if all data is deleted.
   93|  5.13k|    Clear();
   94|  5.13k|}
_ZNK6Assimp11AMFImporter7GetInfoEv:
  487|  5.13k|const aiImporterDesc *AMFImporter::GetInfo() const {
  488|  5.13k|    return &Description;
  489|  5.13k|}

_ZN6Assimp11ASEImporterC2Ev:
   85|  5.13k|        mParser(), mBuffer(), pcScene(), configRecomputeNormals(), noSkeletonMesh() {
   86|       |    // empty
   87|  5.13k|}
_ZNK6Assimp11ASEImporter7GetInfoEv:
   98|  5.13k|const aiImporterDesc *ASEImporter::GetInfo() const {
   99|  5.13k|    return &desc;
  100|  5.13k|}

_ZNK6Assimp14AssbinImporter7GetInfoEv:
   82|  5.13k|const aiImporterDesc *AssbinImporter::GetInfo() const {
   83|  5.13k|    return &desc;
   84|  5.13k|}

_ZN6Assimp11B3DImporterD2Ev:
   91|  5.13k|B3DImporter::~B3DImporter() = default;
_ZNK6Assimp11B3DImporter7GetInfoEv:
  110|  5.13k|const aiImporterDesc *B3DImporter::GetInfo() const {
  111|  5.13k|    return &desc;
  112|  5.13k|}

_ZN6Assimp11B3DImporterC2Ev:
   66|  5.13k|    B3DImporter() = default;

_ZN6Assimp9BVHLoaderC2Ev:
   86|  5.13k|        noSkeletonMesh() {
   87|       |    // empty
   88|  5.13k|}
_ZNK6Assimp9BVHLoader7GetInfoEv:
  104|  5.13k|const aiImporterDesc *BVHLoader::GetInfo() const {
  105|  5.13k|    return &desc;
  106|  5.13k|}

_ZN6Assimp9BVHLoaderD2Ev:
   88|  5.13k|    ~BVHLoader() override = default;

_ZN6Assimp7Blender25CustomDataTypeDescriptionC2EPFbPNS0_8ElemBaseEmRKNS0_12FileDatabaseEEPFS3_mEPFvS3_E:
   77|     84|            Read(read), Create(create), Destroy(destroy) {}

_ZN6Assimp7Blender9TempArrayINSt3__16vectorENS0_15BlenderModifierEEC2Ev:
   67|  5.13k|        TempArray() = default;
_ZN6Assimp7Blender9TempArrayINSt3__16vectorENS0_15BlenderModifierEED2Ev:
   69|  5.13k|        ~TempArray () {
   70|  5.13k|            for(T* elem : arr) {
  ------------------
  |  Branch (70:25): [True: 0, False: 5.13k]
  ------------------
   71|      0|                delete elem;
   72|      0|            }
   73|  5.13k|        }

_ZN6Assimp15BlenderImporterC2Ev:
  101|  5.13k|        modifier_cache(new BlenderModifierShowcase()) {
  102|       |    // empty
  103|  5.13k|}
_ZN6Assimp15BlenderImporterD2Ev:
  107|  5.13k|BlenderImporter::~BlenderImporter() {
  108|  5.13k|    delete modifier_cache;
  109|  5.13k|}
_ZNK6Assimp15BlenderImporter7GetInfoEv:
  121|  5.13k|const aiImporterDesc *BlenderImporter::GetInfo() const {
  122|  5.13k|    return &blenderDesc;
  123|  5.13k|}

_ZNK6Assimp11COBImporter7GetInfoEv:
  102|  5.13k|const aiImporterDesc *COBImporter::GetInfo() const {
  103|  5.13k|    return &desc;
  104|  5.13k|}

_ZN6Assimp11COBImporterC2Ev:
   77|  5.13k|    COBImporter() = default;

_ZN6Assimp11CSMImporterC2Ev:
   76|  5.13k|CSMImporter::CSMImporter() : noSkeletonMesh() {
   77|       |    // empty
   78|  5.13k|}
_ZNK6Assimp11CSMImporter7GetInfoEv:
   89|  5.13k|const aiImporterDesc* CSMImporter::GetInfo () const {
   90|  5.13k|    return &desc;
   91|  5.13k|}

_ZN6Assimp13ColladaLoaderC2Ev:
  103|  5.13k|        noSkeletonMesh(false),
  104|  5.13k|        removeEmptyBones(false),
  105|  5.13k|        ignoreUpDirection(false),
  106|  5.13k|        ignoreUnitSize(false),
  107|  5.13k|        useColladaName(false),
  108|  5.13k|        mNodeNameCounter(0) {
  109|       |    // empty
  110|  5.13k|}
_ZNK6Assimp13ColladaLoader7GetInfoEv:
  136|  5.13k|const aiImporterDesc *ColladaLoader::GetInfo() const {
  137|  5.13k|    return &desc;
  138|  5.13k|}

_ZN6Assimp13ColladaLoaderD2Ev:
   91|  5.13k|    ~ColladaLoader() override = default;

_ZNK6Assimp11DXFImporter7GetInfoEv:
  363|  5.13k|const aiImporterDesc* DXFImporter::GetInfo () const {
  364|  5.13k|    return &desc;
  365|  5.13k|}

_ZN6Assimp11DXFImporterC2Ev:
   71|  5.13k|    DXFImporter() = default;

_ZN6Assimp3FBX14ImportSettingsC2Ev:
   54|  5.13k|            strictMode(true),
   55|  5.13k|            readAllLayers(true),
   56|  5.13k|            readAllMaterials(false),
   57|  5.13k|            readMaterials(true),
   58|  5.13k|            readTextures(true),
   59|  5.13k|            readCameras(true),
   60|  5.13k|            readLights(true),
   61|  5.13k|            readAnimations(true),
   62|  5.13k|            readWeights(true),
   63|  5.13k|            useSkeleton(false),
   64|  5.13k|            preservePivots(true),
   65|  5.13k|            optimizeEmptyAnimationCurves(true),
   66|  5.13k|            useLegacyEmbeddedTextureNaming(false),
   67|  5.13k|            removeEmptyBones(true),
   68|  5.13k|            convertToMeters(false) {
   69|       |        // empty
   70|  5.13k|    }

_ZNK6Assimp11FBXImporter7GetInfoEv:
   99|  5.13k|const aiImporterDesc *FBXImporter::GetInfo() const {
  100|  5.13k|	return &desc;
  101|  5.13k|}

_ZN6Assimp11FBXImporterC2Ev:
   73|  5.13k|    FBXImporter() = default;

_ZN6Assimp11HMPImporterC2Ev:
   75|  5.13k|HMPImporter::HMPImporter() = default;
_ZN6Assimp11HMPImporterD2Ev:
   79|  5.13k|HMPImporter::~HMPImporter() = default;
_ZNK6Assimp11HMPImporter7GetInfoEv:
   94|  5.13k|const aiImporterDesc *HMPImporter::GetInfo() const {
   95|  5.13k|    return &desc;
   96|  5.13k|}

_ZNK6Assimp11IFCImporter7GetInfoEv:
  131|  5.13k|const aiImporterDesc *IFCImporter::GetInfo() const {
  132|  5.13k|    return &desc;
  133|  5.13k|}

_ZN6Assimp11IFCImporterC2Ev:
   89|  5.13k|    IFCImporter() = default;
_ZN6Assimp11IFCImporter8SettingsC2Ev:
   80|  5.13k|                skipSpaceRepresentations(), useCustomTriangulation(), skipAnnotations(), conicSamplingAngle(10.f), cylindricalTessellation(32) {}

_ZN6Assimp11IQMImporterC2Ev:
   87|  5.13k|        mScene(nullptr) {
   88|       |    // empty
   89|  5.13k|}
_ZNK6Assimp11IQMImporter7GetInfoEv:
  113|  5.13k|const aiImporterDesc *IQMImporter::GetInfo() const {
  114|  5.13k|    return &desc;
  115|  5.13k|}

_ZN6Assimp11IRRImporterC2Ev:
   85|  5.13k|        fps(), configSpeedFlag() {
   86|       |    // empty
   87|  5.13k|}
_ZN6Assimp11IRRImporterD2Ev:
   91|  5.13k|IRRImporter::~IRRImporter() = default;
_ZNK6Assimp11IRRImporter7GetInfoEv:
  101|  5.13k|const aiImporterDesc *IRRImporter::GetInfo() const {
  102|  5.13k|    return &desc;
  103|  5.13k|}

_ZNK6Assimp15IRRMeshImporter7GetInfoEv:
   86|  5.13k|const aiImporterDesc *IRRMeshImporter::GetInfo() const {
   87|  5.13k|    return &desc;
   88|  5.13k|}

_ZN6Assimp15IRRMeshImporterC2Ev:
   66|  5.13k|    IRRMeshImporter() = default;
_ZN6Assimp15IRRMeshImporterD2Ev:
   69|  5.13k|    ~IRRMeshImporter() override = default;

_ZN6Assimp12IrrlichtBaseC2Ev:
   61|  10.2k|    IrrlichtBase() {
   62|       |        // empty
   63|  10.2k|    }
_ZN6Assimp12IrrlichtBaseD2Ev:
   65|  10.2k|    ~IrrlichtBase() = default;

_ZNK6Assimp11LWOImporter7GetInfoEv:
  101|  5.13k|const aiImporterDesc *LWOImporter::GetInfo() const {
  102|  5.13k|    return &desc;
  103|  5.13k|}

_ZN6Assimp11LWOImporterC2Ev:
   77|  5.13k|    LWOImporter() = default;
_ZN6Assimp11LWOImporterD2Ev:
   82|  5.13k|    ~LWOImporter() override = default;

_ZN6Assimp11LWSImporterC2Ev:
  145|  5.13k|        noSkeletonMesh() {
  146|       |    // nothing to do here
  147|  5.13k|}
_ZNK6Assimp11LWSImporter7GetInfoEv:
  161|  5.13k|const aiImporterDesc *LWSImporter::GetInfo() const {
  162|  5.13k|    return &desc;
  163|  5.13k|}

_ZN6Assimp11MD2ImporterC2Ev:
   98|  5.13k|{}
_ZNK6Assimp11MD2Importer7GetInfoEv:
  111|  5.13k|{
  112|  5.13k|    return &desc;
  113|  5.13k|}

_ZN6Assimp11MD3ImporterC2Ev:
  344|  5.13k|        configFrameID(0), configHandleMP(true), configSpeedFlag(), pcHeader(), mBuffer(), fileSize(), mScene(), mIOHandler() {}
_ZN6Assimp11MD3ImporterD2Ev:
  348|  5.13k|MD3Importer::~MD3Importer() = default;
_ZNK6Assimp11MD3Importer7GetInfoEv:
  431|  5.13k|const aiImporterDesc *MD3Importer::GetInfo() const {
  432|  5.13k|    return &desc;
  433|  5.13k|}

_ZN6Assimp11MD5ImporterC2Ev:
   83|  5.13k|        mIOHandler(nullptr),
   84|       |        mBuffer(),
   85|       |        mFileSize(),
   86|       |        mLineNumber(),
   87|       |        mScene(),
   88|       |        mHadMD5Mesh(),
   89|       |        mHadMD5Anim(),
   90|       |        mHadMD5Camera(),
   91|  5.13k|        mCconfigNoAutoLoad(false) {
   92|       |    // empty
   93|  5.13k|}
_ZNK6Assimp11MD5Importer7GetInfoEv:
  104|  5.13k|const aiImporterDesc *MD5Importer::GetInfo() const {
  105|  5.13k|    return &desc;
  106|  5.13k|}

_ZN6Assimp11MD5ImporterD2Ev:
   68|  5.13k|    ~MD5Importer() override = default;

_ZN6Assimp11MDCImporterC2Ev:
  102|  5.13k|        fileSize() {
  103|       |    // empty
  104|  5.13k|}
_ZNK6Assimp11MDCImporter7GetInfoEv:
  114|  5.13k|const aiImporterDesc *MDCImporter::GetInfo() const {
  115|  5.13k|    return &desc;
  116|  5.13k|}

_ZN6Assimp3MDL8HalfLife17HL1ImportSettingsC2Ev:
   57|  10.2k|        read_animations(false),
   58|  10.2k|        read_animation_events(false),
   59|  10.2k|        read_blend_controllers(false),
   60|  10.2k|        read_sequence_groups_info(false),
   61|  10.2k|        read_sequence_transitions(false),
   62|  10.2k|        read_attachments(false),
   63|  10.2k|        read_bone_controllers(false),
   64|  10.2k|        read_hitboxes(false),
   65|  10.2k|        read_textures(false),
   66|  10.2k|        read_misc_global_info(false),
   67|  10.2k|        transform_coord_system(true) {
   68|  10.2k|    }

_ZN6Assimp11MDLImporterC2Ev:
   96|  10.2k|        configFrameID(), mBuffer(), iGSFileVersion(), mIOHandler(nullptr), pScene(), iFileSize() {
   97|       |    // empty
   98|  10.2k|}
_ZNK6Assimp11MDLImporter7GetInfoEv:
  147|  5.13k|const aiImporterDesc *MDLImporter::GetInfo() const {
  148|  5.13k|    return &desc;
  149|  5.13k|}

_ZN6Assimp11MDLImporterD2Ev:
   87|  10.2k|    ~MDLImporter() override = default;

_ZN6Assimp11MMDImporterC2Ev:
   78|  5.13k|        m_Buffer(),
   79|  5.13k|        m_strAbsPath() {
   80|  5.13k|    DefaultIOSystem io;
   81|  5.13k|    m_strAbsPath = io.getOsSeparator();
   82|  5.13k|}
_ZNK6Assimp11MMDImporter7GetInfoEv:
   93|  5.13k|const aiImporterDesc *MMDImporter::GetInfo() const {
   94|  5.13k|    return &desc;
   95|  5.13k|}

_ZN6Assimp11MMDImporterD2Ev:
   62|  5.13k|    ~MMDImporter() override = default;

_ZN6Assimp12MS3DImporterC2Ev:
   81|  5.13k|{}
_ZNK6Assimp12MS3DImporter7GetInfoEv:
   93|  5.13k|{
   94|  5.13k|    return &desc;
   95|  5.13k|}

_ZNK6Assimp11NDOImporter7GetInfoEv:
   83|  5.13k|{
   84|  5.13k|    return &desc;
   85|  5.13k|}

_ZN6Assimp11NDOImporterC2Ev:
   68|  5.13k|    NDOImporter() = default;

_ZNK6Assimp11NFFImporter7GetInfoEv:
   82|  5.13k|const aiImporterDesc *NFFImporter::GetInfo() const {
   83|  5.13k|    return &desc;
   84|  5.13k|}

_ZN6Assimp11NFFImporterC2Ev:
   65|  5.13k|    NFFImporter() = default;

_ZNK6Assimp11OFFImporter7GetInfoEv:
   81|  5.13k|const aiImporterDesc *OFFImporter::GetInfo() const {
   82|  5.13k|    return &desc;
   83|  5.13k|}

_ZN6Assimp11OFFImporterC2Ev:
   60|  5.13k|    OFFImporter() = default;

_ZN6Assimp15ObjFileImporterC2Ev:
   79|  5.13k|        m_Buffer(),
   80|  5.13k|        m_pRootObject(nullptr),
   81|  5.13k|        m_strAbsPath(std::string(1, DefaultIOSystem().getOsSeparator())) {
   82|       |    // empty
   83|  5.13k|}
_ZN6Assimp15ObjFileImporterD2Ev:
   87|  5.13k|ObjFileImporter::~ObjFileImporter() {
   88|  5.13k|    delete m_pRootObject;
   89|  5.13k|}
_ZNK6Assimp15ObjFileImporter7GetInfoEv:
   99|  5.13k|const aiImporterDesc *ObjFileImporter::GetInfo() const {
  100|  5.13k|    return &desc;
  101|  5.13k|}

_ZNK6Assimp4Ogre12OgreImporter7GetInfoEv:
   67|  5.13k|const aiImporterDesc *OgreImporter::GetInfo() const {
   68|  5.13k|    return &desc;
   69|  5.13k|}

_ZN6Assimp7OpenGEX15OpenGEXImporter15VertexContainerC2Ev:
  239|  5.13k|        m_numColors(0), m_colors(nullptr), m_numUVComps(), m_textureCoords() {
  ------------------
  |  |   59|  5.13k|#define nullptr nullptr
  ------------------
  240|       |    // empty
  241|  5.13k|}
_ZN6Assimp7OpenGEX15OpenGEXImporter15VertexContainerD2Ev:
  244|  5.13k|OpenGEXImporter::VertexContainer::~VertexContainer() {
  245|  5.13k|    delete[] m_colors;
  246|       |
  247|  41.0k|    for (auto &texcoords : m_textureCoords) {
  ------------------
  |  Branch (247:26): [True: 41.0k, False: 5.13k]
  ------------------
  248|  41.0k|        delete[] texcoords;
  249|  41.0k|    }
  250|  5.13k|}
_ZN6Assimp7OpenGEX15OpenGEXImporterC2Ev:
  262|  5.13k|        m_root(nullptr),
  ------------------
  |  |   59|  5.13k|#define nullptr nullptr
  ------------------
  263|  5.13k|        m_nodeChildMap(),
  264|  5.13k|        m_mesh2refMap(),
  265|  5.13k|        m_material2refMap(),
  266|  5.13k|        m_ctx(nullptr),
  ------------------
  |  |   59|  5.13k|#define nullptr nullptr
  ------------------
  267|  5.13k|        m_metrics(),
  268|  5.13k|        m_currentNode(nullptr),
  ------------------
  |  |   59|  5.13k|#define nullptr nullptr
  ------------------
  269|  5.13k|        m_currentVertices(),
  270|  5.13k|        m_currentMesh(nullptr),
  ------------------
  |  |   59|  5.13k|#define nullptr nullptr
  ------------------
  271|  5.13k|        m_currentMaterial(nullptr),
  ------------------
  |  |   59|  5.13k|#define nullptr nullptr
  ------------------
  272|  5.13k|        m_currentLight(nullptr),
  ------------------
  |  |   59|  5.13k|#define nullptr nullptr
  ------------------
  273|  5.13k|        m_currentCamera(nullptr),
  ------------------
  |  |   59|  5.13k|#define nullptr nullptr
  ------------------
  274|  5.13k|        m_tokenType(Grammar::NoneType),
  275|  5.13k|        m_materialCache(),
  276|  5.13k|        m_cameraCache(),
  277|  5.13k|        m_lightCache(),
  278|  5.13k|        m_nodeStack(),
  279|  5.13k|        m_unresolvedRefStack() {
  280|       |    // empty
  281|  5.13k|}
_ZNK6Assimp7OpenGEX15OpenGEXImporter7GetInfoEv:
  321|  5.13k|const aiImporterDesc *OpenGEXImporter::GetInfo() const {
  322|  5.13k|    return &desc;
  323|  5.13k|}

_ZN6Assimp7OpenGEX10MetricInfoC2Ev:
   81|  20.5k|    MetricInfo(): m_stringValue( ), m_floatValue( 0.0f ), m_intValue( -1 ) {}
_ZN6Assimp7OpenGEX15OpenGEXImporterD2Ev:
   94|  5.13k|    ~OpenGEXImporter() override = default;

_ZN6Assimp11PLYImporterD2Ev:
  172|  5.13k|    PLYImporter::~PLYImporter() {
  173|  5.13k|        delete mGeneratedMesh;
  174|  5.13k|    }
_ZNK6Assimp11PLYImporter7GetInfoEv:
  184|  5.13k|    const aiImporterDesc *PLYImporter::GetInfo() const {
  185|  5.13k|        return &desc;
  186|  5.13k|    }

_ZN6Assimp11PLYImporterC2Ev:
   68|  5.13k|    PLYImporter() = default;

_ZN6Assimp17Q3BSPFileImporterC2Ev:
  137|  5.13k|        m_pCurrentMesh(nullptr), m_pCurrentFace(nullptr) {
  138|       |    // empty
  139|  5.13k|}
_ZN6Assimp17Q3BSPFileImporterD2Ev:
  143|  5.13k|Q3BSPFileImporter::~Q3BSPFileImporter() {
  144|  5.13k|    clear();
  145|  5.13k|}
_ZN6Assimp17Q3BSPFileImporter5clearEv:
  148|  5.13k|void Q3BSPFileImporter::clear() {
  149|  5.13k|    for (FaceMap::iterator it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end(); ++it) {
  ------------------
  |  Branch (149:62): [True: 0, False: 5.13k]
  ------------------
  150|      0|        const std::string &matName = it->first;
  151|      0|        if (!matName.empty()) {
  ------------------
  |  Branch (151:13): [True: 0, False: 0]
  ------------------
  152|      0|            delete it->second;
  153|      0|        }
  154|      0|    }
  155|  5.13k|}
_ZNK6Assimp17Q3BSPFileImporter7GetInfoEv:
  168|  5.13k|const aiImporterDesc *Q3BSPFileImporter::GetInfo() const {
  169|  5.13k|    return &desc;
  170|  5.13k|}

_ZN6Assimp11Q3DImporterC2Ev:
   77|  5.13k|Q3DImporter::Q3DImporter() = default;
_ZN6Assimp11Q3DImporterD2Ev:
   81|  5.13k|Q3DImporter::~Q3DImporter() = default;
_ZNK6Assimp11Q3DImporter7GetInfoEv:
   91|  5.13k|const aiImporterDesc *Q3DImporter::GetInfo() const {
   92|  5.13k|    return &desc;
   93|  5.13k|}

_ZNK6Assimp11RAWImporter7GetInfoEv:
   80|  5.13k|const aiImporterDesc *RAWImporter::GetInfo() const {
   81|  5.13k|    return &desc;
   82|  5.13k|}

_ZN6Assimp11RAWImporterC2Ev:
   60|  5.13k|    RAWImporter() = default;

_ZNK6Assimp11SIBImporter7GetInfoEv:
  206|  5.13k|const aiImporterDesc *SIBImporter::GetInfo() const {
  207|  5.13k|    return &desc;
  208|  5.13k|}

_ZN6Assimp11SIBImporterC2Ev:
   60|  5.13k|    SIBImporter() = default;

_ZN6Assimp11SMDImporterC2Ev:
   86|  5.13k|        mBuffer(),
   87|  5.13k|        mEnd(nullptr),
   88|  5.13k|        pScene(nullptr),
   89|  5.13k|        iFileSize( 0 ),
   90|  5.13k|        iSmallestFrame( INT_MAX ),
   91|  5.13k|        dLengthOfAnim( 0.0 ),
   92|  5.13k|        bHasUVs(false ),
   93|  5.13k|        iLineNumber((unsigned int)-1)  {
   94|       |    // empty
   95|  5.13k|}
_ZNK6Assimp11SMDImporter7GetInfoEv:
  106|  5.13k|const aiImporterDesc* SMDImporter::GetInfo () const {
  107|  5.13k|    return &desc;
  108|  5.13k|}

_ZN6Assimp11SMDImporterD2Ev:
  165|  5.13k|    ~SMDImporter() override = default;

_ZN6Assimp11STLImporterC2Ev:
  130|  5.13k|        mFileSize(0),
  131|  5.13k|        mScene() {
  132|       |    // empty
  133|  5.13k|}
_ZN6Assimp11STLImporterD2Ev:
  137|  5.13k|STLImporter::~STLImporter() = default;
_ZNK6Assimp11STLImporter7GetInfoEv:
  147|  5.13k|const aiImporterDesc *STLImporter::GetInfo() const {
  148|  5.13k|    return &desc;
  149|  5.13k|}

_ZN6Assimp4STEP7EXPRESS16ConversionSchema11SchemaEntryC2EPKcPFPNS0_6ObjectERKNS0_2DBERKNS1_4LISTEE:
  321|  1.96k|        SchemaEntry(const char *name, ConvertObjectProc func) : mName(name), mFunc(func) {}

_ZN6Assimp16TerragenImporterC2Ev:
   72|  5.13k|        configComputeUVs(false) {
   73|       |    // empty
   74|  5.13k|}
_ZNK6Assimp16TerragenImporter7GetInfoEv:
   85|  5.13k|const aiImporterDesc *TerragenImporter::GetInfo() const {
   86|  5.13k|    return &desc;
   87|  5.13k|}

_ZN6Assimp14UnrealImporterC2Ev:
  166|  5.13k|        mConfigFrameID(0), mConfigHandleFlags(true) {
  167|       |    // empty
  168|  5.13k|}
_ZNK6Assimp14UnrealImporter7GetInfoEv:
  178|  5.13k|const aiImporterDesc *UnrealImporter::GetInfo() const {
  179|  5.13k|    return &desc;
  180|  5.13k|}

_ZNK6Assimp13XFileImporter7GetInfoEv:
   86|  5.13k|const aiImporterDesc *XFileImporter::GetInfo() const {
   87|  5.13k|    return &desc;
   88|  5.13k|}

_ZN6Assimp13XFileImporterC2Ev:
   71|  5.13k|    XFileImporter() = default;
_ZN6Assimp13XFileImporterD2Ev:
   72|  5.13k|    ~XFileImporter() override = default;

_ZN6Assimp11X3DImporterC2Ev:
  192|  5.13k|        mNodeElementCur(nullptr),
  193|  5.13k|        mScene(nullptr),
  194|  5.13k|        mpIOHandler(nullptr) {
  195|       |    // empty
  196|  5.13k|}
_ZN6Assimp11X3DImporterD2Ev:
  198|  5.13k|X3DImporter::~X3DImporter() {
  199|       |    // Clear() is accounting if data already is deleted. So, just check again if all data is deleted.
  200|  5.13k|    Clear();
  201|  5.13k|}
_ZN6Assimp11X3DImporter5ClearEv:
  203|  5.13k|void X3DImporter::Clear() {
  204|  5.13k|    mNodeElementCur = nullptr;
  205|       |    // Delete all elements
  206|  5.13k|    if (!NodeElement_List.empty()) {
  ------------------
  |  Branch (206:9): [True: 0, False: 5.13k]
  ------------------
  207|      0|        for (std::list<X3DNodeElementBase *>::iterator it = NodeElement_List.begin(); it != NodeElement_List.end(); ++it) {
  ------------------
  |  Branch (207:87): [True: 0, False: 0]
  ------------------
  208|      0|            delete *it;
  209|      0|        }
  210|      0|        NodeElement_List.clear();
  211|      0|    }
  212|  5.13k|}
_ZNK6Assimp11X3DImporter7GetInfoEv:
  340|  5.13k|const aiImporterDesc *X3DImporter::GetInfo() const {
  341|  5.13k|    return &Description;
  342|  5.13k|}

_ZN6Assimp11XGLImporterC2Ev:
   75|  5.13k|XGLImporter::XGLImporter() : mXmlParser(nullptr), m_scene(nullptr) {
   76|       |    // empty
   77|  5.13k|}
_ZN6Assimp11XGLImporterD2Ev:
   80|  5.13k|XGLImporter::~XGLImporter() {
   81|  5.13k|    clear();
   82|  5.13k|}
_ZNK6Assimp11XGLImporter7GetInfoEv:
   91|  5.13k|const aiImporterDesc *XGLImporter::GetInfo() const {
   92|  5.13k|	return &desc;
   93|  5.13k|}
_ZN6Assimp11XGLImporter5clearEv:
  170|  5.13k|void XGLImporter::clear() {
  171|  5.13k|    delete mXmlParser;
  172|  5.13k|    mXmlParser = nullptr;
  173|  5.13k|}

_ZN4glTF6ObjectD2Ev:
  312|  5.32k|    virtual ~Object() = default;
_ZN4glTF5AssetC2EPN6Assimp8IOSystemE:
  966|  6.73k|            mIOSystem(io),
  967|  6.73k|            asset(),
  968|  6.73k|            accessors(*this, "accessors"),
  969|  6.73k|            animations(*this, "animations"),
  970|  6.73k|            buffers(*this, "buffers"),
  971|  6.73k|            bufferViews(*this, "bufferViews"),
  972|  6.73k|            cameras(*this, "cameras"),
  973|  6.73k|            images(*this, "images"),
  974|  6.73k|            materials(*this, "materials"),
  975|  6.73k|            meshes(*this, "meshes"),
  976|  6.73k|            nodes(*this, "nodes"),
  977|  6.73k|            samplers(*this, "samplers"),
  978|  6.73k|            scenes(*this, "scenes"),
  979|  6.73k|            skins(*this, "skins"),
  980|  6.73k|            textures(*this, "textures"),
  981|  6.73k|            lights(*this, "lights", "KHR_materials_common") {
  982|  6.73k|        memset(&extensionsUsed, 0, sizeof(extensionsUsed));
  983|  6.73k|    }
_ZN4glTF13AssetMetadataC2Ev:
  898|  6.73k|            premultipliedAlpha(false) {
  899|  6.73k|    }
_ZN4glTF12LazyDictBaseD2Ev:
  825|  94.2k|    virtual ~LazyDictBase() = default;
_ZN4glTF6ObjectC2Ev:
  311|  6.68k|    Object() = default;
_ZN4glTF6Buffer13MarkAsSpecialEv:
  484|  1.96k|    void MarkAsSpecial() { mIsSpecial = true; }
_ZN4glTF6Object11TranslateIdERNS_5AssetEPKc:
  315|  5.75k|    static const char *TranslateId(Asset & /*r*/, const char *id) { return id; }
_ZN4glTF5SceneC2Ev:
  724|    538|    Scene() = default;
_ZN4glTF4NodeC2Ev:
  701|  1.56k|    Node() = default;
_ZN4glTF4MeshC2Ev:
  661|    920|    Mesh() = default;
_ZN4glTF4MeshD2Ev:
  664|    698|    ~Mesh() {
  665|    698|        for (std::list<SExtension *>::iterator it = Extension.begin(), it_end = Extension.end(); it != it_end; it++) {
  ------------------
  |  Branch (665:98): [True: 0, False: 698]
  ------------------
  666|      0|            delete *it;
  667|      0|        };
  668|    698|    }
_ZN4glTF8AccessorC2Ev:
  380|    812|    Accessor() = default;
_ZN4glTF10AttribType10FromStringEPKc:
  261|    730|    inline static Value FromString(const char *str) {
  262|  1.83k|        for (size_t i = 0; i < NUM_VALUES; ++i) {
  ------------------
  |  Branch (262:28): [True: 1.80k, False: 28]
  ------------------
  263|  1.80k|            if (strcmp(data<0>::infos[i].name, str) == 0) {
  ------------------
  |  Branch (263:17): [True: 702, False: 1.10k]
  ------------------
  264|    702|                return static_cast<Value>(i);
  265|    702|            }
  266|  1.80k|        }
  267|     28|        return SCALAR;
  268|    730|    }
_ZN4glTF8MaterialC2Ev:
  586|    112|    Material() { SetDefaults(); }
_ZN4glTF7TextureC2Ev:
  762|     80|    Texture() = default;
_ZN4glTF7SamplerC2Ev:
  716|     18|    Sampler() = default;
_ZNK4glTF13AssetMetadatacvbEv:
  901|  5.99k|    operator bool() const { return version.size() && version[0] == '1'; }
  ------------------
  |  Branch (901:36): [True: 5.67k, False: 320]
  |  Branch (901:54): [True: 1.48k, False: 4.19k]
  ------------------
_ZNK4glTF8LazyDictINS_8MaterialEE4SizeEv:
  878|    331|    inline unsigned int Size() const { return unsigned(mObjs.size()); }
_ZN4glTF8LazyDictINS_8MaterialEEixEm:
  880|      8|    inline T &operator[](size_t i) { return *mObjs[i]; }
_ZNK4glTF8LazyDictINS_4MeshEE4SizeEv:
  878|    367|    inline unsigned int Size() const { return unsigned(mObjs.size()); }
_ZN4glTF8LazyDictINS_4MeshEEixEm:
  880|     36|    inline T &operator[](size_t i) { return *mObjs[i]; }
_ZNK4glTF8LazyDictINS_6CameraEE4SizeEv:
  878|    331|    inline unsigned int Size() const { return unsigned(mObjs.size()); }
_ZNK4glTF8LazyDictINS_5LightEE4SizeEv:
  878|    331|    inline unsigned int Size() const { return unsigned(mObjs.size()); }
_ZNK4glTF8LazyDictINS_5ImageEE4SizeEv:
  878|    662|    inline unsigned int Size() const { return unsigned(mObjs.size()); }

_ZN4glTF6BufferD2Ev:
  166|  2.13k|inline Buffer::~Buffer() {
  167|  2.13k|    for (SEncodedRegion *reg : EncodedRegion_List)
  ------------------
  |  Branch (167:30): [True: 0, False: 2.13k]
  ------------------
  168|      0|        delete reg;
  169|  2.13k|}
_ZN4glTF8LazyDictINS_8AccessorEEC2ERNS_5AssetEPKcS6_:
   71|  6.73k|        mDictId(dictId), mExtId(extId), mDict(nullptr), mAsset(asset) {
   72|  6.73k|    asset.mDicts.push_back(this); // register to the list of dictionaries
   73|  6.73k|}
_ZN4glTF8LazyDictINS_8AccessorEE16AttachToDocumentERN9rapidjson15GenericDocumentINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEES8_EE:
   83|  1.15k|inline void LazyDict<T>::AttachToDocument(Document &doc) {
   84|  1.15k|    Value *container = nullptr;
   85|       |
   86|  1.15k|    if (mExtId) {
  ------------------
  |  Branch (86:9): [True: 0, False: 1.15k]
  ------------------
   87|      0|        if (Value *exts = FindObject(doc, "extensions")) {
  ------------------
  |  Branch (87:20): [True: 0, False: 0]
  ------------------
   88|      0|            container = FindObject(*exts, mExtId);
   89|      0|        }
   90|  1.15k|    } else {
   91|  1.15k|        container = &doc;
   92|  1.15k|    }
   93|       |
   94|  1.15k|    if (container) {
  ------------------
  |  Branch (94:9): [True: 1.15k, False: 0]
  ------------------
   95|  1.15k|        mDict = FindObject(*container, mDictId);
   96|  1.15k|    }
   97|  1.15k|}
_ZN4glTF8LazyDictINS_8AccessorEE18DetachFromDocumentEv:
  100|    662|inline void LazyDict<T>::DetachFromDocument() {
  101|    662|    mDict = nullptr;
  102|    662|}
_ZN4glTF8LazyDictINS_9AnimationEEC2ERNS_5AssetEPKcS6_:
   71|  6.73k|        mDictId(dictId), mExtId(extId), mDict(nullptr), mAsset(asset) {
   72|  6.73k|    asset.mDicts.push_back(this); // register to the list of dictionaries
   73|  6.73k|}
_ZN4glTF8LazyDictINS_9AnimationEE16AttachToDocumentERN9rapidjson15GenericDocumentINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEES8_EE:
   83|  1.15k|inline void LazyDict<T>::AttachToDocument(Document &doc) {
   84|  1.15k|    Value *container = nullptr;
   85|       |
   86|  1.15k|    if (mExtId) {
  ------------------
  |  Branch (86:9): [True: 0, False: 1.15k]
  ------------------
   87|      0|        if (Value *exts = FindObject(doc, "extensions")) {
  ------------------
  |  Branch (87:20): [True: 0, False: 0]
  ------------------
   88|      0|            container = FindObject(*exts, mExtId);
   89|      0|        }
   90|  1.15k|    } else {
   91|  1.15k|        container = &doc;
   92|  1.15k|    }
   93|       |
   94|  1.15k|    if (container) {
  ------------------
  |  Branch (94:9): [True: 1.15k, False: 0]
  ------------------
   95|  1.15k|        mDict = FindObject(*container, mDictId);
   96|  1.15k|    }
   97|  1.15k|}
_ZN4glTF8LazyDictINS_9AnimationEE18DetachFromDocumentEv:
  100|    662|inline void LazyDict<T>::DetachFromDocument() {
  101|    662|    mDict = nullptr;
  102|    662|}
_ZN4glTF8LazyDictINS_6BufferEEC2ERNS_5AssetEPKcS6_:
   71|  6.73k|        mDictId(dictId), mExtId(extId), mDict(nullptr), mAsset(asset) {
   72|  6.73k|    asset.mDicts.push_back(this); // register to the list of dictionaries
   73|  6.73k|}
_ZN4glTF8LazyDictINS_6BufferEE16AttachToDocumentERN9rapidjson15GenericDocumentINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEES8_EE:
   83|  1.15k|inline void LazyDict<T>::AttachToDocument(Document &doc) {
   84|  1.15k|    Value *container = nullptr;
   85|       |
   86|  1.15k|    if (mExtId) {
  ------------------
  |  Branch (86:9): [True: 0, False: 1.15k]
  ------------------
   87|      0|        if (Value *exts = FindObject(doc, "extensions")) {
  ------------------
  |  Branch (87:20): [True: 0, False: 0]
  ------------------
   88|      0|            container = FindObject(*exts, mExtId);
   89|      0|        }
   90|  1.15k|    } else {
   91|  1.15k|        container = &doc;
   92|  1.15k|    }
   93|       |
   94|  1.15k|    if (container) {
  ------------------
  |  Branch (94:9): [True: 1.15k, False: 0]
  ------------------
   95|  1.15k|        mDict = FindObject(*container, mDictId);
   96|  1.15k|    }
   97|  1.15k|}
_ZN4glTF8LazyDictINS_6BufferEE18DetachFromDocumentEv:
  100|    662|inline void LazyDict<T>::DetachFromDocument() {
  101|    662|    mDict = nullptr;
  102|    662|}
_ZN4glTF8LazyDictINS_10BufferViewEEC2ERNS_5AssetEPKcS6_:
   71|  6.73k|        mDictId(dictId), mExtId(extId), mDict(nullptr), mAsset(asset) {
   72|  6.73k|    asset.mDicts.push_back(this); // register to the list of dictionaries
   73|  6.73k|}
_ZN4glTF8LazyDictINS_10BufferViewEE16AttachToDocumentERN9rapidjson15GenericDocumentINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEES8_EE:
   83|  1.15k|inline void LazyDict<T>::AttachToDocument(Document &doc) {
   84|  1.15k|    Value *container = nullptr;
   85|       |
   86|  1.15k|    if (mExtId) {
  ------------------
  |  Branch (86:9): [True: 0, False: 1.15k]
  ------------------
   87|      0|        if (Value *exts = FindObject(doc, "extensions")) {
  ------------------
  |  Branch (87:20): [True: 0, False: 0]
  ------------------
   88|      0|            container = FindObject(*exts, mExtId);
   89|      0|        }
   90|  1.15k|    } else {
   91|  1.15k|        container = &doc;
   92|  1.15k|    }
   93|       |
   94|  1.15k|    if (container) {
  ------------------
  |  Branch (94:9): [True: 1.15k, False: 0]
  ------------------
   95|  1.15k|        mDict = FindObject(*container, mDictId);
   96|  1.15k|    }
   97|  1.15k|}
_ZN4glTF8LazyDictINS_10BufferViewEE18DetachFromDocumentEv:
  100|    662|inline void LazyDict<T>::DetachFromDocument() {
  101|    662|    mDict = nullptr;
  102|    662|}
_ZN4glTF8LazyDictINS_6CameraEEC2ERNS_5AssetEPKcS6_:
   71|  6.73k|        mDictId(dictId), mExtId(extId), mDict(nullptr), mAsset(asset) {
   72|  6.73k|    asset.mDicts.push_back(this); // register to the list of dictionaries
   73|  6.73k|}
_ZN4glTF8LazyDictINS_6CameraEE16AttachToDocumentERN9rapidjson15GenericDocumentINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEES8_EE:
   83|  1.15k|inline void LazyDict<T>::AttachToDocument(Document &doc) {
   84|  1.15k|    Value *container = nullptr;
   85|       |
   86|  1.15k|    if (mExtId) {
  ------------------
  |  Branch (86:9): [True: 0, False: 1.15k]
  ------------------
   87|      0|        if (Value *exts = FindObject(doc, "extensions")) {
  ------------------
  |  Branch (87:20): [True: 0, False: 0]
  ------------------
   88|      0|            container = FindObject(*exts, mExtId);
   89|      0|        }
   90|  1.15k|    } else {
   91|  1.15k|        container = &doc;
   92|  1.15k|    }
   93|       |
   94|  1.15k|    if (container) {
  ------------------
  |  Branch (94:9): [True: 1.15k, False: 0]
  ------------------
   95|  1.15k|        mDict = FindObject(*container, mDictId);
   96|  1.15k|    }
   97|  1.15k|}
_ZN4glTF8LazyDictINS_6CameraEE18DetachFromDocumentEv:
  100|    662|inline void LazyDict<T>::DetachFromDocument() {
  101|    662|    mDict = nullptr;
  102|    662|}
_ZN4glTF8LazyDictINS_5ImageEEC2ERNS_5AssetEPKcS6_:
   71|  6.73k|        mDictId(dictId), mExtId(extId), mDict(nullptr), mAsset(asset) {
   72|  6.73k|    asset.mDicts.push_back(this); // register to the list of dictionaries
   73|  6.73k|}
_ZN4glTF8LazyDictINS_5ImageEE16AttachToDocumentERN9rapidjson15GenericDocumentINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEES8_EE:
   83|  1.15k|inline void LazyDict<T>::AttachToDocument(Document &doc) {
   84|  1.15k|    Value *container = nullptr;
   85|       |
   86|  1.15k|    if (mExtId) {
  ------------------
  |  Branch (86:9): [True: 0, False: 1.15k]
  ------------------
   87|      0|        if (Value *exts = FindObject(doc, "extensions")) {
  ------------------
  |  Branch (87:20): [True: 0, False: 0]
  ------------------
   88|      0|            container = FindObject(*exts, mExtId);
   89|      0|        }
   90|  1.15k|    } else {
   91|  1.15k|        container = &doc;
   92|  1.15k|    }
   93|       |
   94|  1.15k|    if (container) {
  ------------------
  |  Branch (94:9): [True: 1.15k, False: 0]
  ------------------
   95|  1.15k|        mDict = FindObject(*container, mDictId);
   96|  1.15k|    }
   97|  1.15k|}
_ZN4glTF8LazyDictINS_5ImageEE18DetachFromDocumentEv:
  100|    662|inline void LazyDict<T>::DetachFromDocument() {
  101|    662|    mDict = nullptr;
  102|    662|}
_ZN4glTF8LazyDictINS_8MaterialEEC2ERNS_5AssetEPKcS6_:
   71|  6.73k|        mDictId(dictId), mExtId(extId), mDict(nullptr), mAsset(asset) {
   72|  6.73k|    asset.mDicts.push_back(this); // register to the list of dictionaries
   73|  6.73k|}
_ZN4glTF8LazyDictINS_8MaterialEE16AttachToDocumentERN9rapidjson15GenericDocumentINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEES8_EE:
   83|  1.15k|inline void LazyDict<T>::AttachToDocument(Document &doc) {
   84|  1.15k|    Value *container = nullptr;
   85|       |
   86|  1.15k|    if (mExtId) {
  ------------------
  |  Branch (86:9): [True: 0, False: 1.15k]
  ------------------
   87|      0|        if (Value *exts = FindObject(doc, "extensions")) {
  ------------------
  |  Branch (87:20): [True: 0, False: 0]
  ------------------
   88|      0|            container = FindObject(*exts, mExtId);
   89|      0|        }
   90|  1.15k|    } else {
   91|  1.15k|        container = &doc;
   92|  1.15k|    }
   93|       |
   94|  1.15k|    if (container) {
  ------------------
  |  Branch (94:9): [True: 1.15k, False: 0]
  ------------------
   95|  1.15k|        mDict = FindObject(*container, mDictId);
   96|  1.15k|    }
   97|  1.15k|}
_ZN4glTF8LazyDictINS_8MaterialEE18DetachFromDocumentEv:
  100|    662|inline void LazyDict<T>::DetachFromDocument() {
  101|    662|    mDict = nullptr;
  102|    662|}
_ZN4glTF8LazyDictINS_4MeshEEC2ERNS_5AssetEPKcS6_:
   71|  6.73k|        mDictId(dictId), mExtId(extId), mDict(nullptr), mAsset(asset) {
   72|  6.73k|    asset.mDicts.push_back(this); // register to the list of dictionaries
   73|  6.73k|}
_ZN4glTF8LazyDictINS_4MeshEE16AttachToDocumentERN9rapidjson15GenericDocumentINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEES8_EE:
   83|  1.15k|inline void LazyDict<T>::AttachToDocument(Document &doc) {
   84|  1.15k|    Value *container = nullptr;
   85|       |
   86|  1.15k|    if (mExtId) {
  ------------------
  |  Branch (86:9): [True: 0, False: 1.15k]
  ------------------
   87|      0|        if (Value *exts = FindObject(doc, "extensions")) {
  ------------------
  |  Branch (87:20): [True: 0, False: 0]
  ------------------
   88|      0|            container = FindObject(*exts, mExtId);
   89|      0|        }
   90|  1.15k|    } else {
   91|  1.15k|        container = &doc;
   92|  1.15k|    }
   93|       |
   94|  1.15k|    if (container) {
  ------------------
  |  Branch (94:9): [True: 1.15k, False: 0]
  ------------------
   95|  1.15k|        mDict = FindObject(*container, mDictId);
   96|  1.15k|    }
   97|  1.15k|}
_ZN4glTF8LazyDictINS_4MeshEE18DetachFromDocumentEv:
  100|    662|inline void LazyDict<T>::DetachFromDocument() {
  101|    662|    mDict = nullptr;
  102|    662|}
_ZN4glTF8LazyDictINS_4NodeEEC2ERNS_5AssetEPKcS6_:
   71|  6.73k|        mDictId(dictId), mExtId(extId), mDict(nullptr), mAsset(asset) {
   72|  6.73k|    asset.mDicts.push_back(this); // register to the list of dictionaries
   73|  6.73k|}
_ZN4glTF8LazyDictINS_4NodeEE16AttachToDocumentERN9rapidjson15GenericDocumentINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEES8_EE:
   83|  1.15k|inline void LazyDict<T>::AttachToDocument(Document &doc) {
   84|  1.15k|    Value *container = nullptr;
   85|       |
   86|  1.15k|    if (mExtId) {
  ------------------
  |  Branch (86:9): [True: 0, False: 1.15k]
  ------------------
   87|      0|        if (Value *exts = FindObject(doc, "extensions")) {
  ------------------
  |  Branch (87:20): [True: 0, False: 0]
  ------------------
   88|      0|            container = FindObject(*exts, mExtId);
   89|      0|        }
   90|  1.15k|    } else {
   91|  1.15k|        container = &doc;
   92|  1.15k|    }
   93|       |
   94|  1.15k|    if (container) {
  ------------------
  |  Branch (94:9): [True: 1.15k, False: 0]
  ------------------
   95|  1.15k|        mDict = FindObject(*container, mDictId);
   96|  1.15k|    }
   97|  1.15k|}
_ZN4glTF8LazyDictINS_4NodeEE18DetachFromDocumentEv:
  100|    662|inline void LazyDict<T>::DetachFromDocument() {
  101|    662|    mDict = nullptr;
  102|    662|}
_ZN4glTF8LazyDictINS_7SamplerEEC2ERNS_5AssetEPKcS6_:
   71|  6.73k|        mDictId(dictId), mExtId(extId), mDict(nullptr), mAsset(asset) {
   72|  6.73k|    asset.mDicts.push_back(this); // register to the list of dictionaries
   73|  6.73k|}
_ZN4glTF8LazyDictINS_7SamplerEE16AttachToDocumentERN9rapidjson15GenericDocumentINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEES8_EE:
   83|  1.15k|inline void LazyDict<T>::AttachToDocument(Document &doc) {
   84|  1.15k|    Value *container = nullptr;
   85|       |
   86|  1.15k|    if (mExtId) {
  ------------------
  |  Branch (86:9): [True: 0, False: 1.15k]
  ------------------
   87|      0|        if (Value *exts = FindObject(doc, "extensions")) {
  ------------------
  |  Branch (87:20): [True: 0, False: 0]
  ------------------
   88|      0|            container = FindObject(*exts, mExtId);
   89|      0|        }
   90|  1.15k|    } else {
   91|  1.15k|        container = &doc;
   92|  1.15k|    }
   93|       |
   94|  1.15k|    if (container) {
  ------------------
  |  Branch (94:9): [True: 1.15k, False: 0]
  ------------------
   95|  1.15k|        mDict = FindObject(*container, mDictId);
   96|  1.15k|    }
   97|  1.15k|}
_ZN4glTF8LazyDictINS_7SamplerEE18DetachFromDocumentEv:
  100|    662|inline void LazyDict<T>::DetachFromDocument() {
  101|    662|    mDict = nullptr;
  102|    662|}
_ZN4glTF8LazyDictINS_5SceneEEC2ERNS_5AssetEPKcS6_:
   71|  6.73k|        mDictId(dictId), mExtId(extId), mDict(nullptr), mAsset(asset) {
   72|  6.73k|    asset.mDicts.push_back(this); // register to the list of dictionaries
   73|  6.73k|}
_ZN4glTF8LazyDictINS_5SceneEE16AttachToDocumentERN9rapidjson15GenericDocumentINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEES8_EE:
   83|  1.15k|inline void LazyDict<T>::AttachToDocument(Document &doc) {
   84|  1.15k|    Value *container = nullptr;
   85|       |
   86|  1.15k|    if (mExtId) {
  ------------------
  |  Branch (86:9): [True: 0, False: 1.15k]
  ------------------
   87|      0|        if (Value *exts = FindObject(doc, "extensions")) {
  ------------------
  |  Branch (87:20): [True: 0, False: 0]
  ------------------
   88|      0|            container = FindObject(*exts, mExtId);
   89|      0|        }
   90|  1.15k|    } else {
   91|  1.15k|        container = &doc;
   92|  1.15k|    }
   93|       |
   94|  1.15k|    if (container) {
  ------------------
  |  Branch (94:9): [True: 1.15k, False: 0]
  ------------------
   95|  1.15k|        mDict = FindObject(*container, mDictId);
   96|  1.15k|    }
   97|  1.15k|}
_ZN4glTF8LazyDictINS_5SceneEE18DetachFromDocumentEv:
  100|    662|inline void LazyDict<T>::DetachFromDocument() {
  101|    662|    mDict = nullptr;
  102|    662|}
_ZN4glTF8LazyDictINS_4SkinEEC2ERNS_5AssetEPKcS6_:
   71|  6.73k|        mDictId(dictId), mExtId(extId), mDict(nullptr), mAsset(asset) {
   72|  6.73k|    asset.mDicts.push_back(this); // register to the list of dictionaries
   73|  6.73k|}
_ZN4glTF8LazyDictINS_4SkinEE16AttachToDocumentERN9rapidjson15GenericDocumentINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEES8_EE:
   83|  1.15k|inline void LazyDict<T>::AttachToDocument(Document &doc) {
   84|  1.15k|    Value *container = nullptr;
   85|       |
   86|  1.15k|    if (mExtId) {
  ------------------
  |  Branch (86:9): [True: 0, False: 1.15k]
  ------------------
   87|      0|        if (Value *exts = FindObject(doc, "extensions")) {
  ------------------
  |  Branch (87:20): [True: 0, False: 0]
  ------------------
   88|      0|            container = FindObject(*exts, mExtId);
   89|      0|        }
   90|  1.15k|    } else {
   91|  1.15k|        container = &doc;
   92|  1.15k|    }
   93|       |
   94|  1.15k|    if (container) {
  ------------------
  |  Branch (94:9): [True: 1.15k, False: 0]
  ------------------
   95|  1.15k|        mDict = FindObject(*container, mDictId);
   96|  1.15k|    }
   97|  1.15k|}
_ZN4glTF8LazyDictINS_4SkinEE18DetachFromDocumentEv:
  100|    662|inline void LazyDict<T>::DetachFromDocument() {
  101|    662|    mDict = nullptr;
  102|    662|}
_ZN4glTF8LazyDictINS_7TextureEEC2ERNS_5AssetEPKcS6_:
   71|  6.73k|        mDictId(dictId), mExtId(extId), mDict(nullptr), mAsset(asset) {
   72|  6.73k|    asset.mDicts.push_back(this); // register to the list of dictionaries
   73|  6.73k|}
_ZN4glTF8LazyDictINS_7TextureEE16AttachToDocumentERN9rapidjson15GenericDocumentINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEES8_EE:
   83|  1.15k|inline void LazyDict<T>::AttachToDocument(Document &doc) {
   84|  1.15k|    Value *container = nullptr;
   85|       |
   86|  1.15k|    if (mExtId) {
  ------------------
  |  Branch (86:9): [True: 0, False: 1.15k]
  ------------------
   87|      0|        if (Value *exts = FindObject(doc, "extensions")) {
  ------------------
  |  Branch (87:20): [True: 0, False: 0]
  ------------------
   88|      0|            container = FindObject(*exts, mExtId);
   89|      0|        }
   90|  1.15k|    } else {
   91|  1.15k|        container = &doc;
   92|  1.15k|    }
   93|       |
   94|  1.15k|    if (container) {
  ------------------
  |  Branch (94:9): [True: 1.15k, False: 0]
  ------------------
   95|  1.15k|        mDict = FindObject(*container, mDictId);
   96|  1.15k|    }
   97|  1.15k|}
_ZN4glTF8LazyDictINS_7TextureEE18DetachFromDocumentEv:
  100|    662|inline void LazyDict<T>::DetachFromDocument() {
  101|    662|    mDict = nullptr;
  102|    662|}
_ZN4glTF8LazyDictINS_5LightEEC2ERNS_5AssetEPKcS6_:
   71|  6.73k|        mDictId(dictId), mExtId(extId), mDict(nullptr), mAsset(asset) {
   72|  6.73k|    asset.mDicts.push_back(this); // register to the list of dictionaries
   73|  6.73k|}
_ZN4glTF8LazyDictINS_5LightEE16AttachToDocumentERN9rapidjson15GenericDocumentINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEES8_EE:
   83|  1.15k|inline void LazyDict<T>::AttachToDocument(Document &doc) {
   84|  1.15k|    Value *container = nullptr;
   85|       |
   86|  1.15k|    if (mExtId) {
  ------------------
  |  Branch (86:9): [True: 1.15k, False: 0]
  ------------------
   87|  1.15k|        if (Value *exts = FindObject(doc, "extensions")) {
  ------------------
  |  Branch (87:20): [True: 2, False: 1.14k]
  ------------------
   88|      2|            container = FindObject(*exts, mExtId);
   89|      2|        }
   90|  1.15k|    } else {
   91|      0|        container = &doc;
   92|      0|    }
   93|       |
   94|  1.15k|    if (container) {
  ------------------
  |  Branch (94:9): [True: 0, False: 1.15k]
  ------------------
   95|      0|        mDict = FindObject(*container, mDictId);
   96|      0|    }
   97|  1.15k|}
_ZN4glTF8LazyDictINS_5LightEE18DetachFromDocumentEv:
  100|    662|inline void LazyDict<T>::DetachFromDocument() {
  101|    662|    mDict = nullptr;
  102|    662|}
_ZN4glTF8LazyDictINS_5LightEED2Ev:
   76|  6.73k|inline LazyDict<T>::~LazyDict() {
   77|  6.73k|    for (size_t i = 0; i < mObjs.size(); ++i) {
  ------------------
  |  Branch (77:24): [True: 0, False: 6.73k]
  ------------------
   78|      0|        delete mObjs[i];
   79|      0|    }
   80|  6.73k|}
_ZN4glTF8LazyDictINS_7TextureEED2Ev:
   76|  6.73k|inline LazyDict<T>::~LazyDict() {
   77|  6.75k|    for (size_t i = 0; i < mObjs.size(); ++i) {
  ------------------
  |  Branch (77:24): [True: 22, False: 6.73k]
  ------------------
   78|     22|        delete mObjs[i];
   79|     22|    }
   80|  6.73k|}
_ZN4glTF8LazyDictINS_4SkinEED2Ev:
   76|  6.73k|inline LazyDict<T>::~LazyDict() {
   77|  6.73k|    for (size_t i = 0; i < mObjs.size(); ++i) {
  ------------------
  |  Branch (77:24): [True: 0, False: 6.73k]
  ------------------
   78|      0|        delete mObjs[i];
   79|      0|    }
   80|  6.73k|}
_ZN4glTF8LazyDictINS_5SceneEED2Ev:
   76|  6.73k|inline LazyDict<T>::~LazyDict() {
   77|  6.82k|    for (size_t i = 0; i < mObjs.size(); ++i) {
  ------------------
  |  Branch (77:24): [True: 92, False: 6.73k]
  ------------------
   78|     92|        delete mObjs[i];
   79|     92|    }
   80|  6.73k|}
_ZN4glTF8LazyDictINS_7SamplerEED2Ev:
   76|  6.73k|inline LazyDict<T>::~LazyDict() {
   77|  6.75k|    for (size_t i = 0; i < mObjs.size(); ++i) {
  ------------------
  |  Branch (77:24): [True: 18, False: 6.73k]
  ------------------
   78|     18|        delete mObjs[i];
   79|     18|    }
   80|  6.73k|}
_ZN4glTF8LazyDictINS_4NodeEED2Ev:
   76|  6.73k|inline LazyDict<T>::~LazyDict() {
   77|  7.87k|    for (size_t i = 0; i < mObjs.size(); ++i) {
  ------------------
  |  Branch (77:24): [True: 1.13k, False: 6.73k]
  ------------------
   78|  1.13k|        delete mObjs[i];
   79|  1.13k|    }
   80|  6.73k|}
_ZN4glTF8LazyDictINS_4MeshEED2Ev:
   76|  6.73k|inline LazyDict<T>::~LazyDict() {
   77|  7.43k|    for (size_t i = 0; i < mObjs.size(); ++i) {
  ------------------
  |  Branch (77:24): [True: 698, False: 6.73k]
  ------------------
   78|    698|        delete mObjs[i];
   79|    698|    }
   80|  6.73k|}
_ZN4glTF8LazyDictINS_8MaterialEED2Ev:
   76|  6.73k|inline LazyDict<T>::~LazyDict() {
   77|  6.77k|    for (size_t i = 0; i < mObjs.size(); ++i) {
  ------------------
  |  Branch (77:24): [True: 44, False: 6.73k]
  ------------------
   78|     44|        delete mObjs[i];
   79|     44|    }
   80|  6.73k|}
_ZN4glTF8LazyDictINS_5ImageEED2Ev:
   76|  6.73k|inline LazyDict<T>::~LazyDict() {
   77|  6.76k|    for (size_t i = 0; i < mObjs.size(); ++i) {
  ------------------
  |  Branch (77:24): [True: 28, False: 6.73k]
  ------------------
   78|     28|        delete mObjs[i];
   79|     28|    }
   80|  6.73k|}
_ZN4glTF8LazyDictINS_6CameraEED2Ev:
   76|  6.73k|inline LazyDict<T>::~LazyDict() {
   77|  6.73k|    for (size_t i = 0; i < mObjs.size(); ++i) {
  ------------------
  |  Branch (77:24): [True: 0, False: 6.73k]
  ------------------
   78|      0|        delete mObjs[i];
   79|      0|    }
   80|  6.73k|}
_ZN4glTF8LazyDictINS_10BufferViewEED2Ev:
   76|  6.73k|inline LazyDict<T>::~LazyDict() {
   77|  7.13k|    for (size_t i = 0; i < mObjs.size(); ++i) {
  ------------------
  |  Branch (77:24): [True: 404, False: 6.73k]
  ------------------
   78|    404|        delete mObjs[i];
   79|    404|    }
   80|  6.73k|}
_ZN4glTF8LazyDictINS_6BufferEED2Ev:
   76|  6.73k|inline LazyDict<T>::~LazyDict() {
   77|  8.87k|    for (size_t i = 0; i < mObjs.size(); ++i) {
  ------------------
  |  Branch (77:24): [True: 2.13k, False: 6.73k]
  ------------------
   78|  2.13k|        delete mObjs[i];
   79|  2.13k|    }
   80|  6.73k|}
_ZN4glTF8LazyDictINS_9AnimationEED2Ev:
   76|  6.73k|inline LazyDict<T>::~LazyDict() {
   77|  6.73k|    for (size_t i = 0; i < mObjs.size(); ++i) {
  ------------------
  |  Branch (77:24): [True: 0, False: 6.73k]
  ------------------
   78|      0|        delete mObjs[i];
   79|      0|    }
   80|  6.73k|}
_ZN4glTF8LazyDictINS_8AccessorEED2Ev:
   76|  6.73k|inline LazyDict<T>::~LazyDict() {
   77|  7.48k|    for (size_t i = 0; i < mObjs.size(); ++i) {
  ------------------
  |  Branch (77:24): [True: 748, False: 6.73k]
  ------------------
   78|    748|        delete mObjs[i];
   79|    748|    }
   80|  6.73k|}
_ZN4glTF5Asset4LoadERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEb:
 1156|  6.73k|inline void Asset::Load(const std::string &pFile, bool isBinary) {
 1157|  6.73k|    mCurrentAssetDir.clear();
 1158|       |
 1159|       |    /*int pos = std::max(int(pFile.rfind('/')), int(pFile.rfind('\\')));
 1160|       |    if (pos != int(std::string::npos)) mCurrentAssetDir = pFile.substr(0, pos + 1);*/
 1161|  6.73k|    if (0 != strncmp(pFile.c_str(), AI_MEMORYIO_MAGIC_FILENAME, AI_MEMORYIO_MAGIC_FILENAME_LENGTH)) {
  ------------------
  |  Branch (1161:9): [True: 0, False: 6.73k]
  ------------------
 1162|      0|        mCurrentAssetDir = getCurrentAssetDir(pFile);
 1163|      0|    }
 1164|       |
 1165|  6.73k|    shared_ptr<IOStream> stream(OpenFile(pFile.c_str(), "rb", true));
 1166|  6.73k|    if (!stream) {
  ------------------
  |  Branch (1166:9): [True: 0, False: 6.73k]
  ------------------
 1167|      0|        throw DeadlyImportError("GLTF: Could not open file for reading");
 1168|      0|    }
 1169|       |
 1170|       |    // is binary? then read the header
 1171|  6.73k|    if (isBinary) {
  ------------------
  |  Branch (1171:9): [True: 1.96k, False: 4.76k]
  ------------------
 1172|  1.96k|        SetAsBinary(); // also creates the body buffer
 1173|  1.96k|        ReadBinaryHeader(*stream);
 1174|  4.76k|    } else {
 1175|  4.76k|        mSceneLength = stream->FileSize();
 1176|  4.76k|        mBodyLength = 0;
 1177|  4.76k|    }
 1178|       |
 1179|       |    // Smallest legal JSON file is "{}" Smallest loadable glTF file is larger than that but catch it later
 1180|  6.73k|    if (mSceneLength < 2) {
  ------------------
  |  Branch (1180:9): [True: 0, False: 6.73k]
  ------------------
 1181|      0|        throw DeadlyImportError("GLTF: No JSON file contents");
 1182|      0|    }
 1183|       |
 1184|       |    // Binary format only supports up to 4GB of JSON so limit it there to avoid extreme memory allocation
 1185|  6.73k|    if (mSceneLength >= std::numeric_limits<uint32_t>::max()) {
  ------------------
  |  Branch (1185:9): [True: 2, False: 6.73k]
  ------------------
 1186|      2|        throw DeadlyImportError("GLTF: JSON size greater than 4GB");
 1187|      2|    }
 1188|       |
 1189|       |    // read the scene data, ensure null termination
 1190|  6.73k|    std::vector<char> sceneData(mSceneLength + 1);
 1191|  6.73k|    sceneData[mSceneLength] = '\0';
 1192|       |
 1193|  6.73k|    if (stream->Read(&sceneData[0], 1, mSceneLength) != mSceneLength) {
  ------------------
  |  Branch (1193:9): [True: 38, False: 6.69k]
  ------------------
 1194|     38|        throw DeadlyImportError("GLTF: Could not read the file contents");
 1195|     38|    }
 1196|       |
 1197|       |    // parse the JSON document
 1198|       |
 1199|  6.69k|    Document doc;
 1200|  6.69k|    doc.ParseInsitu(&sceneData[0]);
 1201|       |
 1202|  6.69k|    if (doc.HasParseError()) {
  ------------------
  |  Branch (1202:9): [True: 1.24k, False: 5.44k]
  ------------------
 1203|  1.24k|        char buffer[32];
 1204|  1.24k|        ai_snprintf(buffer, 32, "%d", static_cast<int>(doc.GetErrorOffset()));
 1205|  1.24k|        throw DeadlyImportError("GLTF: JSON parse error, offset ", buffer, ": ", GetParseError_En(doc.GetParseError()));
 1206|  1.24k|    }
 1207|       |
 1208|  5.44k|    if (!doc.IsObject()) {
  ------------------
  |  Branch (1208:9): [True: 188, False: 5.25k]
  ------------------
 1209|    188|        throw DeadlyImportError("GLTF: JSON document root must be a JSON object");
 1210|    188|    }
 1211|       |
 1212|       |    // Fill the buffer instance for the current file embedded contents
 1213|  5.25k|    if (mBodyLength > 0) {
  ------------------
  |  Branch (1213:9): [True: 0, False: 5.25k]
  ------------------
 1214|      0|        if (!mBodyBuffer->LoadFromStream(*stream, mBodyLength, mBodyOffset)) {
  ------------------
  |  Branch (1214:13): [True: 0, False: 0]
  ------------------
 1215|      0|            throw DeadlyImportError("GLTF: Unable to read gltf file");
 1216|      0|        }
 1217|      0|    }
 1218|       |
 1219|       |    // Load the metadata
 1220|  5.25k|    asset.Read(doc);
 1221|  5.25k|    if (!asset) {
  ------------------
  |  Branch (1221:9): [True: 2.25k, False: 3.00k]
  ------------------
 1222|  2.25k|        return;
 1223|  2.25k|    }
 1224|       |
 1225|  3.00k|    ReadExtensionsUsed(doc);
 1226|       |
 1227|       |    // Prepare the dictionaries
 1228|  19.1k|    for (size_t i = 0; i < mDicts.size(); ++i) {
  ------------------
  |  Branch (1228:24): [True: 16.1k, False: 3.00k]
  ------------------
 1229|  16.1k|        mDicts[i]->AttachToDocument(doc);
 1230|  16.1k|    }
 1231|       |
 1232|       |    // Read the "scene" property, which specifies which scene to load
 1233|       |    // and recursively load everything referenced by it
 1234|  3.00k|    Value *curScene = FindString(doc, "scene");
 1235|  3.00k|    if (nullptr != curScene) {
  ------------------
  |  Branch (1235:9): [True: 554, False: 2.44k]
  ------------------
 1236|    554|        this->scene = scenes.Get(curScene->GetString());
 1237|    554|    }
 1238|       |
 1239|       |    // Clean up
 1240|  12.2k|    for (size_t i = 0; i < mDicts.size(); ++i) {
  ------------------
  |  Branch (1240:24): [True: 9.26k, False: 3.00k]
  ------------------
 1241|  9.26k|        mDicts[i]->DetachFromDocument();
 1242|  9.26k|    }
 1243|  3.00k|}
_ZN4glTF5Asset8OpenFileERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEPKcb:
 1271|  6.75k|inline IOStream *Asset::OpenFile(const std::string &path, const char *mode, bool absolute) {
 1272|  6.75k|#ifdef ASSIMP_API
 1273|  6.75k|    (void)absolute;
 1274|  6.75k|    return mIOSystem->Open(path, mode);
 1275|       |#else
 1276|       |    if (path.size() < 2) return 0;
 1277|       |    if (!absolute && path[1] != ':' && path[0] != '/') { // relative?
 1278|       |        path = mCurrentAssetDir + path;
 1279|       |    }
 1280|       |    FILE *f = fopen(path.c_str(), mode);
 1281|       |    return f ? new IOStream(f) : 0;
 1282|       |#endif
 1283|  6.75k|}
_ZN4glTF5Asset11SetAsBinaryEv:
 1245|  1.96k|inline void Asset::SetAsBinary() {
 1246|  1.96k|    if (!extensionsUsed.KHR_binary_glTF) {
  ------------------
  |  Branch (1246:9): [True: 1.96k, False: 0]
  ------------------
 1247|  1.96k|        extensionsUsed.KHR_binary_glTF = true;
 1248|  1.96k|        mBodyBuffer = buffers.Create("binary_glTF");
 1249|  1.96k|        mBodyBuffer->MarkAsSpecial();
 1250|  1.96k|    }
 1251|  1.96k|}
_ZN4glTF8LazyDictINS_6BufferEE6CreateEPKc:
  149|  1.96k|Ref<T> LazyDict<T>::Create(const char *id) {
  150|  1.96k|    Asset::IdMap::iterator it = mAsset.mUsedIds.find(id);
  151|  1.96k|    if (it != mAsset.mUsedIds.end()) {
  ------------------
  |  Branch (151:9): [True: 0, False: 1.96k]
  ------------------
  152|      0|        throw DeadlyImportError("GLTF: two objects with the same ID exist");
  153|      0|    }
  154|  1.96k|    T *inst = new T();
  155|  1.96k|    inst->id = id;
  156|  1.96k|    return Add(inst);
  157|  1.96k|}
_ZN4glTF6BufferC2Ev:
  164|  2.16k|        byteLength(0), type(Type_arraybuffer), EncodedRegion_Current(nullptr), mIsSpecial(false) {}
_ZN4glTF8LazyDictINS_6BufferEE3AddEPS1_:
  140|  2.13k|Ref<T> LazyDict<T>::Add(T *obj) {
  141|  2.13k|    unsigned int idx = unsigned(mObjs.size());
  142|  2.13k|    mObjs.push_back(obj);
  143|  2.13k|    mObjsById[obj->id] = idx;
  144|  2.13k|    mAsset.mUsedIds[obj->id] = true;
  145|  2.13k|    return Ref<T>(mObjs, idx);
  146|  2.13k|}
_ZN4glTF5Asset16ReadBinaryHeaderERN6Assimp8IOStreamE:
 1123|  1.96k|inline void Asset::ReadBinaryHeader(IOStream &stream) {
 1124|  1.96k|    GLB_Header header;
 1125|  1.96k|    if (stream.Read(&header, sizeof(header), 1) != 1) {
  ------------------
  |  Branch (1125:9): [True: 0, False: 1.96k]
  ------------------
 1126|      0|        throw DeadlyImportError("GLTF: Unable to read the file header");
 1127|      0|    }
 1128|       |
 1129|  1.96k|    if (strncmp((char *)header.magic, AI_GLB_MAGIC_NUMBER, sizeof(header.magic)) != 0) {
  ------------------
  |  |  127|  1.96k|#define AI_GLB_MAGIC_NUMBER "glTF"
  ------------------
  |  Branch (1129:9): [True: 0, False: 1.96k]
  ------------------
 1130|      0|        throw DeadlyImportError("GLTF: Invalid binary glTF file");
 1131|      0|    }
 1132|       |
 1133|  1.96k|    AI_SWAP4(header.version);
 1134|  1.96k|    asset.version = ai_to_string(header.version);
 1135|  1.96k|    if (header.version != 1) {
  ------------------
  |  Branch (1135:9): [True: 1.81k, False: 154]
  ------------------
 1136|  1.81k|        throw DeadlyImportError("GLTF: Unsupported binary glTF version");
 1137|  1.81k|    }
 1138|       |
 1139|    154|    AI_SWAP4(header.sceneFormat);
 1140|    154|    if (header.sceneFormat != SceneFormat_JSON) {
  ------------------
  |  Branch (1140:9): [True: 36, False: 118]
  ------------------
 1141|     36|        throw DeadlyImportError("GLTF: Unsupported binary glTF scene format");
 1142|     36|    }
 1143|       |
 1144|    118|    AI_SWAP4(header.length);
 1145|    118|    AI_SWAP4(header.sceneLength);
 1146|       |
 1147|    118|    static_assert(std::numeric_limits<uint32_t>::max() <= std::numeric_limits<size_t>::max(), "size_t must be at least 32bits");
 1148|    118|    mSceneLength = static_cast<size_t>(header.sceneLength); // Can't be larger than 4GB (max. uint32_t)
 1149|       |
 1150|    118|    mBodyOffset = sizeof(header) + mSceneLength;
 1151|    118|    mBodyOffset = (mBodyOffset + 3) & ~3; // Round up to next multiple of 4
 1152|       |
 1153|    118|    mBodyLength = header.length - mBodyOffset;
 1154|    118|}
_ZN4glTF13AssetMetadata4ReadERN9rapidjson15GenericDocumentINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEES6_EE:
 1093|  3.40k|inline void AssetMetadata::Read(Document &doc) {
 1094|       |    // read the version, etc.
 1095|  3.40k|    if (Value *obj = FindObject(doc, "asset")) {
  ------------------
  |  Branch (1095:16): [True: 3.30k, False: 104]
  ------------------
 1096|  3.30k|        ReadMember(*obj, "copyright", copyright);
 1097|  3.30k|        ReadMember(*obj, "generator", generator);
 1098|       |
 1099|  3.30k|        premultipliedAlpha = MemberOrDefault(*obj, "premultipliedAlpha", false);
 1100|       |
 1101|  3.30k|        if (Value *versionString = FindString(*obj, "version")) {
  ------------------
  |  Branch (1101:20): [True: 3.11k, False: 194]
  ------------------
 1102|  3.11k|            version = versionString->GetString();
 1103|  3.11k|        } else if (Value *versionNumber = FindNumber(*obj, "version")) {
  ------------------
  |  Branch (1103:27): [True: 138, False: 56]
  ------------------
 1104|    138|            char buf[4];
 1105|       |
 1106|    138|            ai_snprintf(buf, 4, "%.1f", versionNumber->GetDouble());
 1107|       |
 1108|    138|            version = buf;
 1109|    138|        }
 1110|       |
 1111|  3.30k|        Value *curProfile = FindObject(*obj, "profile");
 1112|  3.30k|        if (nullptr != curProfile) {
  ------------------
  |  Branch (1112:13): [True: 253, False: 3.05k]
  ------------------
 1113|    253|            ReadMember(*curProfile, "api", this->profile.api);
 1114|    253|            ReadMember(*curProfile, "version", this->profile.version);
 1115|    253|        }
 1116|  3.30k|    }
 1117|  3.40k|}
_ZN4glTF5Asset18ReadExtensionsUsedERN9rapidjson15GenericDocumentINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEES6_EE:
 1253|  1.15k|inline void Asset::ReadExtensionsUsed(Document &doc) {
 1254|  1.15k|    Value *extsUsed = FindArray(doc, "extensionsUsed");
 1255|  1.15k|    if (!extsUsed) return;
  ------------------
  |  Branch (1255:9): [True: 768, False: 384]
  ------------------
 1256|       |
 1257|    384|    std::gltf_unordered_map<std::string, bool> exts;
 1258|       |
 1259|  7.10k|    for (unsigned int i = 0; i < extsUsed->Size(); ++i) {
  ------------------
  |  Branch (1259:30): [True: 6.72k, False: 384]
  ------------------
 1260|  6.72k|        if ((*extsUsed)[i].IsString()) {
  ------------------
  |  Branch (1260:13): [True: 6.62k, False: 96]
  ------------------
 1261|  6.62k|            exts[(*extsUsed)[i].GetString()] = true;
 1262|  6.62k|        }
 1263|  6.72k|    }
 1264|       |
 1265|    384|    CHECK_EXT(KHR_binary_glTF);
  ------------------
  |  |  237|    384|    if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true;
  |  |  ------------------
  |  |  |  Branch (237:9): [True: 0, False: 384]
  |  |  ------------------
  ------------------
 1266|    384|    CHECK_EXT(KHR_materials_common);
  ------------------
  |  |  237|    384|    if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true;
  |  |  ------------------
  |  |  |  Branch (237:9): [True: 6, False: 378]
  |  |  ------------------
  ------------------
 1267|       |
 1268|    384|#undef CHECK_EXT
 1269|    384|}
_ZN4glTF8LazyDictINS_5SceneEE3GetEPKc:
  110|    554|Ref<T> LazyDict<T>::Get(const char *id) {
  111|    554|    id = T::TranslateId(mAsset, id);
  112|       |
  113|    554|    typename Dict::iterator it = mObjsById.find(id);
  114|    554|    if (it != mObjsById.end()) { // already created?
  ------------------
  |  Branch (114:9): [True: 0, False: 554]
  ------------------
  115|      0|        return Ref<T>(mObjs, it->second);
  116|      0|    }
  117|       |
  118|       |    // read it from the JSON object
  119|    554|    if (!mDict) {
  ------------------
  |  Branch (119:9): [True: 2, False: 552]
  ------------------
  120|      2|        throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\"");
  121|      2|    }
  122|       |
  123|    552|    Value::MemberIterator obj = mDict->FindMember(id);
  124|    552|    if (obj == mDict->MemberEnd()) {
  ------------------
  |  Branch (124:9): [True: 12, False: 540]
  ------------------
  125|     12|        throw DeadlyImportError("GLTF: Missing object with id \"", id, "\" in \"", mDictId, "\"");
  126|     12|    }
  127|    540|    if (!obj->value.IsObject()) {
  ------------------
  |  Branch (127:9): [True: 2, False: 538]
  ------------------
  128|      2|        throw DeadlyImportError("GLTF: Object with id \"", id, "\" is not a JSON object");
  129|      2|    }
  130|       |
  131|       |    // create an instance of the given type
  132|    538|    T *inst = new T();
  133|    538|    inst->id = id;
  134|    538|    ReadMember(obj->value, "name", inst->name);
  135|    538|    inst->Read(obj->value, mAsset);
  136|    538|    return Add(inst);
  137|    540|}
_ZN4glTF5Scene4ReadERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEERNS_5AssetE:
 1082|    538|inline void Scene::Read(Value &obj, Asset &r) {
 1083|    538|    if (Value *array = FindArray(obj, "nodes")) {
  ------------------
  |  Branch (1083:16): [True: 532, False: 6]
  ------------------
 1084|  2.26k|        for (unsigned int i = 0; i < array->Size(); ++i) {
  ------------------
  |  Branch (1084:34): [True: 1.73k, False: 532]
  ------------------
 1085|  1.73k|            if (!(*array)[i].IsString()) continue;
  ------------------
  |  Branch (1085:17): [True: 20, False: 1.71k]
  ------------------
 1086|  1.71k|            Ref<Node> node = r.nodes.Get((*array)[i].GetString());
 1087|  1.71k|            if (node)
  ------------------
  |  Branch (1087:17): [True: 1.26k, False: 446]
  ------------------
 1088|  1.26k|                this->nodes.push_back(node);
 1089|  1.71k|        }
 1090|    532|    }
 1091|    538|}
_ZN4glTF8LazyDictINS_4NodeEE3GetEPKc:
  110|  2.08k|Ref<T> LazyDict<T>::Get(const char *id) {
  111|  2.08k|    id = T::TranslateId(mAsset, id);
  112|       |
  113|  2.08k|    typename Dict::iterator it = mObjsById.find(id);
  114|  2.08k|    if (it != mObjsById.end()) { // already created?
  ------------------
  |  Branch (114:9): [True: 362, False: 1.72k]
  ------------------
  115|    362|        return Ref<T>(mObjs, it->second);
  116|    362|    }
  117|       |
  118|       |    // read it from the JSON object
  119|  1.72k|    if (!mDict) {
  ------------------
  |  Branch (119:9): [True: 6, False: 1.71k]
  ------------------
  120|      6|        throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\"");
  121|      6|    }
  122|       |
  123|  1.71k|    Value::MemberIterator obj = mDict->FindMember(id);
  124|  1.71k|    if (obj == mDict->MemberEnd()) {
  ------------------
  |  Branch (124:9): [True: 152, False: 1.56k]
  ------------------
  125|    152|        throw DeadlyImportError("GLTF: Missing object with id \"", id, "\" in \"", mDictId, "\"");
  126|    152|    }
  127|  1.56k|    if (!obj->value.IsObject()) {
  ------------------
  |  Branch (127:9): [True: 2, False: 1.56k]
  ------------------
  128|      2|        throw DeadlyImportError("GLTF: Object with id \"", id, "\" is not a JSON object");
  129|      2|    }
  130|       |
  131|       |    // create an instance of the given type
  132|  1.56k|    T *inst = new T();
  133|  1.56k|    inst->id = id;
  134|  1.56k|    ReadMember(obj->value, "name", inst->name);
  135|  1.56k|    inst->Read(obj->value, mAsset);
  136|  1.56k|    return Add(inst);
  137|  1.56k|}
_ZN4glTF4Node4ReadERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEERNS_5AssetE:
 1015|  1.56k|inline void Node::Read(Value &obj, Asset &r) {
 1016|  1.56k|    if (name.empty()) {
  ------------------
  |  Branch (1016:9): [True: 82, False: 1.48k]
  ------------------
 1017|     82|        name = id;
 1018|     82|    }
 1019|       |
 1020|  1.56k|    Value *curChildren = FindArray(obj, "children");
 1021|  1.56k|    if (nullptr != curChildren) {
  ------------------
  |  Branch (1021:9): [True: 674, False: 888]
  ------------------
 1022|    674|        this->children.reserve(curChildren->Size());
 1023|  1.14k|        for (unsigned int i = 0; i < curChildren->Size(); ++i) {
  ------------------
  |  Branch (1023:34): [True: 474, False: 674]
  ------------------
 1024|    474|            Value &child = (*curChildren)[i];
 1025|    474|            if (child.IsString()) {
  ------------------
  |  Branch (1025:17): [True: 372, False: 102]
  ------------------
 1026|       |                // get/create the child node
 1027|    372|                Ref<Node> chn = r.nodes.Get(child.GetString());
 1028|    372|                if (chn) this->children.push_back(chn);
  ------------------
  |  Branch (1028:21): [True: 232, False: 140]
  ------------------
 1029|    372|            }
 1030|    474|        }
 1031|    674|    }
 1032|       |
 1033|  1.56k|    Value *curMatrix = FindArray(obj, "matrix");
 1034|  1.56k|    if (nullptr != curMatrix) {
  ------------------
  |  Branch (1034:9): [True: 376, False: 1.18k]
  ------------------
 1035|    376|        ReadValue(*curMatrix, this->matrix);
 1036|  1.18k|    } else {
 1037|  1.18k|        ReadMember(obj, "translation", translation);
 1038|  1.18k|        ReadMember(obj, "scale", scale);
 1039|  1.18k|        ReadMember(obj, "rotation", rotation);
 1040|  1.18k|    }
 1041|       |
 1042|  1.56k|    Value *curMeshes = FindArray(obj, "meshes");
 1043|  1.56k|    if (nullptr != curMeshes) {
  ------------------
  |  Branch (1043:9): [True: 1.11k, False: 448]
  ------------------
 1044|  1.11k|        unsigned int numMeshes = (unsigned int)curMeshes->Size();
 1045|       |
 1046|  1.11k|        std::vector<unsigned int> meshList;
 1047|       |
 1048|  1.11k|        this->meshes.reserve(numMeshes);
 1049|  2.34k|        for (unsigned i = 0; i < numMeshes; ++i) {
  ------------------
  |  Branch (1049:30): [True: 1.23k, False: 1.11k]
  ------------------
 1050|  1.23k|            if ((*curMeshes)[i].IsString()) {
  ------------------
  |  Branch (1050:17): [True: 1.08k, False: 148]
  ------------------
 1051|  1.08k|                Ref<Mesh> mesh = r.meshes.Get((*curMeshes)[i].GetString());
 1052|  1.08k|                if (mesh) {
  ------------------
  |  Branch (1052:21): [True: 798, False: 286]
  ------------------
 1053|    798|                    this->meshes.push_back(mesh);
 1054|    798|                }
 1055|  1.08k|            }
 1056|  1.23k|        }
 1057|  1.11k|    }
 1058|       |
 1059|  1.56k|    Value *curCamera = FindString(obj, "camera");
 1060|  1.56k|    if (nullptr != curCamera) {
  ------------------
  |  Branch (1060:9): [True: 0, False: 1.56k]
  ------------------
 1061|      0|        this->camera = r.cameras.Get(curCamera->GetString());
 1062|      0|        if (this->camera) {
  ------------------
  |  Branch (1062:13): [True: 0, False: 0]
  ------------------
 1063|      0|            this->camera->id = this->id;
 1064|      0|        }
 1065|      0|    }
 1066|       |
 1067|       |    // TODO load "skeletons", "skin", "jointName"
 1068|       |
 1069|  1.56k|    if (Value *extensions = FindObject(obj, "extensions")) {
  ------------------
  |  Branch (1069:16): [True: 0, False: 1.56k]
  ------------------
 1070|      0|        if (r.extensionsUsed.KHR_materials_common) {
  ------------------
  |  Branch (1070:13): [True: 0, False: 0]
  ------------------
 1071|       |
 1072|      0|            if (Value *ext = FindObject(*extensions, "KHR_materials_common")) {
  ------------------
  |  Branch (1072:24): [True: 0, False: 0]
  ------------------
 1073|      0|                Value *curLight = FindString(*ext, "light");
 1074|      0|                if (nullptr != curLight) {
  ------------------
  |  Branch (1074:21): [True: 0, False: 0]
  ------------------
 1075|      0|                    this->light = r.lights.Get(curLight->GetString());
 1076|      0|                }
 1077|      0|            }
 1078|      0|        }
 1079|      0|    }
 1080|  1.56k|}
_ZN4glTF8LazyDictINS_4MeshEE3GetEPKc:
  110|  1.08k|Ref<T> LazyDict<T>::Get(const char *id) {
  111|  1.08k|    id = T::TranslateId(mAsset, id);
  112|       |
  113|  1.08k|    typename Dict::iterator it = mObjsById.find(id);
  114|  1.08k|    if (it != mObjsById.end()) { // already created?
  ------------------
  |  Branch (114:9): [True: 100, False: 984]
  ------------------
  115|    100|        return Ref<T>(mObjs, it->second);
  116|    100|    }
  117|       |
  118|       |    // read it from the JSON object
  119|    984|    if (!mDict) {
  ------------------
  |  Branch (119:9): [True: 4, False: 980]
  ------------------
  120|      4|        throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\"");
  121|      4|    }
  122|       |
  123|    980|    Value::MemberIterator obj = mDict->FindMember(id);
  124|    980|    if (obj == mDict->MemberEnd()) {
  ------------------
  |  Branch (124:9): [True: 58, False: 922]
  ------------------
  125|     58|        throw DeadlyImportError("GLTF: Missing object with id \"", id, "\" in \"", mDictId, "\"");
  126|     58|    }
  127|    922|    if (!obj->value.IsObject()) {
  ------------------
  |  Branch (127:9): [True: 2, False: 920]
  ------------------
  128|      2|        throw DeadlyImportError("GLTF: Object with id \"", id, "\" is not a JSON object");
  129|      2|    }
  130|       |
  131|       |    // create an instance of the given type
  132|    920|    T *inst = new T();
  133|    920|    inst->id = id;
  134|    920|    ReadMember(obj->value, "name", inst->name);
  135|    920|    inst->Read(obj->value, mAsset);
  136|    920|    return Add(inst);
  137|    922|}
_ZN4glTF4Mesh4ReadERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEERNS_5AssetE:
  682|    920|inline void Mesh::Read(Value &pJSON_Object, Asset &pAsset_Root) {
  683|       |    /****************** Mesh primitives ******************/
  684|    920|    Value *curPrimitives = FindArray(pJSON_Object, "primitives");
  685|    920|    if (nullptr != curPrimitives) {
  ------------------
  |  Branch (685:9): [True: 824, False: 96]
  ------------------
  686|    824|        this->primitives.resize(curPrimitives->Size());
  687|  1.67k|        for (unsigned int i = 0; i < curPrimitives->Size(); ++i) {
  ------------------
  |  Branch (687:34): [True: 846, False: 824]
  ------------------
  688|    846|            Value &primitive = (*curPrimitives)[i];
  689|       |
  690|    846|            Primitive &prim = this->primitives[i];
  691|    846|            prim.mode = MemberOrDefault(primitive, "mode", PrimitiveMode_TRIANGLES);
  692|       |
  693|    846|            if (Value *attrs = FindObject(primitive, "attributes")) {
  ------------------
  |  Branch (693:24): [True: 644, False: 202]
  ------------------
  694|  1.55k|                for (Value::MemberIterator it = attrs->MemberBegin(); it != attrs->MemberEnd(); ++it) {
  ------------------
  |  Branch (694:71): [True: 906, False: 644]
  ------------------
  695|    906|                    if (!it->value.IsString()) continue;
  ------------------
  |  Branch (695:25): [True: 6, False: 900]
  ------------------
  696|    900|                    const char *attr = it->name.GetString();
  697|       |                    // Valid attribute semantics include POSITION, NORMAL, TEXCOORD, COLOR, JOINT, JOINTMATRIX,
  698|       |                    // and WEIGHT.Attribute semantics can be of the form[semantic]_[set_index], e.g., TEXCOORD_0, TEXCOORD_1, etc.
  699|       |
  700|    900|                    int undPos = 0;
  701|    900|                    Mesh::AccessorList *vec = nullptr;
  702|    900|                    if (GetAttribVector(prim, attr, vec, undPos)) {
  ------------------
  |  Branch (702:25): [True: 782, False: 118]
  ------------------
  703|    782|                        size_t idx = (attr[undPos] == '_') ? atoi(attr + undPos + 1) : 0;
  ------------------
  |  Branch (703:38): [True: 102, False: 680]
  ------------------
  704|    782|                        if ((*vec).size() <= idx) (*vec).resize(idx + 1);
  ------------------
  |  Branch (704:29): [True: 778, False: 4]
  ------------------
  705|    782|                        (*vec)[idx] = pAsset_Root.accessors.Get(it->value.GetString());
  706|    782|                    }
  707|    900|                }
  708|    644|            }
  709|       |
  710|    846|            if (Value *indices = FindString(primitive, "indices")) {
  ------------------
  |  Branch (710:24): [True: 216, False: 630]
  ------------------
  711|    216|                prim.indices = pAsset_Root.accessors.Get(indices->GetString());
  712|    216|            }
  713|       |
  714|    846|            if (Value *material = FindString(primitive, "material")) {
  ------------------
  |  Branch (714:24): [True: 122, False: 724]
  ------------------
  715|    122|                prim.material = pAsset_Root.materials.Get(material->GetString());
  716|    122|            }
  717|    846|        }
  718|    824|    }
  719|       |
  720|       |    /****************** Mesh extensions ******************/
  721|    920|    Value *json_extensions = FindObject(pJSON_Object, "extensions");
  722|       |
  723|    920|    if (json_extensions == nullptr) goto mr_skip_extensions;
  ------------------
  |  Branch (723:9): [True: 698, False: 222]
  ------------------
  724|       |
  725|    222|#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
  726|    222|    for (Value::MemberIterator it_memb = json_extensions->MemberBegin(); it_memb != json_extensions->MemberEnd(); it_memb++) {
  ------------------
  |  Branch (726:74): [True: 0, False: 222]
  ------------------
  727|      0|        if (it_memb->name.GetString() == std::string("Open3DGC-compression")) {
  ------------------
  |  Branch (727:13): [True: 0, False: 0]
  ------------------
  728|       |            // Search for compressed data.
  729|       |            // Compressed data contain description of part of "buffer" which is encoded. This part must be decoded and
  730|       |            // new data will replace old encoded part by request. In fact \"compressedData\" is kind of "accessor" structure.
  731|      0|            Value *comp_data = FindObject(it_memb->value, "compressedData");
  732|       |
  733|      0|            if (comp_data == nullptr) throw DeadlyImportError("GLTF: \"Open3DGC-compression\" must has \"compressedData\".");
  ------------------
  |  Branch (733:17): [True: 0, False: 0]
  ------------------
  734|       |
  735|      0|            ASSIMP_LOG_INFO("GLTF: Decompressing Open3DGC data.");
  736|       |
  737|       |/************** Read data from JSON-document **************/
  738|      0|#define MESH_READ_COMPRESSEDDATA_MEMBER(pFieldName, pOut)                                   \
  739|      0|    if (!ReadMember(*comp_data, pFieldName, pOut)) {                                        \
  740|      0|        throw DeadlyImportError("GLTF: \"compressedData\" must has \"", pFieldName, "\"."); \
  741|      0|    }
  742|       |
  743|      0|            const char *mode_str;
  744|      0|            const char *type_str;
  745|      0|            ComponentType component_type;
  746|      0|            SCompression_Open3DGC *ext_o3dgc = new SCompression_Open3DGC;
  747|       |
  748|      0|            MESH_READ_COMPRESSEDDATA_MEMBER("buffer", ext_o3dgc->Buffer);
  ------------------
  |  |  739|      0|    if (!ReadMember(*comp_data, pFieldName, pOut)) {                                        \
  |  |  ------------------
  |  |  |  Branch (739:9): [True: 0, False: 0]
  |  |  ------------------
  |  |  740|      0|        throw DeadlyImportError("GLTF: \"compressedData\" must has \"", pFieldName, "\"."); \
  |  |  741|      0|    }
  ------------------
  749|      0|            MESH_READ_COMPRESSEDDATA_MEMBER("byteOffset", ext_o3dgc->Offset);
  ------------------
  |  |  739|      0|    if (!ReadMember(*comp_data, pFieldName, pOut)) {                                        \
  |  |  ------------------
  |  |  |  Branch (739:9): [True: 0, False: 0]
  |  |  ------------------
  |  |  740|      0|        throw DeadlyImportError("GLTF: \"compressedData\" must has \"", pFieldName, "\"."); \
  |  |  741|      0|    }
  ------------------
  750|      0|            MESH_READ_COMPRESSEDDATA_MEMBER("componentType", component_type);
  ------------------
  |  |  739|      0|    if (!ReadMember(*comp_data, pFieldName, pOut)) {                                        \
  |  |  ------------------
  |  |  |  Branch (739:9): [True: 0, False: 0]
  |  |  ------------------
  |  |  740|      0|        throw DeadlyImportError("GLTF: \"compressedData\" must has \"", pFieldName, "\"."); \
  |  |  741|      0|    }
  ------------------
  751|      0|            MESH_READ_COMPRESSEDDATA_MEMBER("type", type_str);
  ------------------
  |  |  739|      0|    if (!ReadMember(*comp_data, pFieldName, pOut)) {                                        \
  |  |  ------------------
  |  |  |  Branch (739:9): [True: 0, False: 0]
  |  |  ------------------
  |  |  740|      0|        throw DeadlyImportError("GLTF: \"compressedData\" must has \"", pFieldName, "\"."); \
  |  |  741|      0|    }
  ------------------
  752|      0|            MESH_READ_COMPRESSEDDATA_MEMBER("count", ext_o3dgc->Count);
  ------------------
  |  |  739|      0|    if (!ReadMember(*comp_data, pFieldName, pOut)) {                                        \
  |  |  ------------------
  |  |  |  Branch (739:9): [True: 0, False: 0]
  |  |  ------------------
  |  |  740|      0|        throw DeadlyImportError("GLTF: \"compressedData\" must has \"", pFieldName, "\"."); \
  |  |  741|      0|    }
  ------------------
  753|      0|            MESH_READ_COMPRESSEDDATA_MEMBER("mode", mode_str);
  ------------------
  |  |  739|      0|    if (!ReadMember(*comp_data, pFieldName, pOut)) {                                        \
  |  |  ------------------
  |  |  |  Branch (739:9): [True: 0, False: 0]
  |  |  ------------------
  |  |  740|      0|        throw DeadlyImportError("GLTF: \"compressedData\" must has \"", pFieldName, "\"."); \
  |  |  741|      0|    }
  ------------------
  754|      0|            MESH_READ_COMPRESSEDDATA_MEMBER("indicesCount", ext_o3dgc->IndicesCount);
  ------------------
  |  |  739|      0|    if (!ReadMember(*comp_data, pFieldName, pOut)) {                                        \
  |  |  ------------------
  |  |  |  Branch (739:9): [True: 0, False: 0]
  |  |  ------------------
  |  |  740|      0|        throw DeadlyImportError("GLTF: \"compressedData\" must has \"", pFieldName, "\"."); \
  |  |  741|      0|    }
  ------------------
  755|      0|            MESH_READ_COMPRESSEDDATA_MEMBER("verticesCount", ext_o3dgc->VerticesCount);
  ------------------
  |  |  739|      0|    if (!ReadMember(*comp_data, pFieldName, pOut)) {                                        \
  |  |  ------------------
  |  |  |  Branch (739:9): [True: 0, False: 0]
  |  |  ------------------
  |  |  740|      0|        throw DeadlyImportError("GLTF: \"compressedData\" must has \"", pFieldName, "\"."); \
  |  |  741|      0|    }
  ------------------
  756|       |
  757|      0|#undef MESH_READ_COMPRESSEDDATA_MEMBER
  758|       |
  759|       |            // Check some values
  760|      0|            if (strcmp(type_str, "SCALAR")) throw DeadlyImportError("GLTF: only \"SCALAR\" type is supported for compressed data.");
  ------------------
  |  Branch (760:17): [True: 0, False: 0]
  ------------------
  761|      0|            if (component_type != ComponentType_UNSIGNED_BYTE) throw DeadlyImportError("GLTF: only \"UNSIGNED_BYTE\" component type is supported for compressed data.");
  ------------------
  |  Branch (761:17): [True: 0, False: 0]
  ------------------
  762|       |
  763|       |            // Set read/write data mode.
  764|      0|            if (strcmp(mode_str, "binary") == 0)
  ------------------
  |  Branch (764:17): [True: 0, False: 0]
  ------------------
  765|      0|                ext_o3dgc->Binary = true;
  766|      0|            else if (strcmp(mode_str, "ascii") == 0)
  ------------------
  |  Branch (766:22): [True: 0, False: 0]
  ------------------
  767|      0|                ext_o3dgc->Binary = false;
  768|      0|            else
  769|      0|                throw DeadlyImportError("GLTF: for compressed data supported modes is: \"ascii\", \"binary\". Not the: \"", mode_str, "\".");
  770|       |
  771|       |            /************************ Decoding ************************/
  772|      0|            Decode_O3DGC(*ext_o3dgc, pAsset_Root);
  773|      0|            Extension.push_back(ext_o3dgc); // store info in mesh extensions list.
  774|      0|        } // if(it_memb->name.GetString() == "Open3DGC-compression")
  775|      0|        else {
  776|      0|            throw DeadlyImportError("GLTF: Unknown mesh extension: \"", it_memb->name.GetString(), "\".");
  777|      0|        }
  778|      0|    } // for(Value::MemberIterator it_memb = json_extensions->MemberBegin(); it_memb != json_extensions->MemberEnd(); json_extensions++)
  779|    222|#endif
  780|       |
  781|    698|mr_skip_extensions:
  782|       |
  783|    698|    return; // After label some operators must be present.
  784|    222|}
glTFImporter.cpp:_ZN4glTF12_GLOBAL__N_115GetAttribVectorERNS_4Mesh9PrimitiveEPKcRPNSt3__16vectorIN10glTFCommon3RefINS_8AccessorEEENS6_9allocatorISB_EEEERi:
  661|    900|inline bool GetAttribVector(Mesh::Primitive &p, const char *attr, Mesh::AccessorList *&v, int &pos) {
  662|    900|    if ((pos = Compare(attr, "POSITION"))) {
  ------------------
  |  Branch (662:9): [True: 496, False: 404]
  ------------------
  663|    496|        v = &(p.attributes.position);
  664|    496|    } else if ((pos = Compare(attr, "NORMAL"))) {
  ------------------
  |  Branch (664:16): [True: 172, False: 232]
  ------------------
  665|    172|        v = &(p.attributes.normal);
  666|    232|    } else if ((pos = Compare(attr, "TEXCOORD"))) {
  ------------------
  |  Branch (666:16): [True: 102, False: 130]
  ------------------
  667|    102|        v = &(p.attributes.texcoord);
  668|    130|    } else if ((pos = Compare(attr, "COLOR"))) {
  ------------------
  |  Branch (668:16): [True: 10, False: 120]
  ------------------
  669|     10|        v = &(p.attributes.color);
  670|    120|    } else if ((pos = Compare(attr, "JOINT"))) {
  ------------------
  |  Branch (670:16): [True: 2, False: 118]
  ------------------
  671|      2|        v = &(p.attributes.joint);
  672|    118|    } else if ((pos = Compare(attr, "JOINTMATRIX"))) {
  ------------------
  |  Branch (672:16): [True: 0, False: 118]
  ------------------
  673|      0|        v = &(p.attributes.jointmatrix);
  674|    118|    } else if ((pos = Compare(attr, "WEIGHT"))) {
  ------------------
  |  Branch (674:16): [True: 0, False: 118]
  ------------------
  675|      0|        v = &(p.attributes.weight);
  676|      0|    } else
  677|    118|        return false;
  678|    782|    return true;
  679|    900|}
glTFImporter.cpp:_ZN4glTF12_GLOBAL__N_17CompareILi9EEEiPKcRAT__S2_:
  657|  1.13k|inline int Compare(const char *attr, const char (&str)[N]) {
  658|  1.13k|    return (strncmp(attr, str, N - 1) == 0) ? N - 1 : 0;
  ------------------
  |  Branch (658:12): [True: 598, False: 534]
  ------------------
  659|  1.13k|}
glTFImporter.cpp:_ZN4glTF12_GLOBAL__N_17CompareILi7EEEiPKcRAT__S2_:
  657|    522|inline int Compare(const char *attr, const char (&str)[N]) {
  658|    522|    return (strncmp(attr, str, N - 1) == 0) ? N - 1 : 0;
  ------------------
  |  Branch (658:12): [True: 172, False: 350]
  ------------------
  659|    522|}
glTFImporter.cpp:_ZN4glTF12_GLOBAL__N_17CompareILi6EEEiPKcRAT__S2_:
  657|    250|inline int Compare(const char *attr, const char (&str)[N]) {
  658|    250|    return (strncmp(attr, str, N - 1) == 0) ? N - 1 : 0;
  ------------------
  |  Branch (658:12): [True: 12, False: 238]
  ------------------
  659|    250|}
glTFImporter.cpp:_ZN4glTF12_GLOBAL__N_17CompareILi12EEEiPKcRAT__S2_:
  657|    118|inline int Compare(const char *attr, const char (&str)[N]) {
  658|    118|    return (strncmp(attr, str, N - 1) == 0) ? N - 1 : 0;
  ------------------
  |  Branch (658:12): [True: 0, False: 118]
  ------------------
  659|    118|}
_ZN4glTF8LazyDictINS_8AccessorEE3GetEPKc:
  110|    998|Ref<T> LazyDict<T>::Get(const char *id) {
  111|    998|    id = T::TranslateId(mAsset, id);
  112|       |
  113|    998|    typename Dict::iterator it = mObjsById.find(id);
  114|    998|    if (it != mObjsById.end()) { // already created?
  ------------------
  |  Branch (114:9): [True: 104, False: 894]
  ------------------
  115|    104|        return Ref<T>(mObjs, it->second);
  116|    104|    }
  117|       |
  118|       |    // read it from the JSON object
  119|    894|    if (!mDict) {
  ------------------
  |  Branch (119:9): [True: 6, False: 888]
  ------------------
  120|      6|        throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\"");
  121|      6|    }
  122|       |
  123|    888|    Value::MemberIterator obj = mDict->FindMember(id);
  124|    888|    if (obj == mDict->MemberEnd()) {
  ------------------
  |  Branch (124:9): [True: 74, False: 814]
  ------------------
  125|     74|        throw DeadlyImportError("GLTF: Missing object with id \"", id, "\" in \"", mDictId, "\"");
  126|     74|    }
  127|    814|    if (!obj->value.IsObject()) {
  ------------------
  |  Branch (127:9): [True: 2, False: 812]
  ------------------
  128|      2|        throw DeadlyImportError("GLTF: Object with id \"", id, "\" is not a JSON object");
  129|      2|    }
  130|       |
  131|       |    // create an instance of the given type
  132|    812|    T *inst = new T();
  133|    812|    inst->id = id;
  134|    812|    ReadMember(obj->value, "name", inst->name);
  135|    812|    inst->Read(obj->value, mAsset);
  136|    812|    return Add(inst);
  137|    814|}
_ZN4glTF8Accessor4ReadERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEERNS_5AssetE:
  358|    812|inline void Accessor::Read(Value &obj, Asset &r) {
  359|    812|    const char *bufferViewId = MemberOrDefault<const char *>(obj, "bufferView", 0);
  360|    812|    if (bufferViewId) {
  ------------------
  |  Branch (360:9): [True: 714, False: 98]
  ------------------
  361|    714|        bufferView = r.bufferViews.Get(bufferViewId);
  362|    714|    }
  363|       |
  364|    812|    byteOffset = MemberOrDefault(obj, "byteOffset", 0u);
  365|    812|    byteStride = MemberOrDefault(obj, "byteStride", 0u);
  366|    812|    componentType = MemberOrDefault(obj, "componentType", ComponentType_BYTE);
  367|    812|    count = MemberOrDefault(obj, "count", 0u);
  368|       |
  369|    812|    const char *typestr;
  370|    812|    type = ReadMember(obj, "type", typestr) ? AttribType::FromString(typestr) : AttribType::SCALAR;
  ------------------
  |  Branch (370:12): [True: 730, False: 82]
  ------------------
  371|    812|}
_ZN4glTF8LazyDictINS_10BufferViewEE3GetEPKc:
  110|    714|Ref<T> LazyDict<T>::Get(const char *id) {
  111|    714|    id = T::TranslateId(mAsset, id);
  112|       |
  113|    714|    typename Dict::iterator it = mObjsById.find(id);
  114|    714|    if (it != mObjsById.end()) { // already created?
  ------------------
  |  Branch (114:9): [True: 246, False: 468]
  ------------------
  115|    246|        return Ref<T>(mObjs, it->second);
  116|    246|    }
  117|       |
  118|       |    // read it from the JSON object
  119|    468|    if (!mDict) {
  ------------------
  |  Branch (119:9): [True: 2, False: 466]
  ------------------
  120|      2|        throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\"");
  121|      2|    }
  122|       |
  123|    466|    Value::MemberIterator obj = mDict->FindMember(id);
  124|    466|    if (obj == mDict->MemberEnd()) {
  ------------------
  |  Branch (124:9): [True: 18, False: 448]
  ------------------
  125|     18|        throw DeadlyImportError("GLTF: Missing object with id \"", id, "\" in \"", mDictId, "\"");
  126|     18|    }
  127|    448|    if (!obj->value.IsObject()) {
  ------------------
  |  Branch (127:9): [True: 2, False: 446]
  ------------------
  128|      2|        throw DeadlyImportError("GLTF: Object with id \"", id, "\" is not a JSON object");
  129|      2|    }
  130|       |
  131|       |    // create an instance of the given type
  132|    446|    T *inst = new T();
  133|    446|    inst->id = id;
  134|    446|    ReadMember(obj->value, "name", inst->name);
  135|    446|    inst->Read(obj->value, mAsset);
  136|    446|    return Add(inst);
  137|    448|}
_ZN4glTF10BufferView4ReadERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEERNS_5AssetE:
  344|    446|inline void BufferView::Read(Value &obj, Asset &r) {
  345|    446|    const char *bufferId = MemberOrDefault<const char *>(obj, "buffer", 0);
  346|    446|    if (bufferId) {
  ------------------
  |  Branch (346:9): [True: 318, False: 128]
  ------------------
  347|    318|        buffer = r.buffers.Get(bufferId);
  348|    318|    }
  349|       |
  350|    446|    byteOffset = MemberOrDefault(obj, "byteOffset", 0u);
  351|    446|    byteLength = MemberOrDefault(obj, "byteLength", 0u);
  352|    446|}
_ZN4glTF8LazyDictINS_6BufferEE3GetEPKc:
  110|    318|Ref<T> LazyDict<T>::Get(const char *id) {
  111|    318|    id = T::TranslateId(mAsset, id);
  112|       |
  113|    318|    typename Dict::iterator it = mObjsById.find(id);
  114|    318|    if (it != mObjsById.end()) { // already created?
  ------------------
  |  Branch (114:9): [True: 106, False: 212]
  ------------------
  115|    106|        return Ref<T>(mObjs, it->second);
  116|    106|    }
  117|       |
  118|       |    // read it from the JSON object
  119|    212|    if (!mDict) {
  ------------------
  |  Branch (119:9): [True: 4, False: 208]
  ------------------
  120|      4|        throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\"");
  121|      4|    }
  122|       |
  123|    208|    Value::MemberIterator obj = mDict->FindMember(id);
  124|    208|    if (obj == mDict->MemberEnd()) {
  ------------------
  |  Branch (124:9): [True: 6, False: 202]
  ------------------
  125|      6|        throw DeadlyImportError("GLTF: Missing object with id \"", id, "\" in \"", mDictId, "\"");
  126|      6|    }
  127|    202|    if (!obj->value.IsObject()) {
  ------------------
  |  Branch (127:9): [True: 0, False: 202]
  ------------------
  128|      0|        throw DeadlyImportError("GLTF: Object with id \"", id, "\" is not a JSON object");
  129|      0|    }
  130|       |
  131|       |    // create an instance of the given type
  132|    202|    T *inst = new T();
  133|    202|    inst->id = id;
  134|    202|    ReadMember(obj->value, "name", inst->name);
  135|    202|    inst->Read(obj->value, mAsset);
  136|    202|    return Add(inst);
  137|    202|}
_ZN4glTF6Buffer11TranslateIdERNS_5AssetEPKc:
  171|    318|inline const char *Buffer::TranslateId(Asset &r, const char *id) {
  172|       |    // Compatibility with old spec
  173|    318|    if (r.extensionsUsed.KHR_binary_glTF && strcmp(id, "KHR_binary_glTF") == 0) {
  ------------------
  |  Branch (173:9): [True: 0, False: 318]
  |  Branch (173:45): [True: 0, False: 0]
  ------------------
  174|      0|        return "binary_glTF";
  175|      0|    }
  176|       |
  177|    318|    return id;
  178|    318|}
_ZN4glTF6Buffer4ReadERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEERNS_5AssetE:
  180|    202|inline void Buffer::Read(Value &obj, Asset &r) {
  181|    202|    size_t statedLength = MemberOrDefault<size_t>(obj, "byteLength", 0);
  182|    202|    byteLength = statedLength;
  183|       |
  184|    202|    Value *it = FindString(obj, "uri");
  185|    202|    if (!it) {
  ------------------
  |  Branch (185:9): [True: 28, False: 174]
  ------------------
  186|     28|        if (statedLength > 0) {
  ------------------
  |  Branch (186:13): [True: 2, False: 26]
  ------------------
  187|      2|            throw DeadlyImportError("GLTF: buffer with non-zero length missing the \"uri\" attribute");
  188|      2|        }
  189|     26|        return;
  190|     28|    }
  191|       |
  192|    174|    const char *uri = it->GetString();
  193|       |
  194|    174|    glTFCommon::Util::DataURI dataURI;
  195|    174|    if (ParseDataURI(uri, it->GetStringLength(), dataURI)) {
  ------------------
  |  Branch (195:9): [True: 6, False: 168]
  ------------------
  196|      6|        if (dataURI.base64) {
  ------------------
  |  Branch (196:13): [True: 0, False: 6]
  ------------------
  197|      0|            uint8_t *data = nullptr;
  198|      0|            this->byteLength = Base64::Decode(dataURI.data, dataURI.dataLength, data);
  199|      0|            this->mData.reset(data, std::default_delete<uint8_t[]>());
  200|       |
  201|      0|            if (statedLength > 0 && this->byteLength != statedLength) {
  ------------------
  |  Branch (201:17): [True: 0, False: 0]
  |  Branch (201:37): [True: 0, False: 0]
  ------------------
  202|      0|                throw DeadlyImportError("GLTF: buffer \"", id, "\", expected ", ai_to_string(statedLength),
  203|      0|                        " bytes, but found ", ai_to_string(dataURI.dataLength));
  204|      0|            }
  205|      6|        } else { // assume raw data
  206|      6|            if (statedLength != dataURI.dataLength) {
  ------------------
  |  Branch (206:17): [True: 6, False: 0]
  ------------------
  207|      6|                throw DeadlyImportError("GLTF: buffer \"", id, "\", expected ", ai_to_string(statedLength),
  208|      6|                        " bytes, but found ", ai_to_string(dataURI.dataLength));
  209|      6|            }
  210|       |
  211|      0|            this->mData.reset(new uint8_t[dataURI.dataLength], std::default_delete<uint8_t[]>());
  212|      0|            memcpy(this->mData.get(), dataURI.data, dataURI.dataLength);
  213|      0|        }
  214|    168|    } else { // Local file
  215|    168|        if (byteLength > 0) {
  ------------------
  |  Branch (215:13): [True: 24, False: 144]
  ------------------
  216|     24|            std::string dir = !r.mCurrentAssetDir.empty() ? (
  ------------------
  |  Branch (216:31): [True: 0, False: 24]
  ------------------
  217|      0|                                                                    r.mCurrentAssetDir.back() == '/' ?
  ------------------
  |  Branch (217:69): [True: 0, False: 0]
  ------------------
  218|      0|                                                                            r.mCurrentAssetDir :
  219|      0|                                                                            r.mCurrentAssetDir + '/') :
  220|     24|                                                            "";
  221|       |
  222|     24|            IOStream *file = r.OpenFile(dir + uri, "rb");
  223|     24|            if (file) {
  ------------------
  |  Branch (223:17): [True: 0, False: 24]
  ------------------
  224|      0|                bool ok = LoadFromStream(*file, byteLength);
  225|      0|                delete file;
  226|       |
  227|      0|                if (!ok)
  ------------------
  |  Branch (227:21): [True: 0, False: 0]
  ------------------
  228|      0|                    throw DeadlyImportError("GLTF: error while reading referenced file \"", uri, "\"");
  229|     24|            } else {
  230|     24|                throw DeadlyImportError("GLTF: could not open referenced file \"", uri, "\"");
  231|     24|            }
  232|     24|        }
  233|    168|    }
  234|    174|}
_ZN4glTF8LazyDictINS_10BufferViewEE3AddEPS1_:
  140|    404|Ref<T> LazyDict<T>::Add(T *obj) {
  141|    404|    unsigned int idx = unsigned(mObjs.size());
  142|    404|    mObjs.push_back(obj);
  143|    404|    mObjsById[obj->id] = idx;
  144|    404|    mAsset.mUsedIds[obj->id] = true;
  145|    404|    return Ref<T>(mObjs, idx);
  146|    404|}
_ZN4glTF8LazyDictINS_8AccessorEE3AddEPS1_:
  140|    748|Ref<T> LazyDict<T>::Add(T *obj) {
  141|    748|    unsigned int idx = unsigned(mObjs.size());
  142|    748|    mObjs.push_back(obj);
  143|    748|    mObjsById[obj->id] = idx;
  144|    748|    mAsset.mUsedIds[obj->id] = true;
  145|    748|    return Ref<T>(mObjs, idx);
  146|    748|}
_ZN4glTF8LazyDictINS_8MaterialEE3GetEPKc:
  110|    122|Ref<T> LazyDict<T>::Get(const char *id) {
  111|    122|    id = T::TranslateId(mAsset, id);
  112|       |
  113|    122|    typename Dict::iterator it = mObjsById.find(id);
  114|    122|    if (it != mObjsById.end()) { // already created?
  ------------------
  |  Branch (114:9): [True: 2, False: 120]
  ------------------
  115|      2|        return Ref<T>(mObjs, it->second);
  116|      2|    }
  117|       |
  118|       |    // read it from the JSON object
  119|    120|    if (!mDict) {
  ------------------
  |  Branch (119:9): [True: 2, False: 118]
  ------------------
  120|      2|        throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\"");
  121|      2|    }
  122|       |
  123|    118|    Value::MemberIterator obj = mDict->FindMember(id);
  124|    118|    if (obj == mDict->MemberEnd()) {
  ------------------
  |  Branch (124:9): [True: 6, False: 112]
  ------------------
  125|      6|        throw DeadlyImportError("GLTF: Missing object with id \"", id, "\" in \"", mDictId, "\"");
  126|      6|    }
  127|    112|    if (!obj->value.IsObject()) {
  ------------------
  |  Branch (127:9): [True: 0, False: 112]
  ------------------
  128|      0|        throw DeadlyImportError("GLTF: Object with id \"", id, "\" is not a JSON object");
  129|      0|    }
  130|       |
  131|       |    // create an instance of the given type
  132|    112|    T *inst = new T();
  133|    112|    inst->id = id;
  134|    112|    ReadMember(obj->value, "name", inst->name);
  135|    112|    inst->Read(obj->value, mAsset);
  136|    112|    return Add(inst);
  137|    112|}
_ZN4glTF8Material11SetDefaultsEv:
  640|    224|inline void Material::SetDefaults() {
  641|    224|    SetVector(ambient.color, 0, 0, 0, 1);
  642|    224|    SetVector(diffuse.color, 0, 0, 0, 1);
  643|    224|    SetVector(specular.color, 0, 0, 0, 1);
  644|    224|    SetVector(emission.color, 0, 0, 0, 1);
  645|       |
  646|    224|    doubleSided = false;
  647|    224|    transparent = false;
  648|    224|    transparency = 1.0;
  649|    224|    shininess = 0.0;
  650|       |
  651|    224|    technique = Technique_undefined;
  652|    224|}
glTFImporter.cpp:_ZN4glTF12_GLOBAL__N_19SetVectorERA4_fffff:
  632|    896|void SetVector(vec4 &v, float x, float y, float z, float w) {
  633|    896|    v[0] = x;
  634|    896|    v[1] = y;
  635|    896|    v[2] = z;
  636|    896|    v[3] = w;
  637|    896|}
_ZN4glTF8Material4ReadERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEERNS_5AssetE:
  589|    112|inline void Material::Read(Value &material, Asset &r) {
  590|    112|    SetDefaults();
  591|       |
  592|    112|    if (Value *values = FindObject(material, "values")) {
  ------------------
  |  Branch (592:16): [True: 110, False: 2]
  ------------------
  593|    110|        ReadMaterialProperty(r, *values, "ambient", this->ambient);
  594|    110|        ReadMaterialProperty(r, *values, "diffuse", this->diffuse);
  595|    110|        ReadMaterialProperty(r, *values, "specular", this->specular);
  596|       |
  597|    110|        ReadMember(*values, "transparency", transparency);
  598|    110|        ReadMember(*values, "shininess", shininess);
  599|    110|    }
  600|       |
  601|    112|    if (Value *extensions = FindObject(material, "extensions")) {
  ------------------
  |  Branch (601:16): [True: 0, False: 112]
  ------------------
  602|      0|        if (r.extensionsUsed.KHR_materials_common) {
  ------------------
  |  Branch (602:13): [True: 0, False: 0]
  ------------------
  603|      0|            if (Value *ext = FindObject(*extensions, "KHR_materials_common")) {
  ------------------
  |  Branch (603:24): [True: 0, False: 0]
  ------------------
  604|      0|                if (Value *tnq = FindString(*ext, "technique")) {
  ------------------
  |  Branch (604:28): [True: 0, False: 0]
  ------------------
  605|      0|                    const char *t = tnq->GetString();
  606|      0|                    if (strcmp(t, "BLINN") == 0)
  ------------------
  |  Branch (606:25): [True: 0, False: 0]
  ------------------
  607|      0|                        technique = Technique_BLINN;
  608|      0|                    else if (strcmp(t, "PHONG") == 0)
  ------------------
  |  Branch (608:30): [True: 0, False: 0]
  ------------------
  609|      0|                        technique = Technique_PHONG;
  610|      0|                    else if (strcmp(t, "LAMBERT") == 0)
  ------------------
  |  Branch (610:30): [True: 0, False: 0]
  ------------------
  611|      0|                        technique = Technique_LAMBERT;
  612|      0|                    else if (strcmp(t, "CONSTANT") == 0)
  ------------------
  |  Branch (612:30): [True: 0, False: 0]
  ------------------
  613|      0|                        technique = Technique_CONSTANT;
  614|      0|                }
  615|       |
  616|      0|                if (Value *values = FindObject(*ext, "values")) {
  ------------------
  |  Branch (616:28): [True: 0, False: 0]
  ------------------
  617|      0|                    ReadMaterialProperty(r, *values, "ambient", this->ambient);
  618|      0|                    ReadMaterialProperty(r, *values, "diffuse", this->diffuse);
  619|      0|                    ReadMaterialProperty(r, *values, "specular", this->specular);
  620|       |
  621|      0|                    ReadMember(*values, "doubleSided", doubleSided);
  622|      0|                    ReadMember(*values, "transparent", transparent);
  623|      0|                    ReadMember(*values, "transparency", transparency);
  624|      0|                    ReadMember(*values, "shininess", shininess);
  625|      0|                }
  626|      0|            }
  627|      0|        }
  628|      0|    }
  629|    112|}
glTFImporter.cpp:_ZN4glTF12_GLOBAL__N_120ReadMaterialPropertyERNS_5AssetERN9rapidjson12GenericValueINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEEEEPKcRNS_11TexPropertyE:
  578|    262|inline void ReadMaterialProperty(Asset &r, Value &vals, const char *propName, TexProperty &out) {
  579|    262|    if (Value *prop = FindMember(vals, propName)) {
  ------------------
  |  Branch (579:16): [True: 148, False: 114]
  ------------------
  580|    148|        if (prop->IsString()) {
  ------------------
  |  Branch (580:13): [True: 92, False: 56]
  ------------------
  581|     92|            out.texture = r.textures.Get(prop->GetString());
  582|     92|        } else {
  583|     56|            ReadValue(*prop, out.color);
  584|     56|        }
  585|    148|    }
  586|    262|}
_ZN4glTF8LazyDictINS_7TextureEE3GetEPKc:
  110|     92|Ref<T> LazyDict<T>::Get(const char *id) {
  111|     92|    id = T::TranslateId(mAsset, id);
  112|       |
  113|     92|    typename Dict::iterator it = mObjsById.find(id);
  114|     92|    if (it != mObjsById.end()) { // already created?
  ------------------
  |  Branch (114:9): [True: 2, False: 90]
  ------------------
  115|      2|        return Ref<T>(mObjs, it->second);
  116|      2|    }
  117|       |
  118|       |    // read it from the JSON object
  119|     90|    if (!mDict) {
  ------------------
  |  Branch (119:9): [True: 2, False: 88]
  ------------------
  120|      2|        throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\"");
  121|      2|    }
  122|       |
  123|     88|    Value::MemberIterator obj = mDict->FindMember(id);
  124|     88|    if (obj == mDict->MemberEnd()) {
  ------------------
  |  Branch (124:9): [True: 8, False: 80]
  ------------------
  125|      8|        throw DeadlyImportError("GLTF: Missing object with id \"", id, "\" in \"", mDictId, "\"");
  126|      8|    }
  127|     80|    if (!obj->value.IsObject()) {
  ------------------
  |  Branch (127:9): [True: 0, False: 80]
  ------------------
  128|      0|        throw DeadlyImportError("GLTF: Object with id \"", id, "\" is not a JSON object");
  129|      0|    }
  130|       |
  131|       |    // create an instance of the given type
  132|     80|    T *inst = new T();
  133|     80|    inst->id = id;
  134|     80|    ReadMember(obj->value, "name", inst->name);
  135|     80|    inst->Read(obj->value, mAsset);
  136|     80|    return Add(inst);
  137|     80|}
_ZN4glTF7Texture4ReadERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEERNS_5AssetE:
  565|     80|inline void Texture::Read(Value &obj, Asset &r) {
  566|     80|    const char *sourcestr;
  567|     80|    if (ReadMember(obj, "source", sourcestr)) {
  ------------------
  |  Branch (567:9): [True: 74, False: 6]
  ------------------
  568|     74|        source = r.images.Get(sourcestr);
  569|     74|    }
  570|       |
  571|     80|    const char *samplerstr;
  572|     80|    if (ReadMember(obj, "sampler", samplerstr)) {
  ------------------
  |  Branch (572:9): [True: 30, False: 50]
  ------------------
  573|     30|        sampler = r.samplers.Get(samplerstr);
  574|     30|    }
  575|     80|}
_ZN4glTF8LazyDictINS_5ImageEE3GetEPKc:
  110|     74|Ref<T> LazyDict<T>::Get(const char *id) {
  111|     74|    id = T::TranslateId(mAsset, id);
  112|       |
  113|     74|    typename Dict::iterator it = mObjsById.find(id);
  114|     74|    if (it != mObjsById.end()) { // already created?
  ------------------
  |  Branch (114:9): [True: 0, False: 74]
  ------------------
  115|      0|        return Ref<T>(mObjs, it->second);
  116|      0|    }
  117|       |
  118|       |    // read it from the JSON object
  119|     74|    if (!mDict) {
  ------------------
  |  Branch (119:9): [True: 2, False: 72]
  ------------------
  120|      2|        throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\"");
  121|      2|    }
  122|       |
  123|     72|    Value::MemberIterator obj = mDict->FindMember(id);
  124|     72|    if (obj == mDict->MemberEnd()) {
  ------------------
  |  Branch (124:9): [True: 44, False: 28]
  ------------------
  125|     44|        throw DeadlyImportError("GLTF: Missing object with id \"", id, "\" in \"", mDictId, "\"");
  126|     44|    }
  127|     28|    if (!obj->value.IsObject()) {
  ------------------
  |  Branch (127:9): [True: 0, False: 28]
  ------------------
  128|      0|        throw DeadlyImportError("GLTF: Object with id \"", id, "\" is not a JSON object");
  129|      0|    }
  130|       |
  131|       |    // create an instance of the given type
  132|     28|    T *inst = new T();
  133|     28|    inst->id = id;
  134|     28|    ReadMember(obj->value, "name", inst->name);
  135|     28|    inst->Read(obj->value, mAsset);
  136|     28|    return Add(inst);
  137|     28|}
_ZN4glTF5ImageC2Ev:
  480|     28|        width(0), height(0), mDataLength(0) {
  481|     28|}
_ZN4glTF5Image4ReadERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEERNS_5AssetE:
  483|     28|inline void Image::Read(Value &obj, Asset &r) {
  484|       |    // Check for extensions first (to detect binary embedded data)
  485|     28|    if (Value *extensions = FindObject(obj, "extensions")) {
  ------------------
  |  Branch (485:16): [True: 0, False: 28]
  ------------------
  486|      0|        if (r.extensionsUsed.KHR_binary_glTF) {
  ------------------
  |  Branch (486:13): [True: 0, False: 0]
  ------------------
  487|      0|            if (Value *ext = FindObject(*extensions, "KHR_binary_glTF")) {
  ------------------
  |  Branch (487:24): [True: 0, False: 0]
  ------------------
  488|       |
  489|      0|                width = MemberOrDefault(*ext, "width", 0);
  490|      0|                height = MemberOrDefault(*ext, "height", 0);
  491|       |
  492|      0|                ReadMember(*ext, "mimeType", mimeType);
  493|       |
  494|      0|                const char *bufferViewId;
  495|      0|                if (ReadMember(*ext, "bufferView", bufferViewId)) {
  ------------------
  |  Branch (495:21): [True: 0, False: 0]
  ------------------
  496|      0|                    Ref<BufferView> bv = r.bufferViews.Get(bufferViewId);
  497|      0|                    if (bv) {
  ------------------
  |  Branch (497:25): [True: 0, False: 0]
  ------------------
  498|      0|                        mDataLength = bv->byteLength;
  499|      0|                        mData.reset(new uint8_t[mDataLength]);
  500|      0|                        memcpy(mData.get(), bv->buffer->GetPointer() + bv->byteOffset, mDataLength);
  501|      0|                    }
  502|      0|                }
  503|      0|            }
  504|      0|        }
  505|      0|    }
  506|       |
  507|     28|    if (!mDataLength) {
  ------------------
  |  Branch (507:9): [True: 28, False: 0]
  ------------------
  508|     28|        Value *curUri = FindString(obj, "uri");
  509|     28|        if (nullptr != curUri) {
  ------------------
  |  Branch (509:13): [True: 24, False: 4]
  ------------------
  510|     24|            const char *uristr = curUri->GetString();
  511|       |
  512|     24|            glTFCommon::Util::DataURI dataURI;
  513|     24|            if (ParseDataURI(uristr, curUri->GetStringLength(), dataURI)) {
  ------------------
  |  Branch (513:17): [True: 0, False: 24]
  ------------------
  514|      0|                mimeType = dataURI.mediaType;
  515|      0|                if (dataURI.base64) {
  ------------------
  |  Branch (515:21): [True: 0, False: 0]
  ------------------
  516|      0|                    uint8_t *ptr = nullptr;
  517|      0|                    mDataLength = Base64::Decode(dataURI.data, dataURI.dataLength, ptr);
  518|      0|                    mData.reset(ptr);
  519|      0|                }
  520|     24|            } else {
  521|     24|                this->uri = uristr;
  522|     24|            }
  523|     24|        }
  524|     28|    }
  525|     28|}
_ZN4glTF8LazyDictINS_5ImageEE3AddEPS1_:
  140|     28|Ref<T> LazyDict<T>::Add(T *obj) {
  141|     28|    unsigned int idx = unsigned(mObjs.size());
  142|     28|    mObjs.push_back(obj);
  143|     28|    mObjsById[obj->id] = idx;
  144|     28|    mAsset.mUsedIds[obj->id] = true;
  145|     28|    return Ref<T>(mObjs, idx);
  146|     28|}
_ZN4glTF8LazyDictINS_7SamplerEE3GetEPKc:
  110|     30|Ref<T> LazyDict<T>::Get(const char *id) {
  111|     30|    id = T::TranslateId(mAsset, id);
  112|       |
  113|     30|    typename Dict::iterator it = mObjsById.find(id);
  114|     30|    if (it != mObjsById.end()) { // already created?
  ------------------
  |  Branch (114:9): [True: 0, False: 30]
  ------------------
  115|      0|        return Ref<T>(mObjs, it->second);
  116|      0|    }
  117|       |
  118|       |    // read it from the JSON object
  119|     30|    if (!mDict) {
  ------------------
  |  Branch (119:9): [True: 6, False: 24]
  ------------------
  120|      6|        throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\"");
  121|      6|    }
  122|       |
  123|     24|    Value::MemberIterator obj = mDict->FindMember(id);
  124|     24|    if (obj == mDict->MemberEnd()) {
  ------------------
  |  Branch (124:9): [True: 6, False: 18]
  ------------------
  125|      6|        throw DeadlyImportError("GLTF: Missing object with id \"", id, "\" in \"", mDictId, "\"");
  126|      6|    }
  127|     18|    if (!obj->value.IsObject()) {
  ------------------
  |  Branch (127:9): [True: 0, False: 18]
  ------------------
  128|      0|        throw DeadlyImportError("GLTF: Object with id \"", id, "\" is not a JSON object");
  129|      0|    }
  130|       |
  131|       |    // create an instance of the given type
  132|     18|    T *inst = new T();
  133|     18|    inst->id = id;
  134|     18|    ReadMember(obj->value, "name", inst->name);
  135|     18|    inst->Read(obj->value, mAsset);
  136|     18|    return Add(inst);
  137|     18|}
_ZN4glTF7Sampler4ReadERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEERNS_5AssetE:
  549|     18|inline void Sampler::Read(Value &obj, Asset & /*r*/) {
  550|     18|    SetDefaults();
  551|       |
  552|     18|    ReadMember(obj, "magFilter", magFilter);
  553|     18|    ReadMember(obj, "minFilter", minFilter);
  554|     18|    ReadMember(obj, "wrapS", wrapS);
  555|     18|    ReadMember(obj, "wrapT", wrapT);
  556|     18|}
_ZN4glTF7Sampler11SetDefaultsEv:
  558|     18|inline void Sampler::SetDefaults() {
  559|     18|    magFilter = SamplerMagFilter_Linear;
  560|     18|    minFilter = SamplerMinFilter_Linear;
  561|     18|    wrapS = SamplerWrap_Repeat;
  562|     18|    wrapT = SamplerWrap_Repeat;
  563|     18|}
_ZN4glTF8LazyDictINS_7SamplerEE3AddEPS1_:
  140|     18|Ref<T> LazyDict<T>::Add(T *obj) {
  141|     18|    unsigned int idx = unsigned(mObjs.size());
  142|     18|    mObjs.push_back(obj);
  143|     18|    mObjsById[obj->id] = idx;
  144|     18|    mAsset.mUsedIds[obj->id] = true;
  145|     18|    return Ref<T>(mObjs, idx);
  146|     18|}
_ZN4glTF8LazyDictINS_7TextureEE3AddEPS1_:
  140|     22|Ref<T> LazyDict<T>::Add(T *obj) {
  141|     22|    unsigned int idx = unsigned(mObjs.size());
  142|     22|    mObjs.push_back(obj);
  143|     22|    mObjsById[obj->id] = idx;
  144|     22|    mAsset.mUsedIds[obj->id] = true;
  145|     22|    return Ref<T>(mObjs, idx);
  146|     22|}
_ZN4glTF8LazyDictINS_8MaterialEE3AddEPS1_:
  140|     44|Ref<T> LazyDict<T>::Add(T *obj) {
  141|     44|    unsigned int idx = unsigned(mObjs.size());
  142|     44|    mObjs.push_back(obj);
  143|     44|    mObjsById[obj->id] = idx;
  144|     44|    mAsset.mUsedIds[obj->id] = true;
  145|     44|    return Ref<T>(mObjs, idx);
  146|     44|}
_ZN4glTF8LazyDictINS_4MeshEE3AddEPS1_:
  140|    698|Ref<T> LazyDict<T>::Add(T *obj) {
  141|    698|    unsigned int idx = unsigned(mObjs.size());
  142|    698|    mObjs.push_back(obj);
  143|    698|    mObjsById[obj->id] = idx;
  144|    698|    mAsset.mUsedIds[obj->id] = true;
  145|    698|    return Ref<T>(mObjs, idx);
  146|    698|}
_ZN4glTF8LazyDictINS_4NodeEE3AddEPS1_:
  140|  1.13k|Ref<T> LazyDict<T>::Add(T *obj) {
  141|  1.13k|    unsigned int idx = unsigned(mObjs.size());
  142|  1.13k|    mObjs.push_back(obj);
  143|  1.13k|    mObjsById[obj->id] = idx;
  144|  1.13k|    mAsset.mUsedIds[obj->id] = true;
  145|  1.13k|    return Ref<T>(mObjs, idx);
  146|  1.13k|}
_ZN4glTF8LazyDictINS_5SceneEE3AddEPS1_:
  140|     92|Ref<T> LazyDict<T>::Add(T *obj) {
  141|     92|    unsigned int idx = unsigned(mObjs.size());
  142|     92|    mObjs.push_back(obj);
  143|     92|    mObjsById[obj->id] = idx;
  144|     92|    mAsset.mUsedIds[obj->id] = true;
  145|     92|    return Ref<T>(mObjs, idx);
  146|     92|}
_ZN4glTF8Accessor10GetPointerEv:
  385|     28|inline uint8_t *Accessor::GetPointer() {
  386|     28|    if (!bufferView || !bufferView->buffer) return nullptr;
  ------------------
  |  Branch (386:9): [True: 26, False: 2]
  |  Branch (386:24): [True: 2, False: 0]
  ------------------
  387|      0|    uint8_t *basePtr = bufferView->buffer->GetPointer();
  388|      0|    if (!basePtr) return nullptr;
  ------------------
  |  Branch (388:9): [True: 0, False: 0]
  ------------------
  389|       |
  390|      0|    size_t offset = byteOffset + bufferView->byteOffset;
  391|       |
  392|       |    // Check if region is encoded.
  393|      0|    if (bufferView->buffer->EncodedRegion_Current != nullptr) {
  ------------------
  |  Branch (393:9): [True: 0, False: 0]
  ------------------
  394|      0|        const size_t begin = bufferView->buffer->EncodedRegion_Current->Offset;
  395|      0|        const size_t end = begin + bufferView->buffer->EncodedRegion_Current->DecodedData_Length;
  396|       |
  397|      0|        if ((offset >= begin) && (offset < end))
  ------------------
  |  Branch (397:13): [True: 0, False: 0]
  |  Branch (397:34): [True: 0, False: 0]
  ------------------
  398|      0|            return &bufferView->buffer->EncodedRegion_Current->DecodedData[offset - begin];
  399|      0|    }
  400|       |
  401|      0|    return basePtr + offset;
  402|      0|}
_ZN4glTF8Accessor11ExtractDataI10aiVector3tIfEEEbRPT_:
  425|     28|bool Accessor::ExtractData(T *&outData) {
  426|     28|    uint8_t *data = GetPointer();
  427|     28|    if (!data) return false;
  ------------------
  |  Branch (427:9): [True: 28, False: 0]
  ------------------
  428|       |
  429|      0|    const size_t elemSize = GetElementSize();
  430|      0|    const size_t totalSize = elemSize * count;
  431|       |
  432|      0|    const size_t stride = byteStride ? byteStride : elemSize;
  ------------------
  |  Branch (432:27): [True: 0, False: 0]
  ------------------
  433|       |
  434|      0|    const size_t targetElemSize = sizeof(T);
  435|      0|    ai_assert(elemSize <= targetElemSize);
  436|       |
  437|      0|    ai_assert(count * stride <= bufferView->byteLength);
  438|       |
  439|      0|    outData = new T[count];
  440|      0|    if (stride == elemSize && targetElemSize == elemSize) {
  ------------------
  |  Branch (440:9): [True: 0, False: 0]
  |  Branch (440:31): [True: 0, False: 0]
  ------------------
  441|      0|        memcpy(outData, data, totalSize);
  442|      0|    } else {
  443|      0|        for (size_t i = 0; i < count; ++i) {
  ------------------
  |  Branch (443:28): [True: 0, False: 0]
  ------------------
  444|      0|            memcpy(outData + i, data + i * stride, elemSize);
  445|      0|        }
  446|      0|    }
  447|       |
  448|      0|    return true;
  449|     28|}

_ZN6Assimp12glTFImporterC2Ev:
  148|  5.13k|        mScene(nullptr) {
  149|       |    // empty
  150|  5.13k|}
_ZNK6Assimp12glTFImporter7GetInfoEv:
  152|  15.7k|const aiImporterDesc *glTFImporter::GetInfo() const {
  153|  15.7k|    return &desc;
  154|  15.7k|}
_ZNK6Assimp12glTFImporter7CanReadERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEPNS_8IOSystemEb:
  156|  6.40k|bool glTFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /* checkSig */) const {
  157|  6.40k|    Asset asset(pIOHandler);
  158|  6.40k|    try {
  159|  6.40k|        asset.Load(pFile,
  160|  6.40k|                   CheckMagicToken(
  161|  6.40k|                       pIOHandler, pFile, AI_GLB_MAGIC_NUMBER, 1, 0,
  ------------------
  |  |  127|  6.40k|#define AI_GLB_MAGIC_NUMBER "glTF"
  ------------------
  162|  6.40k|                       static_cast<unsigned int>(strlen(AI_GLB_MAGIC_NUMBER))));
  ------------------
  |  |  127|  6.40k|#define AI_GLB_MAGIC_NUMBER "glTF"
  ------------------
  163|  6.40k|        return asset.asset;
  164|  6.40k|    } catch (...) {
  165|  3.81k|        return false;
  166|  3.81k|    }
  167|  6.40k|}
_ZNK6Assimp12glTFImporter15ImportMaterialsERN4glTF5AssetE:
  169|    331|void glTFImporter::ImportMaterials(Asset &r) const {
  170|    331|    mScene->mNumMaterials = r.materials.Size();
  171|    331|    if (mScene->mNumMaterials == 0) {
  ------------------
  |  Branch (171:9): [True: 323, False: 8]
  ------------------
  172|    323|        createDefaultMaterial(mScene);
  173|    323|        return;
  174|    323|    }
  175|       |
  176|      8|    mScene->mMaterials = new aiMaterial *[mScene->mNumMaterials];
  177|     16|    for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) {
  ------------------
  |  Branch (177:30): [True: 8, False: 8]
  ------------------
  178|      8|        aiMaterial *aimat = mScene->mMaterials[i] = new aiMaterial();
  179|       |
  180|      8|        Material &mat = r.materials[i];
  181|      8|        aiString str(mat.id);
  182|      8|        aimat->AddProperty(&str, AI_MATKEY_NAME);
  183|       |
  184|      8|        SetMaterialColorProperty(embeddedTexIdxs, r, mat.ambient, aimat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT);
  185|      8|        SetMaterialColorProperty(embeddedTexIdxs, r, mat.diffuse, aimat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE);
  186|      8|        SetMaterialColorProperty(embeddedTexIdxs, r, mat.specular, aimat, aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR);
  187|      8|        SetMaterialColorProperty(embeddedTexIdxs, r, mat.emission, aimat, aiTextureType_EMISSIVE, AI_MATKEY_COLOR_EMISSIVE);
  188|       |
  189|      8|        aimat->AddProperty(&mat.doubleSided, 1, AI_MATKEY_TWOSIDED);
  190|       |
  191|      8|        if (mat.transparent && (mat.transparency != 1.0f)) {
  ------------------
  |  Branch (191:13): [True: 0, False: 8]
  |  Branch (191:32): [True: 0, False: 0]
  ------------------
  192|      0|            aimat->AddProperty(&mat.transparency, 1, AI_MATKEY_OPACITY);
  193|      0|        }
  194|       |
  195|      8|        if (mat.shininess > 0.f) {
  ------------------
  |  Branch (195:13): [True: 8, False: 0]
  ------------------
  196|       |            aimat->AddProperty(&mat.shininess, 1, AI_MATKEY_SHININESS);
  197|      8|        }
  198|      8|    }
  199|      8|}
_ZN6Assimp12glTFImporter12ImportMeshesERN4glTF5AssetE:
  201|    331|void glTFImporter::ImportMeshes(Asset &r) {
  202|    331|    std::vector<aiMesh *> meshes;
  203|       |
  204|    331|    unsigned int k = 0;
  205|    331|    meshOffsets.clear();
  206|       |
  207|    367|    for (unsigned int m = 0; m < r.meshes.Size(); ++m) {
  ------------------
  |  Branch (207:30): [True: 36, False: 331]
  ------------------
  208|     36|        Mesh &mesh = r.meshes[m];
  209|       |
  210|       |        // Check if mesh extensions is used
  211|     36|        if (mesh.Extension.size() > 0) {
  ------------------
  |  Branch (211:13): [True: 0, False: 36]
  ------------------
  212|      0|#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
  213|      0|            for (Mesh::SExtension *cur_ext : mesh.Extension) {
  ------------------
  |  Branch (213:44): [True: 0, False: 0]
  ------------------
  214|      0|                if (cur_ext->Type == Mesh::SExtension::EType::Compression_Open3DGC) {
  ------------------
  |  Branch (214:21): [True: 0, False: 0]
  ------------------
  215|       |                    // Limitations for meshes when using Open3DGC-compression.
  216|       |                    // It's a current limitation of sp... Specification have not this part still - about mesh compression. Why only one primitive?
  217|       |                    // Because glTF is very flexibly. But in fact it ugly flexible. Every primitive can has own set of accessors and accessors can
  218|       |                    // point to a-a-a-a-any part of buffer (through bufferview of course) and even to another buffer. We know that "Open3DGC-compression"
  219|       |                    // is applicable only to part of buffer. As we can't guaranty continuity of the data for decoder, we will limit quantity of primitives.
  220|       |                    // Yes indices, coordinates etc. still can br stored in different buffers, but with current specification it's a exporter problem.
  221|       |                    // Also primitive can has only one of "POSITION", "NORMAL" and less then "AI_MAX_NUMBER_OF_TEXTURECOORDS" of "TEXCOORD". All accessor
  222|       |                    // of primitive must point to one continuous region of the buffer.
  223|      0|                    if (mesh.primitives.size() > 2) throw DeadlyImportError("GLTF: When using Open3DGC compression then only one primitive per mesh are allowed.");
  ------------------
  |  Branch (223:25): [True: 0, False: 0]
  ------------------
  224|       |
  225|      0|                    Mesh::SCompression_Open3DGC *o3dgc_ext = (Mesh::SCompression_Open3DGC *)cur_ext;
  226|      0|                    Ref<Buffer> buf = r.buffers.Get(o3dgc_ext->Buffer);
  227|       |
  228|      0|                    buf->EncodedRegion_SetCurrent(mesh.id);
  229|      0|                } else
  230|      0|                {
  231|      0|                    throw DeadlyImportError("GLTF: Can not import mesh: unknown mesh extension (code: \"", ai_to_string(cur_ext->Type),
  232|      0|                                            "\"), only Open3DGC is supported.");
  233|      0|                }
  234|      0|            }
  235|      0|#endif
  236|      0|        } // if(mesh.Extension.size() > 0)
  237|       |
  238|     36|        meshOffsets.push_back(k);
  239|     36|        k += static_cast<unsigned>(mesh.primitives.size());
  240|       |
  241|     67|        for (unsigned int p = 0; p < mesh.primitives.size(); ++p) {
  ------------------
  |  Branch (241:34): [True: 31, False: 36]
  ------------------
  242|     31|            auto &[mode, attributes, indices, material] = mesh.primitives[p];
  243|       |
  244|     31|            aiMesh *aim = new aiMesh();
  245|     31|            meshes.push_back(aim);
  246|       |
  247|     31|            aim->mName = mesh.id;
  248|     31|            if (mesh.primitives.size() > 1) {
  ------------------
  |  Branch (248:17): [True: 12, False: 19]
  ------------------
  249|     12|                ai_uint32 &len = aim->mName.length;
  250|     12|                aim->mName.data[len] = '-';
  251|     12|                len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(AI_MAXLEN - len - 1), p);
  252|     12|            }
  253|       |
  254|     31|            switch (mode) {
  ------------------
  |  Branch (254:21): [True: 30, False: 1]
  ------------------
  255|      0|            case PrimitiveMode_POINTS:
  ------------------
  |  Branch (255:13): [True: 0, False: 31]
  ------------------
  256|      0|                aim->mPrimitiveTypes |= aiPrimitiveType_POINT;
  257|      0|                break;
  258|       |
  259|      2|            case PrimitiveMode_LINES:
  ------------------
  |  Branch (259:13): [True: 2, False: 29]
  ------------------
  260|      2|            case PrimitiveMode_LINE_LOOP:
  ------------------
  |  Branch (260:13): [True: 0, False: 31]
  ------------------
  261|      2|            case PrimitiveMode_LINE_STRIP:
  ------------------
  |  Branch (261:13): [True: 0, False: 31]
  ------------------
  262|      2|                aim->mPrimitiveTypes |= aiPrimitiveType_LINE;
  263|      2|                break;
  264|       |
  265|     28|            case PrimitiveMode_TRIANGLES:
  ------------------
  |  Branch (265:13): [True: 28, False: 3]
  ------------------
  266|     28|            case PrimitiveMode_TRIANGLE_STRIP:
  ------------------
  |  Branch (266:13): [True: 0, False: 31]
  ------------------
  267|     28|            case PrimitiveMode_TRIANGLE_FAN:
  ------------------
  |  Branch (267:13): [True: 0, False: 31]
  ------------------
  268|     28|                aim->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
  269|     28|                break;
  270|     31|            }
  271|       |
  272|     31|            Mesh::Primitive::Attributes &attr = attributes;
  273|       |
  274|     31|            if (attr.position.size() > 0 && attr.position[0]) {
  ------------------
  |  Branch (274:17): [True: 12, False: 19]
  |  Branch (274:45): [True: 12, False: 0]
  ------------------
  275|     12|                aim->mNumVertices = attr.position[0]->count;
  276|     12|                attr.position[0]->ExtractData(aim->mVertices);
  277|     12|            }
  278|       |
  279|     31|            if (attr.normal.size() > 0 && attr.normal[0]) attr.normal[0]->ExtractData(aim->mNormals);
  ------------------
  |  Branch (279:17): [True: 16, False: 15]
  |  Branch (279:43): [True: 16, False: 0]
  ------------------
  280|       |
  281|     31|            for (size_t tc = 0; tc < attr.texcoord.size() && tc < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) {
  ------------------
  |  Branch (281:33): [True: 0, False: 31]
  |  Branch (281:62): [True: 0, False: 0]
  ------------------
  282|      0|                attr.texcoord[tc]->ExtractData(aim->mTextureCoords[tc]);
  283|      0|                aim->mNumUVComponents[tc] = attr.texcoord[tc]->GetNumComponents();
  284|       |
  285|      0|                aiVector3D *values = aim->mTextureCoords[tc];
  286|      0|                for (unsigned int i = 0; i < aim->mNumVertices; ++i) {
  ------------------
  |  Branch (286:42): [True: 0, False: 0]
  ------------------
  287|      0|                    values[i].y = 1 - values[i].y; // Flip Y coords
  288|      0|                }
  289|      0|            }
  290|       |
  291|     31|            aiFace *faces = nullptr;
  292|     31|            unsigned int nFaces = 0;
  293|       |
  294|     31|            if (indices) {
  ------------------
  |  Branch (294:17): [True: 0, False: 31]
  ------------------
  295|      0|                unsigned int count = indices->count;
  296|       |
  297|      0|                Accessor::Indexer data = indices->GetIndexer();
  298|      0|                ai_assert(data.IsValid());
  299|       |
  300|      0|                switch (mode) {
  ------------------
  |  Branch (300:25): [True: 0, False: 0]
  ------------------
  301|      0|                case PrimitiveMode_POINTS: {
  ------------------
  |  Branch (301:17): [True: 0, False: 0]
  ------------------
  302|      0|                    nFaces = count;
  303|      0|                    faces = new aiFace[nFaces];
  304|      0|                    for (unsigned int i = 0; i < count; ++i) {
  ------------------
  |  Branch (304:46): [True: 0, False: 0]
  ------------------
  305|      0|                        SetFace(faces[i], data.GetUInt(i));
  306|      0|                    }
  307|      0|                    break;
  308|      0|                }
  309|       |
  310|      0|                case PrimitiveMode_LINES: {
  ------------------
  |  Branch (310:17): [True: 0, False: 0]
  ------------------
  311|      0|                    nFaces = count / 2;
  312|      0|                    if (nFaces * 2 != count) {
  ------------------
  |  Branch (312:25): [True: 0, False: 0]
  ------------------
  313|      0|                        ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped.");
  314|      0|                        count = nFaces * 2;
  315|      0|                    }
  316|      0|                    faces = new aiFace[nFaces];
  317|      0|                    for (unsigned int i = 0; i < count; i += 2) {
  ------------------
  |  Branch (317:46): [True: 0, False: 0]
  ------------------
  318|      0|                        SetFace(faces[i / 2], data.GetUInt(i), data.GetUInt(i + 1));
  319|      0|                    }
  320|      0|                    break;
  321|      0|                }
  322|       |
  323|      0|                case PrimitiveMode_LINE_LOOP:
  ------------------
  |  Branch (323:17): [True: 0, False: 0]
  ------------------
  324|      0|                case PrimitiveMode_LINE_STRIP: {
  ------------------
  |  Branch (324:17): [True: 0, False: 0]
  ------------------
  325|      0|                    nFaces = count - ((mode == PrimitiveMode_LINE_STRIP) ? 1 : 0);
  ------------------
  |  Branch (325:39): [True: 0, False: 0]
  ------------------
  326|      0|                    faces = new aiFace[nFaces];
  327|      0|                    SetFace(faces[0], data.GetUInt(0), data.GetUInt(1));
  328|      0|                    for (unsigned int i = 2; i < count; ++i) {
  ------------------
  |  Branch (328:46): [True: 0, False: 0]
  ------------------
  329|      0|                        SetFace(faces[i - 1], faces[i - 2].mIndices[1], data.GetUInt(i));
  330|      0|                    }
  331|      0|                    if (mode == PrimitiveMode_LINE_LOOP) { // close the loop
  ------------------
  |  Branch (331:25): [True: 0, False: 0]
  ------------------
  332|      0|                        SetFace(faces[count - 1], faces[count - 2].mIndices[1], faces[0].mIndices[0]);
  333|      0|                    }
  334|      0|                    break;
  335|      0|                }
  336|       |
  337|      0|                case PrimitiveMode_TRIANGLES: {
  ------------------
  |  Branch (337:17): [True: 0, False: 0]
  ------------------
  338|      0|                    nFaces = count / 3;
  339|      0|                    if (nFaces * 3 != count) {
  ------------------
  |  Branch (339:25): [True: 0, False: 0]
  ------------------
  340|      0|                        ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped.");
  341|      0|                        count = nFaces * 3;
  342|      0|                    }
  343|      0|                    faces = new aiFace[nFaces];
  344|      0|                    for (unsigned int i = 0; i < count; i += 3) {
  ------------------
  |  Branch (344:46): [True: 0, False: 0]
  ------------------
  345|      0|                        SetFace(faces[i / 3], data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2));
  346|      0|                    }
  347|      0|                    break;
  348|      0|                }
  349|      0|                case PrimitiveMode_TRIANGLE_STRIP: {
  ------------------
  |  Branch (349:17): [True: 0, False: 0]
  ------------------
  350|      0|                    nFaces = count - 2;
  351|      0|                    faces = new aiFace[nFaces];
  352|      0|                    SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2));
  353|      0|                    for (unsigned int i = 3; i < count; ++i) {
  ------------------
  |  Branch (353:46): [True: 0, False: 0]
  ------------------
  354|      0|                        SetFace(faces[i - 2], faces[i - 1].mIndices[1], faces[i - 1].mIndices[2], data.GetUInt(i));
  355|      0|                    }
  356|      0|                    break;
  357|      0|                }
  358|      0|                case PrimitiveMode_TRIANGLE_FAN:
  ------------------
  |  Branch (358:17): [True: 0, False: 0]
  ------------------
  359|      0|                    nFaces = count - 2;
  360|      0|                    faces = new aiFace[nFaces];
  361|      0|                    SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2));
  362|      0|                    for (unsigned int i = 3; i < count; ++i) {
  ------------------
  |  Branch (362:46): [True: 0, False: 0]
  ------------------
  363|      0|                        SetFace(faces[i - 2], faces[0].mIndices[0], faces[i - 1].mIndices[2], data.GetUInt(i));
  364|      0|                    }
  365|      0|                    break;
  366|      0|                }
  367|     31|            } else { // no indices provided so directly generate from counts
  368|       |
  369|       |                // use the already determined count as it includes checks
  370|     31|                unsigned int count = aim->mNumVertices;
  371|       |
  372|     31|                switch (mode) {
  ------------------
  |  Branch (372:25): [True: 30, False: 1]
  ------------------
  373|      0|                case PrimitiveMode_POINTS: {
  ------------------
  |  Branch (373:17): [True: 0, False: 31]
  ------------------
  374|      0|                    nFaces = count;
  375|      0|                    faces = new aiFace[nFaces];
  376|      0|                    for (unsigned int i = 0; i < count; ++i) {
  ------------------
  |  Branch (376:46): [True: 0, False: 0]
  ------------------
  377|      0|                        SetFace(faces[i], i);
  378|      0|                    }
  379|      0|                    break;
  380|      0|                }
  381|       |
  382|      2|                case PrimitiveMode_LINES: {
  ------------------
  |  Branch (382:17): [True: 2, False: 29]
  ------------------
  383|      2|                    nFaces = count / 2;
  384|      2|                    if (nFaces * 2 != count) {
  ------------------
  |  Branch (384:25): [True: 1, False: 1]
  ------------------
  385|      1|                        ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped.");
  386|      1|                        count = nFaces * 2;
  387|      1|                    }
  388|      2|                    faces = new aiFace[nFaces];
  389|    147|                    for (unsigned int i = 0; i < count; i += 2) {
  ------------------
  |  Branch (389:46): [True: 145, False: 2]
  ------------------
  390|    145|                        SetFace(faces[i / 2], i, i + 1);
  391|    145|                    }
  392|      2|                    break;
  393|      0|                }
  394|       |
  395|      0|                case PrimitiveMode_LINE_LOOP:
  ------------------
  |  Branch (395:17): [True: 0, False: 31]
  ------------------
  396|      0|                case PrimitiveMode_LINE_STRIP: {
  ------------------
  |  Branch (396:17): [True: 0, False: 31]
  ------------------
  397|      0|                    nFaces = count - ((mode == PrimitiveMode_LINE_STRIP) ? 1 : 0);
  ------------------
  |  Branch (397:39): [True: 0, False: 0]
  ------------------
  398|      0|                    faces = new aiFace[nFaces];
  399|      0|                    SetFace(faces[0], 0, 1);
  400|      0|                    for (unsigned int i = 2; i < count; ++i) {
  ------------------
  |  Branch (400:46): [True: 0, False: 0]
  ------------------
  401|      0|                        SetFace(faces[i - 1], faces[i - 2].mIndices[1], i);
  402|      0|                    }
  403|      0|                    if (mode == PrimitiveMode_LINE_LOOP) { // close the loop
  ------------------
  |  Branch (403:25): [True: 0, False: 0]
  ------------------
  404|      0|                        SetFace(faces[count - 1], faces[count - 2].mIndices[1], faces[0].mIndices[0]);
  405|      0|                    }
  406|      0|                    break;
  407|      0|                }
  408|       |
  409|     28|                case PrimitiveMode_TRIANGLES: {
  ------------------
  |  Branch (409:17): [True: 28, False: 3]
  ------------------
  410|     28|                    nFaces = count / 3;
  411|     28|                    if (nFaces * 3 != count) {
  ------------------
  |  Branch (411:25): [True: 7, False: 21]
  ------------------
  412|      7|                        ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped.");
  413|      7|                        count = nFaces * 3;
  414|      7|                    }
  415|     28|                    faces = new aiFace[nFaces];
  416|    924|                    for (unsigned int i = 0; i < count; i += 3) {
  ------------------
  |  Branch (416:46): [True: 896, False: 28]
  ------------------
  417|    896|                        SetFace(faces[i / 3], i, i + 1, i + 2);
  418|    896|                    }
  419|     28|                    break;
  420|      0|                }
  421|      0|                case PrimitiveMode_TRIANGLE_STRIP: {
  ------------------
  |  Branch (421:17): [True: 0, False: 31]
  ------------------
  422|      0|                    nFaces = count - 2;
  423|      0|                    faces = new aiFace[nFaces];
  424|      0|                    SetFace(faces[0], 0, 1, 2);
  425|      0|                    for (unsigned int i = 3; i < count; ++i) {
  ------------------
  |  Branch (425:46): [True: 0, False: 0]
  ------------------
  426|      0|                        SetFace(faces[i - 2], faces[i - 1].mIndices[1], faces[i - 1].mIndices[2], i);
  427|      0|                    }
  428|      0|                    break;
  429|      0|                }
  430|      0|                case PrimitiveMode_TRIANGLE_FAN:
  ------------------
  |  Branch (430:17): [True: 0, False: 31]
  ------------------
  431|      0|                    nFaces = count - 2;
  432|      0|                    faces = new aiFace[nFaces];
  433|      0|                    SetFace(faces[0], 0, 1, 2);
  434|      0|                    for (unsigned int i = 3; i < count; ++i) {
  ------------------
  |  Branch (434:46): [True: 0, False: 0]
  ------------------
  435|      0|                        SetFace(faces[i - 2], faces[0].mIndices[0], faces[i - 1].mIndices[2], i);
  436|      0|                    }
  437|      0|                    break;
  438|     31|                }
  439|     31|            }
  440|       |
  441|     31|            if (faces) {
  ------------------
  |  Branch (441:17): [True: 30, False: 1]
  ------------------
  442|     30|                aim->mFaces = faces;
  443|     30|                aim->mNumFaces = nFaces;
  444|     30|                const bool validRes = CheckValidFacesIndices(faces, nFaces, aim->mNumVertices);
  445|     30|                if (!validRes) {
  ------------------
  |  Branch (445:21): [True: 0, False: 30]
  ------------------
  446|      0|                    ai_assert(validRes);
  447|      0|                    ASSIMP_LOG_WARN("Invalid number of faces detected.");
  448|      0|                }
  449|     30|            }
  450|       |
  451|     31|            if (material) {
  ------------------
  |  Branch (451:17): [True: 8, False: 23]
  ------------------
  452|      8|                aim->mMaterialIndex = material.GetIndex();
  453|      8|            }
  454|     31|        }
  455|     36|    }
  456|       |
  457|    331|    meshOffsets.push_back(k);
  458|       |
  459|    331|    CopyVector(meshes, mScene->mMeshes, mScene->mNumMeshes);
  460|    331|}
_ZNK6Assimp12glTFImporter13ImportCamerasERN4glTF5AssetE:
  462|    331|void glTFImporter::ImportCameras(Asset &r) const {
  463|    331|    if (!r.cameras.Size()) {
  ------------------
  |  Branch (463:9): [True: 331, False: 0]
  ------------------
  464|    331|        return;
  465|    331|    }
  466|       |
  467|      0|    mScene->mNumCameras = r.cameras.Size();
  468|      0|    mScene->mCameras = new aiCamera *[r.cameras.Size()];
  469|      0|    for (size_t i = 0; i < r.cameras.Size(); ++i) {
  ------------------
  |  Branch (469:24): [True: 0, False: 0]
  ------------------
  470|      0|        const Camera &cam = r.cameras[i];
  471|      0|        mScene->mCameras[i] = new aiCamera();
  472|      0|        const auto aiCameraPtr = mScene->mCameras[i];
  473|      0|        if (cam.type == Camera::Perspective) {
  ------------------
  |  Branch (473:13): [True: 0, False: 0]
  ------------------
  474|      0|            aiCameraPtr->mAspect = cam.perspective.aspectRatio;
  475|      0|            aiCameraPtr->mHorizontalFOV = cam.perspective.yfov * ((aiCameraPtr->mAspect == 0.f) ? 1.f : aiCameraPtr->mAspect);
  ------------------
  |  Branch (475:67): [True: 0, False: 0]
  ------------------
  476|      0|            aiCameraPtr->mClipPlaneFar = cam.perspective.zfar;
  477|      0|            aiCameraPtr->mClipPlaneNear = cam.perspective.znear;
  478|      0|        } else {
  479|      0|            aiCameraPtr->mClipPlaneFar = cam.ortographic.zfar;
  480|      0|            aiCameraPtr->mClipPlaneNear = cam.ortographic.znear;
  481|      0|            aiCameraPtr->mHorizontalFOV = 0.0;
  482|      0|            aiCameraPtr->mAspect = 1.0f;
  483|      0|            if (0.f != cam.ortographic.ymag) {
  ------------------
  |  Branch (483:17): [True: 0, False: 0]
  ------------------
  484|      0|                aiCameraPtr->mAspect = cam.ortographic.xmag / cam.ortographic.ymag;
  485|      0|            }
  486|      0|        }
  487|      0|    }
  488|      0|}
_ZNK6Assimp12glTFImporter12ImportLightsERN4glTF5AssetE:
  490|    331|void glTFImporter::ImportLights(Asset &r) const {
  491|    331|    if (!r.lights.Size()) {
  ------------------
  |  Branch (491:9): [True: 331, False: 0]
  ------------------
  492|    331|        return;
  493|    331|    }
  494|       |
  495|      0|    mScene->mNumLights = r.lights.Size();
  496|      0|    mScene->mLights = new aiLight *[r.lights.Size()];
  497|       |
  498|      0|    for (size_t i = 0; i < r.lights.Size(); ++i) {
  ------------------
  |  Branch (498:24): [True: 0, False: 0]
  ------------------
  499|      0|        Light &l = r.lights[i];
  500|       |
  501|      0|        aiLight *ail = mScene->mLights[i] = new aiLight();
  502|       |
  503|      0|        switch (l.type) {
  504|      0|        case Light::Type_directional:
  ------------------
  |  Branch (504:9): [True: 0, False: 0]
  ------------------
  505|      0|            ail->mType = aiLightSource_DIRECTIONAL;
  506|      0|            break;
  507|       |
  508|      0|        case Light::Type_spot:
  ------------------
  |  Branch (508:9): [True: 0, False: 0]
  ------------------
  509|      0|            ail->mType = aiLightSource_SPOT;
  510|      0|            break;
  511|       |
  512|      0|        case Light::Type_ambient:
  ------------------
  |  Branch (512:9): [True: 0, False: 0]
  ------------------
  513|      0|            ail->mType = aiLightSource_AMBIENT;
  514|      0|            break;
  515|       |
  516|      0|        default: // Light::Type_point
  ------------------
  |  Branch (516:9): [True: 0, False: 0]
  ------------------
  517|      0|            ail->mType = aiLightSource_POINT;
  518|      0|            break;
  519|      0|        }
  520|       |
  521|      0|        CopyValue(l.color, ail->mColorAmbient);
  522|      0|        CopyValue(l.color, ail->mColorDiffuse);
  523|      0|        CopyValue(l.color, ail->mColorSpecular);
  524|       |
  525|      0|        ail->mAngleOuterCone = l.falloffAngle;
  526|      0|        ail->mAngleInnerCone = l.falloffAngle * (1.0f - 1.0f / (1.0f + l.falloffExponent)); 
  527|       |
  528|      0|        ail->mAttenuationConstant = l.constantAttenuation;
  529|      0|        ail->mAttenuationLinear = l.linearAttenuation;
  530|      0|        ail->mAttenuationQuadratic = l.quadraticAttenuation;
  531|      0|    }
  532|      0|}
_Z10ImportNodeP7aiSceneRN4glTF5AssetERNSt3__16vectorIjNS4_9allocatorIjEEEERN10glTFCommon3RefINS1_4NodeEEE:
  534|    141|aiNode *ImportNode(aiScene *pScene, Asset &r, std::vector<unsigned int> &meshOffsets, Ref<Node> &ptr) {
  535|    141|    Node &node = *ptr;
  536|       |
  537|    141|    aiNode *ainode = new aiNode(node.id);
  538|       |
  539|    141|    if (!node.children.empty()) {
  ------------------
  |  Branch (539:9): [True: 40, False: 101]
  ------------------
  540|     40|        ainode->mNumChildren = static_cast<unsigned>(node.children.size());
  541|     40|        ainode->mChildren = new aiNode *[ainode->mNumChildren];
  542|       |
  543|    123|        for (unsigned int i = 0; i < ainode->mNumChildren; ++i) {
  ------------------
  |  Branch (543:34): [True: 83, False: 40]
  ------------------
  544|     83|            aiNode *child = ImportNode(pScene, r, meshOffsets, node.children[i]);
  545|     83|            child->mParent = ainode;
  546|     83|            ainode->mChildren[i] = child;
  547|     83|        }
  548|     40|    }
  549|       |
  550|    141|    aiMatrix4x4 &matrix = ainode->mTransformation;
  551|    141|    if (node.matrix.isPresent) {
  ------------------
  |  Branch (551:9): [True: 93, False: 48]
  ------------------
  552|     93|        CopyValue(node.matrix.value, matrix);
  553|     93|    } else {
  554|     48|        if (node.translation.isPresent) {
  ------------------
  |  Branch (554:13): [True: 13, False: 35]
  ------------------
  555|     13|            aiVector3D trans;
  556|     13|            CopyValue(node.translation.value, trans);
  557|     13|            aiMatrix4x4 t;
  558|     13|            aiMatrix4x4::Translation(trans, t);
  559|     13|            matrix = t * matrix;
  560|     13|        }
  561|       |
  562|     48|        if (node.scale.isPresent) {
  ------------------
  |  Branch (562:13): [True: 5, False: 43]
  ------------------
  563|      5|            aiVector3D scal(1.f);
  564|      5|            CopyValue(node.scale.value, scal);
  565|      5|            aiMatrix4x4 s;
  566|      5|            aiMatrix4x4::Scaling(scal, s);
  567|      5|            matrix = s * matrix;
  568|      5|        }
  569|       |
  570|     48|        if (node.rotation.isPresent) {
  ------------------
  |  Branch (570:13): [True: 5, False: 43]
  ------------------
  571|      5|            aiQuaternion rot;
  572|      5|            CopyValue(node.rotation.value, rot);
  573|      5|            matrix = aiMatrix4x4(rot.GetMatrix()) * matrix;
  574|      5|        }
  575|     48|    }
  576|       |
  577|    141|    if (!node.meshes.empty()) {
  ------------------
  |  Branch (577:9): [True: 74, False: 67]
  ------------------
  578|     74|        int count = 0;
  579|    148|        for (size_t i = 0; i < node.meshes.size(); ++i) {
  ------------------
  |  Branch (579:28): [True: 74, False: 74]
  ------------------
  580|     74|            const int idx = node.meshes[i].GetIndex();
  581|     74|            count += meshOffsets[idx + 1] - meshOffsets[idx];
  582|     74|        }
  583|       |
  584|     74|        ainode->mNumMeshes = count;
  585|     74|        ainode->mMeshes = new unsigned int[count];
  586|       |
  587|     74|        int k = 0;
  588|    148|        for (size_t i = 0; i < node.meshes.size(); ++i) {
  ------------------
  |  Branch (588:28): [True: 74, False: 74]
  ------------------
  589|     74|            const int idx = node.meshes[i].GetIndex();
  590|    141|            for (unsigned int j = meshOffsets[idx]; j < meshOffsets[idx + 1]; ++j, ++k) {
  ------------------
  |  Branch (590:53): [True: 67, False: 74]
  ------------------
  591|     67|                ainode->mMeshes[k] = j;
  592|     67|            }
  593|     74|        }
  594|     74|    }
  595|       |
  596|    141|    if (node.camera) {
  ------------------
  |  Branch (596:9): [True: 0, False: 141]
  ------------------
  597|      0|        pScene->mCameras[node.camera.GetIndex()]->mName = ainode->mName;
  598|      0|    }
  599|       |
  600|    141|    if (node.light) {
  ------------------
  |  Branch (600:9): [True: 0, False: 141]
  ------------------
  601|      0|        pScene->mLights[node.light.GetIndex()]->mName = ainode->mName;
  602|      0|    }
  603|       |
  604|    141|    return ainode;
  605|    141|}
_ZN6Assimp12glTFImporter11ImportNodesERN4glTF5AssetE:
  607|    331|void glTFImporter::ImportNodes(Asset &r) {
  608|    331|    if (!r.scene) {
  ------------------
  |  Branch (608:9): [True: 285, False: 46]
  ------------------
  609|    285|        return;
  610|    285|    }
  611|       |
  612|     46|    std::vector<Ref<Node>> rootNodes = r.scene->nodes;
  613|       |
  614|       |    // The root nodes
  615|     46|    if (auto numRootNodes = static_cast<unsigned>(rootNodes.size()); numRootNodes == 1) { // a single root node: use it
  ------------------
  |  Branch (615:70): [True: 34, False: 12]
  ------------------
  616|     34|        mScene->mRootNode = ImportNode(mScene, r, meshOffsets, rootNodes[0]);
  617|     34|    } else if (numRootNodes > 1) { // more than one root node: create a fake root
  ------------------
  |  Branch (617:16): [True: 6, False: 6]
  ------------------
  618|      6|        aiNode *root = new aiNode("ROOT");
  619|      6|        root->mChildren = new aiNode *[numRootNodes];
  620|     30|        for (unsigned int i = 0; i < numRootNodes; ++i) {
  ------------------
  |  Branch (620:34): [True: 24, False: 6]
  ------------------
  621|     24|            aiNode *node = ImportNode(mScene, r, meshOffsets, rootNodes[i]);
  622|     24|            node->mParent = root;
  623|     24|            root->mChildren[root->mNumChildren++] = node;
  624|     24|        }
  625|      6|        mScene->mRootNode = root;
  626|      6|    }
  627|     46|}
_ZN6Assimp12glTFImporter22ImportEmbeddedTexturesERN4glTF5AssetE:
  629|    331|void glTFImporter::ImportEmbeddedTextures(Asset &r) {
  630|    331|    embeddedTexIdxs.resize(r.images.Size(), -1);
  631|       |
  632|    331|    int numEmbeddedTexs = 0;
  633|    331|    for (size_t i = 0; i < r.images.Size(); ++i) {
  ------------------
  |  Branch (633:24): [True: 0, False: 331]
  ------------------
  634|      0|        if (r.images[i].HasData())
  ------------------
  |  Branch (634:13): [True: 0, False: 0]
  ------------------
  635|      0|            numEmbeddedTexs += 1;
  636|      0|    }
  637|       |
  638|    331|    if (numEmbeddedTexs == 0) {
  ------------------
  |  Branch (638:9): [True: 331, False: 0]
  ------------------
  639|    331|        return;
  640|    331|    }
  641|       |
  642|      0|    mScene->mTextures = new aiTexture *[numEmbeddedTexs];
  643|       |
  644|       |    // Add the embedded textures
  645|      0|    for (size_t i = 0; i < r.images.Size(); ++i) {
  ------------------
  |  Branch (645:24): [True: 0, False: 0]
  ------------------
  646|      0|        Image &img = r.images[i];
  647|      0|        if (!img.HasData()) continue;
  ------------------
  |  Branch (647:13): [True: 0, False: 0]
  ------------------
  648|       |
  649|      0|        int idx = mScene->mNumTextures++;
  650|      0|        embeddedTexIdxs[i] = idx;
  651|       |
  652|      0|        aiTexture *tex = mScene->mTextures[idx] = new aiTexture();
  653|       |
  654|      0|        const size_t length = img.GetDataLength();
  655|      0|        void *data = img.StealData();
  656|       |
  657|      0|        tex->mFilename = img.name;
  658|      0|        tex->mWidth = static_cast<unsigned int>(length);
  659|      0|        tex->mHeight = 0;
  660|      0|        tex->pcData = static_cast<aiTexel *>(data);
  661|       |
  662|      0|        if (!img.mimeType.empty()) {
  ------------------
  |  Branch (662:13): [True: 0, False: 0]
  ------------------
  663|      0|            if (const char *ext = strchr(img.mimeType.c_str(), '/') + 1) {
  ------------------
  |  Branch (663:29): [True: 0, False: 0]
  ------------------
  664|      0|                if (strncmp(ext, "jpeg", 4) == 0) {
  ------------------
  |  Branch (664:21): [True: 0, False: 0]
  ------------------
  665|      0|                    ext = "jpg";
  666|      0|                }
  667|       |
  668|      0|                tex->achFormatHint[3] = '\0';
  669|      0|                size_t len = strlen(ext);
  670|      0|                if (len > 3) len = 3;
  ------------------
  |  Branch (670:21): [True: 0, False: 0]
  ------------------
  671|      0|                memcpy(tex->achFormatHint, ext, len);
  672|      0|            }
  673|      0|        }
  674|      0|    }
  675|      0|}
_ZNK6Assimp12glTFImporter20ImportCommonMetadataERKN4glTF5AssetE:
  677|    331|void glTFImporter::ImportCommonMetadata(const Asset &a) const {
  678|    331|    ai_assert(mScene->mMetaData == nullptr);
  679|       |
  680|    331|    const bool hasVersion = !a.asset.version.empty();
  681|    331|    const bool hasGenerator = !a.asset.generator.empty();
  682|    331|    const bool hasCopyright = !a.asset.copyright.empty();
  683|    331|    if (hasVersion || hasGenerator || hasCopyright) {
  ------------------
  |  Branch (683:9): [True: 331, False: 0]
  |  Branch (683:23): [True: 0, False: 0]
  |  Branch (683:39): [True: 0, False: 0]
  ------------------
  684|    331|        mScene->mMetaData = new aiMetadata;
  685|    331|        if (hasVersion) {
  ------------------
  |  Branch (685:13): [True: 331, False: 0]
  ------------------
  686|    331|            mScene->mMetaData->Add(AI_METADATA_SOURCE_FORMAT_VERSION, aiString(a.asset.version));
  687|    331|        }
  688|    331|        if (hasGenerator) {
  ------------------
  |  Branch (688:13): [True: 64, False: 267]
  ------------------
  689|     64|            mScene->mMetaData->Add(AI_METADATA_SOURCE_GENERATOR, aiString(a.asset.generator));
  690|     64|        }
  691|    331|        if (hasCopyright) {
  ------------------
  |  Branch (691:13): [True: 0, False: 331]
  ------------------
  692|       |            mScene->mMetaData->Add(AI_METADATA_SOURCE_COPYRIGHT, aiString(a.asset.copyright));
  693|      0|        }
  694|    331|    }
  695|    331|}
_ZN6Assimp12glTFImporter14InternReadFileERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP7aiScenePNS_8IOSystemE:
  697|    331|void glTFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
  698|       |    // clean all member arrays
  699|    331|    meshOffsets.clear();
  700|    331|    embeddedTexIdxs.clear();
  701|       |
  702|    331|    this->mScene = pScene;
  703|       |
  704|       |    // read the asset file
  705|    331|    Asset asset(pIOHandler);
  706|    331|    asset.Load(pFile,
  707|    331|               CheckMagicToken(
  708|    331|                   pIOHandler, pFile, AI_GLB_MAGIC_NUMBER, 1, 0,
  ------------------
  |  |  127|    331|#define AI_GLB_MAGIC_NUMBER "glTF"
  ------------------
  709|    331|                   static_cast<unsigned int>(strlen(AI_GLB_MAGIC_NUMBER))));
  ------------------
  |  |  127|    331|#define AI_GLB_MAGIC_NUMBER "glTF"
  ------------------
  710|       |
  711|       |    //
  712|       |    // Copy the data out
  713|       |    //
  714|       |
  715|    331|    ImportEmbeddedTextures(asset);
  716|    331|    ImportMaterials(asset);
  717|       |
  718|    331|    ImportMeshes(asset);
  719|       |
  720|    331|    ImportCameras(asset);
  721|    331|    ImportLights(asset);
  722|       |
  723|    331|    ImportNodes(asset);
  724|    331|    ImportCommonMetadata(asset);
  725|       |
  726|    331|    if (pScene->mNumMeshes == 0) {
  ------------------
  |  Branch (726:9): [True: 309, False: 22]
  ------------------
  727|       |        pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
  728|    309|    }
  729|    331|}
glTFImporter.cpp:_ZN12_GLOBAL__N_121createDefaultMaterialEP7aiScene:
  135|    323|    void createDefaultMaterial(aiScene *scene) {
  136|    323|        if (scene == nullptr) {
  ------------------
  |  Branch (136:13): [True: 0, False: 323]
  ------------------
  137|      0|            return;
  138|      0|        }
  139|    323|        scene->mNumMaterials = 1;
  140|    323|        scene->mMaterials = nullptr;
  141|    323|        scene->mMaterials = new aiMaterial *[1];
  142|    323|        scene->mMaterials[0] = new aiMaterial();
  143|    323|    }
glTFImporter.cpp:_ZN12_GLOBAL__N_124SetMaterialColorPropertyERKNSt3__16vectorIiNS0_9allocatorIiEEEERN4glTF5AssetENS7_11TexPropertyEP10aiMaterial13aiTextureTypePKcjj:
   82|     32|            aiTextureType texType, const char *pKey, unsigned int type, unsigned int idx) {
   83|     32|        if (prop.texture) {
  ------------------
  |  Branch (83:13): [True: 0, False: 32]
  ------------------
   84|      0|            if (prop.texture->source) {
  ------------------
  |  Branch (84:17): [True: 0, False: 0]
  ------------------
   85|      0|                aiString uri(prop.texture->source->uri);
   86|       |
   87|      0|                if (const int texIdx = embeddedTexIdxs[prop.texture->source.GetIndex()]; texIdx != -1) { // embedded
  ------------------
  |  Branch (87:90): [True: 0, False: 0]
  ------------------
   88|       |                    // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture)
   89|      0|                    uri.data[0] = '*';
   90|      0|                    uri.length = 1 + ASSIMP_itoa10(uri.data + 1, AI_MAXLEN - 1, texIdx);
   91|      0|                }
   92|       |
   93|      0|                mat->AddProperty(&uri, _AI_MATKEY_TEXTURE_BASE, texType, 0);
   94|      0|            }
   95|      0|            return;
   96|      0|        }
   97|       |
   98|     32|        aiColor4D col;
   99|     32|        CopyValue(prop.color, col);
  100|     32|        mat->AddProperty(&col, 1, pKey, type, idx);
  101|     32|    }
glTFImporter.cpp:_ZN12_GLOBAL__N_17SetFaceER6aiFaceii:
  109|    145|    void SetFace(aiFace &face, int a, int b) {
  110|    145|        face.mNumIndices = 2;
  111|    145|        face.mIndices = new unsigned int[2];
  112|    145|        face.mIndices[0] = a;
  113|    145|        face.mIndices[1] = b;
  114|    145|    }
glTFImporter.cpp:_ZN12_GLOBAL__N_17SetFaceER6aiFaceiii:
  116|    896|    void SetFace(aiFace &face, int a, int b, int c) {
  117|    896|        face.mNumIndices = 3;
  118|    896|        face.mIndices = new unsigned int[3];
  119|    896|        face.mIndices[0] = a;
  120|    896|        face.mIndices[1] = b;
  121|    896|        face.mIndices[2] = c;
  122|    896|    }
glTFImporter.cpp:_ZN12_GLOBAL__N_122CheckValidFacesIndicesEPK6aiFacejj:
  124|     30|    bool CheckValidFacesIndices(const aiFace *faces, unsigned nFaces, unsigned nVerts) {
  125|  1.07k|        for (unsigned i = 0; i < nFaces; ++i) {
  ------------------
  |  Branch (125:30): [True: 1.04k, False: 30]
  ------------------
  126|  4.01k|            for (unsigned j = 0; j < faces[i].mNumIndices; ++j) {
  ------------------
  |  Branch (126:34): [True: 2.97k, False: 1.04k]
  ------------------
  127|  2.97k|                unsigned idx = faces[i].mIndices[j];
  128|  2.97k|                if (idx >= nVerts)
  ------------------
  |  Branch (128:21): [True: 0, False: 2.97k]
  ------------------
  129|      0|                    return false;
  130|  2.97k|            }
  131|  1.04k|        }
  132|     30|        return true;
  133|     30|    }

_ZN6Assimp12glTFImporterD2Ev:
   64|  5.13k|    ~glTFImporter() override = default;

_ZN5glTF26ObjectD2Ev:
  394|  59.5k|    virtual ~Object() = default;
_ZN5glTF215CustomExtensionD2Ev:
  367|   102k|    ~CustomExtension() = default;
_ZN5glTF210AttribType10FromStringEPKc:
  308|  12.4k|    inline static Value FromString(const char *str) {
  309|  35.9k|        for (size_t i = 0; i < NUM_VALUES; ++i) {
  ------------------
  |  Branch (309:28): [True: 35.4k, False: 486]
  ------------------
  310|  35.4k|            if (strcmp(data<0>::infos[i].name, str) == 0) {
  ------------------
  |  Branch (310:17): [True: 11.9k, False: 23.4k]
  ------------------
  311|  11.9k|                return static_cast<Value>(i);
  312|  11.9k|            }
  313|  35.4k|        }
  314|    486|        return SCALAR;
  315|  12.4k|    }
_ZN5glTF210AttribType16GetNumComponentsENS0_5ValueE:
  321|  26.6k|    inline static unsigned int GetNumComponents(Value type) {
  322|  26.6k|        return data<0>::infos[static_cast<size_t>(type)].numComponents;
  323|  26.6k|    }
_ZNK5glTF215CustomExtensioncvbEv:
  353|  12.8k|    operator bool() const {
  354|  12.8k|        return Size() != 0;
  355|  12.8k|    }
_ZNK5glTF215CustomExtension4SizeEv:
  357|  12.8k|    size_t Size() const {
  358|  12.8k|        if (mValues.isPresent) {
  ------------------
  |  Branch (358:13): [True: 0, False: 12.8k]
  ------------------
  359|      0|            return mValues.value.size();
  360|  12.8k|        } else if (mStringValue.isPresent || mDoubleValue.isPresent || mUint64Value.isPresent || mInt64Value.isPresent || mBoolValue.isPresent) {
  ------------------
  |  Branch (360:20): [True: 0, False: 12.8k]
  |  Branch (360:46): [True: 0, False: 12.8k]
  |  Branch (360:72): [True: 0, False: 12.8k]
  |  Branch (360:98): [True: 0, False: 12.8k]
  |  Branch (360:123): [True: 0, False: 12.8k]
  ------------------
  361|      0|            return 1;
  362|      0|        }
  363|  12.8k|        return 0;
  364|  12.8k|    }
_ZNK5glTF26Extras9HasExtrasEv:
  376|  12.8k|    inline bool HasExtras() const {
  377|  12.8k|        return !mValues.empty();
  378|  12.8k|    }
_ZN5glTF26Buffer10GetPointerEv:
  520|  6.75k|    uint8_t *GetPointer() { return mData.get(); }
_ZN5glTF26Buffer13MarkAsSpecialEv:
  522|  3.45k|    void MarkAsSpecial() { mIsSpecial = true; }
_ZN5glTF28Accessor7Indexer7GetUIntEi:
  596|  28.6k|        inline unsigned int GetUInt(int i) {
  597|  28.6k|            return GetValue<unsigned int>(i);
  598|  28.6k|        }
_ZNK5glTF28Accessor7Indexer7IsValidEv:
  600|  1.30k|        inline bool IsValid() const {
  601|  1.30k|            return data != nullptr;
  602|  1.30k|        }
_ZN5glTF28Accessor10GetIndexerEv:
  605|  1.31k|    inline Indexer GetIndexer() {
  606|  1.31k|        return Indexer(*this);
  607|  1.31k|    }
_ZN5glTF26CameraC2Ev:
  653|    104|            type(Perspective),
  654|    104|            cameraProperties() {
  655|       |        // empty
  656|    104|    }
_ZNK5glTF25Image7HasDataEv:
  699|    241|    inline bool HasData() const { return mDataLength > 0; }
_ZNK5glTF25Image13GetDataLengthEv:
  701|    111|    inline size_t GetDataLength() const { return mDataLength; }
_ZN5glTF221PbrSpecularGlossinessC2Ev:
  754|  5.45k|    PbrSpecularGlossiness() { SetDefaults(); }
_ZN5glTF216MaterialSpecularC2Ev:
  764|  5.45k|    MaterialSpecular() { SetDefaults(); }
_ZN5glTF213MaterialSheenC2Ev:
  774|  5.45k|    MaterialSheen() { SetDefaults(); }
_ZN5glTF214MaterialVolumeC2Ev:
  797|  5.45k|    MaterialVolume() { SetDefaults(); }
_ZN5glTF211MaterialIORC2Ev:
  804|  5.45k|    MaterialIOR() { SetDefaults(); }
_ZN5glTF224MaterialEmissiveStrengthC2Ev:
  811|  5.45k|    MaterialEmissiveStrength() { SetDefaults(); }
_ZN5glTF218MaterialAnisotropyC2Ev:
  820|  5.45k|    MaterialAnisotropy() { SetDefaults(); }
_ZN5glTF28MaterialC2Ev:
  868|  5.45k|    Material() { SetDefaults(); }
_ZN5glTF24Mesh9PrimitiveC2Ev:
  901|  4.47k|        Primitive(): ngonEncoded(false) {}
_ZN5glTF27SamplerC2Ev:
  950|    144|    Sampler() { SetDefaults(); }
_ZN5glTF25AssetC2EPN6Assimp8IOSystemEPN9rapidjson36IGenericRemoteSchemaDocumentProviderINS4_21GenericSchemaDocumentINS4_12GenericValueINS4_4UTF8IcEENS4_19MemoryPoolAllocatorINS4_12CrtAllocatorEEEEESB_EEEE:
 1179|  9.60k|            mDicts(),
 1180|  9.60k|            extensionsUsed(),
 1181|  9.60k|            extensionsRequired(),
 1182|  9.60k|            asset(),
 1183|  9.60k|            extras(nullptr),
 1184|  9.60k|            accessors(*this, "accessors"),
 1185|  9.60k|            animations(*this, "animations"),
 1186|  9.60k|            buffers(*this, "buffers"),
 1187|  9.60k|            bufferViews(*this, "bufferViews"),
 1188|  9.60k|            cameras(*this, "cameras"),
 1189|  9.60k|            lights(*this, "lights", "KHR_lights_punctual"),
 1190|  9.60k|            images(*this, "images"),
 1191|  9.60k|            materials(*this, "materials"),
 1192|  9.60k|            meshes(*this, "meshes"),
 1193|  9.60k|            nodes(*this, "nodes"),
 1194|  9.60k|            samplers(*this, "samplers"),
 1195|  9.60k|            scenes(*this, "scenes"),
 1196|  9.60k|            skins(*this, "skins"),
 1197|  9.60k|            textures(*this, "textures") ,
 1198|  9.60k|            mIOSystem(io),
 1199|  9.60k|            mSchemaDocumentProvider(schemaDocumentProvider) {
 1200|       |        // empty
 1201|  9.60k|    }
_ZN5glTF217ComponentTypeSizeENS_13ComponentTypeE:
  197|  26.1k|inline unsigned int ComponentTypeSize(ComponentType t) {
  198|  26.1k|    switch (t) {
  199|     93|    case ComponentType_SHORT:
  ------------------
  |  Branch (199:5): [True: 93, False: 26.0k]
  ------------------
  200|  3.68k|    case ComponentType_UNSIGNED_SHORT:
  ------------------
  |  Branch (200:5): [True: 3.59k, False: 22.5k]
  ------------------
  201|  3.68k|        return 2;
  202|       |
  203|  2.91k|    case ComponentType_UNSIGNED_INT:
  ------------------
  |  Branch (203:5): [True: 2.91k, False: 23.2k]
  ------------------
  204|  17.1k|    case ComponentType_FLOAT:
  ------------------
  |  Branch (204:5): [True: 14.2k, False: 11.9k]
  ------------------
  205|  17.1k|        return 4;
  206|       |
  207|  3.71k|    case ComponentType_BYTE:
  ------------------
  |  Branch (207:5): [True: 3.71k, False: 22.4k]
  ------------------
  208|  5.29k|    case ComponentType_UNSIGNED_BYTE:
  ------------------
  |  Branch (208:5): [True: 1.57k, False: 24.5k]
  ------------------
  209|  5.29k|        return 1;
  210|     38|    default:
  ------------------
  |  Branch (210:5): [True: 38, False: 26.0k]
  ------------------
  211|     38|        throw DeadlyImportError("GLTF: Unsupported Component Type ", ai_to_string(t));
  212|  26.1k|    }
  213|  26.1k|}
_ZN5glTF226getContextForErrorMessagesERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEES8_:
 1244|    134|inline std::string getContextForErrorMessages(const std::string &id, const std::string &name) {
 1245|    134|    std::string context = id;
 1246|    134|    if (!name.empty()) {
  ------------------
  |  Branch (1246:9): [True: 54, False: 80]
  ------------------
 1247|     54|        context += " (\"" + name + "\")";
 1248|     54|    }
 1249|    134|    return context;
 1250|    134|}
_ZN5glTF25Asset10ExtensionsC2Ev:
 1142|  9.60k|        Extensions() = default;
_ZN5glTF25Asset18RequiredExtensionsC2Ev:
 1152|  9.60k|        RequiredExtensions() = default;
_ZN5glTF213AssetMetadataC2Ev:
 1104|  9.60k|    AssetMetadata() = default;
_ZN5glTF212LazyDictBaseD2Ev:
 1026|   134k|    virtual ~LazyDictBase() = default;
_ZN5glTF215CustomExtensionC2Ev:
  366|  82.4k|    CustomExtension() = default;
_ZN5glTF215CustomExtensionC2ERKS0_:
  368|  19.7k|    CustomExtension(const CustomExtension &other) = default;
_ZN5glTF215CustomExtensionaSERKS0_:
  369|  2.25k|    CustomExtension& operator=(const CustomExtension&) = default;
_ZN5glTF25SceneC2Ev:
  959|  3.18k|    Scene() = default;
_ZN5glTF24NodeC2Ev:
  935|  15.3k|    Node() = default;
_ZN5glTF24MeshC2Ev:
  909|  4.49k|    Mesh() = default;
_ZN5glTF28AccessorC2Ev:
  609|  13.4k|    Accessor() = default;
_ZN5glTF27TextureC2Ev:
  989|    203|    Texture() = default;
_ZN5glTF24SkinC2Ev:
  974|  3.68k|    Skin() = default;
_ZN5glTF29AnimationC2Ev:
 1019|    352|    Animation() = default;
_ZN5glTF29Animation7SamplerC2Ev:
  995|    273|        Sampler() = default;
_ZN5glTF29Animation7ChannelC2Ev:
 1010|    335|        Channel() = default;
_ZN5glTF29Animation6TargetC2Ev:
 1003|    335|        Target() = default;
_ZNK5glTF28LazyDictINS_8MaterialEE4SizeEv:
 1086|  2.35k|    inline unsigned int Size() const { return unsigned(mObjs.size()); }
_ZN5glTF28LazyDictINS_8MaterialEEixEm:
 1088|  2.23k|    inline T &operator[](size_t i) { return *mObjs[i]; }
_ZNK5glTF28LazyDictINS_4MeshEE4SizeEv:
 1086|  13.9k|    inline unsigned int Size() const { return unsigned(mObjs.size()); }
_ZN5glTF28LazyDictINS_4MeshEEixEm:
 1088|  4.88k|    inline T &operator[](size_t i) { return *mObjs[i]; }
_ZNK5glTF28LazyDictINS_6CameraEE4SizeEv:
 1086|  2.04k|    inline unsigned int Size() const { return unsigned(mObjs.size()); }
_ZN5glTF28LazyDictINS_6CameraEEixEm:
 1088|     50|    inline T &operator[](size_t i) { return *mObjs[i]; }
_ZNK5glTF28LazyDictINS_5LightEE4SizeEv:
 1086|  2.00k|    inline unsigned int Size() const { return unsigned(mObjs.size()); }
_ZNK5glTF28LazyDictINS_9AnimationEE4SizeEv:
 1086|  1.71k|    inline unsigned int Size() const { return unsigned(mObjs.size()); }
_ZN5glTF28LazyDictINS_9AnimationEEixEm:
 1088|    257|    inline T &operator[](size_t i) { return *mObjs[i]; }
_ZN5glTF28LazyDictINS_4NodeEEixEm:
 1088|    120|    inline T &operator[](size_t i) { return *mObjs[i]; }
_ZNK5glTF28LazyDictINS_5ImageEE4SizeEv:
 1086|  5.05k|    inline unsigned int Size() const { return unsigned(mObjs.size()); }
_ZN5glTF28LazyDictINS_5ImageEEixEm:
 1088|    241|    inline T &operator[](size_t i) { return *mObjs[i]; }

_ZN5glTF26BufferD2Ev:
  565|  4.92k|inline Buffer::~Buffer() {
  566|  4.92k|    for (SEncodedRegion *reg : EncodedRegion_List) delete reg;
  ------------------
  |  Branch (566:30): [True: 0, False: 4.92k]
  ------------------
  567|  4.92k|}
_ZN5glTF26Object10FindStringERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEEPKc:
  235|  5.26k|inline Value *Object::FindString(Value &val, const char *memberId) {
  236|  5.26k|    return FindStringInContext(val, memberId, id.c_str(), name.c_str());
  237|  5.26k|}
_ZN5glTF26Object8FindUIntERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEEPKc:
  243|  91.5k|inline Value *Object::FindUInt(Value &val, const char *memberId) {
  244|  91.5k|    return FindUIntInContext(val, memberId, id.c_str(), name.c_str());
  245|  91.5k|}
_ZN5glTF26Object9FindArrayERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEEPKc:
  247|  49.7k|inline Value *Object::FindArray(Value &val, const char *memberId) {
  248|  49.7k|    return FindArrayInContext(val, memberId, id.c_str(), name.c_str());
  249|  49.7k|}
_ZN5glTF26Object10FindObjectERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEEPKc:
  251|   143k|inline Value *Object::FindObject(Value &val, const char *memberId) {
  252|   143k|    return FindObjectInContext(val, memberId, id.c_str(), name.c_str());
  253|   143k|}
_ZN5glTF26Object13FindExtensionERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEEPKc:
  255|      3|inline Value *Object::FindExtension(Value &val, const char *extensionId) {
  256|      3|    return FindExtensionInContext(val, extensionId, id.c_str(), name.c_str());
  257|      3|}
_ZN5glTF26Object14ReadExtensionsERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEE:
  259|  49.0k|inline void Object::ReadExtensions(Value &val) {
  260|  49.0k|    if (Value *curExtensions = FindObject(val, "extensions")) {
  ------------------
  |  Branch (260:16): [True: 0, False: 49.0k]
  ------------------
  261|      0|        this->customExtensions = glTF2::ReadExtensions("extensions", *curExtensions);
  262|      0|    }
  263|  49.0k|}
_ZN5glTF26Object10ReadExtrasERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEE:
  265|  49.0k|inline void Object::ReadExtras(Value &val) {
  266|  49.0k|    if (Value *curExtras = FindObject(val, "extras")) {
  ------------------
  |  Branch (266:16): [True: 4.81k, False: 44.2k]
  ------------------
  267|  4.81k|        this->extras = glTF2::ReadExtras(*curExtras);
  268|  4.81k|    }
  269|  49.0k|}
_ZN5glTF26Buffer4ReadERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEERNS_5AssetE:
  573|  1.47k|inline void Buffer::Read(Value &obj, Asset &r) {
  574|  1.47k|    size_t statedLength = MemberOrDefault<size_t>(obj, "byteLength", 0);
  575|  1.47k|    byteLength = statedLength;
  576|       |
  577|  1.47k|    Value *it = FindString(obj, "uri");
  578|  1.47k|    if (!it) {
  ------------------
  |  Branch (578:9): [True: 24, False: 1.45k]
  ------------------
  579|     24|        if (statedLength > 0) {
  ------------------
  |  Branch (579:13): [True: 15, False: 9]
  ------------------
  580|     15|            throw DeadlyImportError("GLTF: buffer with non-zero length missing the \"uri\" attribute");
  581|     15|        }
  582|      9|        return;
  583|     24|    }
  584|       |
  585|  1.45k|    const char *uri = it->GetString();
  586|       |
  587|  1.45k|    glTFCommon::Util::DataURI dataURI;
  588|  1.45k|    if (ParseDataURI(uri, it->GetStringLength(), dataURI)) {
  ------------------
  |  Branch (588:9): [True: 1.15k, False: 295]
  ------------------
  589|  1.15k|        if (dataURI.base64) {
  ------------------
  |  Branch (589:13): [True: 1.09k, False: 58]
  ------------------
  590|  1.09k|            uint8_t *data = nullptr;
  591|  1.09k|            this->byteLength = Base64::Decode(dataURI.data, dataURI.dataLength, data);
  592|  1.09k|            this->mData.reset(data, std::default_delete<uint8_t[]>());
  593|       |
  594|  1.09k|            if (statedLength > 0 && this->byteLength != statedLength) {
  ------------------
  |  Branch (594:17): [True: 972, False: 127]
  |  Branch (594:37): [True: 21, False: 951]
  ------------------
  595|     21|                throw DeadlyImportError("GLTF: buffer \"", id, "\", expected ", ai_to_string(statedLength),
  596|     21|                        " bytes, but found ", ai_to_string(dataURI.dataLength));
  597|     21|            }
  598|  1.09k|        } else { // assume raw data
  599|     58|            if (statedLength != dataURI.dataLength) {
  ------------------
  |  Branch (599:17): [True: 56, False: 2]
  ------------------
  600|     56|                throw DeadlyImportError("GLTF: buffer \"", id, "\", expected ", ai_to_string(statedLength),
  601|     56|                        " bytes, but found ", ai_to_string(dataURI.dataLength));
  602|     56|            }
  603|       |
  604|      2|            this->mData.reset(new uint8_t[dataURI.dataLength], std::default_delete<uint8_t[]>());
  605|      2|            memcpy(this->mData.get(), dataURI.data, dataURI.dataLength);
  606|      2|        }
  607|  1.15k|    } else { // Local file
  608|    295|        if (byteLength > 0) {
  ------------------
  |  Branch (608:13): [True: 276, False: 19]
  ------------------
  609|    276|            std::string dir = !r.mCurrentAssetDir.empty() ? (r.mCurrentAssetDir.back() == '/' ? r.mCurrentAssetDir : r.mCurrentAssetDir + '/') : "";
  ------------------
  |  Branch (609:31): [True: 0, False: 276]
  |  Branch (609:62): [True: 0, False: 0]
  ------------------
  610|       |
  611|    276|            IOStream *file = r.OpenFile(dir + uri, "rb");
  612|    276|            if (file) {
  ------------------
  |  Branch (612:17): [True: 26, False: 250]
  ------------------
  613|     26|                bool ok = LoadFromStream(*file, byteLength);
  614|     26|                delete file;
  615|       |
  616|     26|                if (!ok)
  ------------------
  |  Branch (616:21): [True: 0, False: 26]
  ------------------
  617|      0|                    throw DeadlyImportError("GLTF: error while reading referenced file \"", uri, "\"");
  618|    250|            } else {
  619|    250|                throw DeadlyImportError("GLTF: could not open referenced file \"", uri, "\"");
  620|    250|            }
  621|    276|        }
  622|    295|    }
  623|  1.45k|}
_ZN5glTF26Buffer14LoadFromStreamERN6Assimp8IOStreamEmm:
  625|  1.50k|inline bool Buffer::LoadFromStream(IOStream &stream, size_t length, size_t baseOffset) {
  626|  1.50k|    byteLength = length ? length : stream.FileSize();
  ------------------
  |  Branch (626:18): [True: 1.50k, False: 0]
  ------------------
  627|       |
  628|  1.50k|    if (byteLength > stream.FileSize()) {
  ------------------
  |  Branch (628:9): [True: 52, False: 1.45k]
  ------------------
  629|     52|        throw DeadlyImportError("GLTF: Invalid byteLength exceeds size of actual data.");
  630|     52|    }
  631|       |
  632|  1.45k|    if (baseOffset) {
  ------------------
  |  Branch (632:9): [True: 1.43k, False: 17]
  ------------------
  633|  1.43k|        stream.Seek(baseOffset, aiOrigin_SET);
  634|  1.43k|    }
  635|       |
  636|  1.45k|    mData.reset(new uint8_t[byteLength], std::default_delete<uint8_t[]>());
  637|       |
  638|  1.45k|    if (stream.Read(mData.get(), byteLength, 1) != 1) {
  ------------------
  |  Branch (638:9): [True: 12, False: 1.44k]
  ------------------
  639|     12|        return false;
  640|     12|    }
  641|  1.44k|    return true;
  642|  1.45k|}
_ZN5glTF210BufferView4ReadERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEERNS_5AssetE:
  765|  8.05k|inline void BufferView::Read(Value &obj, Asset &r) {
  766|  8.05k|    if (Value *bufferVal = FindUInt(obj, "buffer")) {
  ------------------
  |  Branch (766:16): [True: 8.05k, False: 4]
  ------------------
  767|  8.05k|        buffer = r.buffers.Retrieve(bufferVal->GetUint());
  768|  8.05k|    }
  769|       |
  770|  8.05k|    if (!buffer) {
  ------------------
  |  Branch (770:9): [True: 3, False: 8.05k]
  ------------------
  771|      3|        throw DeadlyImportError("GLTF: Buffer view without valid buffer.");
  772|      3|    }
  773|       |
  774|  8.05k|    byteOffset = MemberOrDefault(obj, "byteOffset", size_t(0));
  775|  8.05k|    byteLength = MemberOrDefault(obj, "byteLength", size_t(0));
  776|  8.05k|    byteStride = MemberOrDefault(obj, "byteStride", 0u);
  777|       |
  778|       |    // Check length
  779|  8.05k|    if ((byteOffset + byteLength) > buffer->byteLength) {
  ------------------
  |  Branch (779:9): [True: 40, False: 8.01k]
  ------------------
  780|     40|        throw DeadlyImportError("GLTF: Buffer view with offset/length (", byteOffset, "/", byteLength, ") is out of range.");
  781|     40|    }
  782|  8.05k|}
_ZN5glTF28Accessor4ReadERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEERNS_5AssetE:
  871|  13.4k|inline void Accessor::Read(Value &obj, Asset &r) {
  872|  13.4k|    if (Value *bufferViewVal = FindUInt(obj, "bufferView")) {
  ------------------
  |  Branch (872:16): [True: 8.68k, False: 4.73k]
  ------------------
  873|  8.68k|        bufferView = r.bufferViews.Retrieve(bufferViewVal->GetUint());
  874|  8.68k|    }
  875|       |
  876|  13.4k|    byteOffset = MemberOrDefault(obj, "byteOffset", size_t(0));
  877|  13.4k|    componentType = MemberOrDefault(obj, "componentType", ComponentType_BYTE);
  878|  13.4k|    {
  879|  13.4k|        const Value *countValue = FindUInt(obj, "count");
  880|  13.4k|        if (!countValue) {
  ------------------
  |  Branch (880:13): [True: 8, False: 13.4k]
  ------------------
  881|      8|            throw DeadlyImportError("A count value is required, when reading ", id.c_str(), name.empty() ? "" : " (" + name + ")");
  ------------------
  |  Branch (881:93): [True: 6, False: 2]
  ------------------
  882|      8|        }
  883|  13.4k|        count = countValue->GetUint();
  884|  13.4k|    }
  885|       |
  886|      0|    const char *typestr;
  887|  13.4k|    type = ReadMember(obj, "type", typestr) ? AttribType::FromString(typestr) : AttribType::SCALAR;
  ------------------
  |  Branch (887:12): [True: 12.4k, False: 931]
  ------------------
  888|       |
  889|  13.4k|    if (bufferView) {
  ------------------
  |  Branch (889:9): [True: 8.15k, False: 5.24k]
  ------------------
  890|       |        // Check length
  891|  8.15k|        unsigned long long byteLength = count > 0
  ------------------
  |  Branch (891:41): [True: 8.12k, False: 36]
  ------------------
  892|  8.15k|            ? (unsigned long long)GetStride() * (unsigned long long)(count - 1) + (unsigned long long)GetElementSize()
  893|  8.15k|            : 0;
  894|       |
  895|       |        // handle integer overflow
  896|  8.15k|        if (byteLength < count) {
  ------------------
  |  Branch (896:13): [True: 0, False: 8.15k]
  ------------------
  897|      0|            throw DeadlyImportError("GLTF: Accessor with offset/count (", byteOffset, "/", count, ") is out of range.");
  898|      0|        }
  899|       |
  900|  8.15k|        if ((byteOffset + byteLength) > bufferView->byteLength || (bufferView->byteOffset + byteOffset + byteLength) > bufferView->buffer->byteLength) {
  ------------------
  |  Branch (900:13): [True: 105, False: 8.05k]
  |  Branch (900:67): [True: 0, False: 8.05k]
  ------------------
  901|     77|            throw DeadlyImportError("GLTF: Accessor with offset/length (", byteOffset, "/", byteLength, ") is out of range.");
  902|     77|        }
  903|  8.15k|    }
  904|       |
  905|  13.3k|    if (Value *sparseValue = FindObject(obj, "sparse")) {
  ------------------
  |  Branch (905:16): [True: 0, False: 13.3k]
  ------------------
  906|      0|        sparse.reset(new Sparse);
  907|       |        // count
  908|      0|        ReadMember(*sparseValue, "count", sparse->count);
  909|       |
  910|       |        // indices
  911|      0|        if (Value *indicesValue = FindObject(*sparseValue, "indices")) {
  ------------------
  |  Branch (911:20): [True: 0, False: 0]
  ------------------
  912|       |            //indices bufferView
  913|      0|            Value *indiceViewID = FindUInt(*indicesValue, "bufferView");
  914|      0|            if (!indiceViewID) {
  ------------------
  |  Branch (914:17): [True: 0, False: 0]
  ------------------
  915|      0|                throw DeadlyImportError("A bufferView value is required, when reading ", id.c_str(), name.empty() ? "" : " (" + name + ")");
  ------------------
  |  Branch (915:102): [True: 0, False: 0]
  ------------------
  916|      0|            }
  917|      0|            sparse->indices = r.bufferViews.Retrieve(indiceViewID->GetUint());
  918|       |            //indices byteOffset
  919|      0|            sparse->indicesByteOffset = MemberOrDefault(*indicesValue, "byteOffset", size_t(0));
  920|       |            //indices componentType
  921|      0|            sparse->indicesType = MemberOrDefault(*indicesValue, "componentType", ComponentType_BYTE);
  922|       |            //sparse->indices->Read(*indicesValue, r);
  923|      0|        } else {
  924|       |            // indicesType
  925|      0|            sparse->indicesType = MemberOrDefault(*sparseValue, "componentType", ComponentType_UNSIGNED_SHORT);
  926|      0|        }
  927|       |
  928|       |        // value
  929|      0|        if (Value *valuesValue = FindObject(*sparseValue, "values")) {
  ------------------
  |  Branch (929:20): [True: 0, False: 0]
  ------------------
  930|       |            //value bufferView
  931|      0|            Value *valueViewID = FindUInt(*valuesValue, "bufferView");
  932|      0|            if (!valueViewID) {
  ------------------
  |  Branch (932:17): [True: 0, False: 0]
  ------------------
  933|      0|                throw DeadlyImportError("A bufferView value is required, when reading ", id.c_str(), name.empty() ? "" : " (" + name + ")");
  ------------------
  |  Branch (933:102): [True: 0, False: 0]
  ------------------
  934|      0|            }
  935|      0|            sparse->values = r.bufferViews.Retrieve(valueViewID->GetUint());
  936|       |            //value byteOffset
  937|      0|            sparse->valuesByteOffset = MemberOrDefault(*valuesValue, "byteOffset", size_t(0));
  938|       |            //sparse->values->Read(*valuesValue, r);
  939|      0|        }
  940|       |
  941|       |
  942|      0|        const unsigned int elementSize = GetElementSize();
  943|      0|        const size_t dataSize = count * elementSize;
  944|      0|        if (bufferView) {
  ------------------
  |  Branch (944:13): [True: 0, False: 0]
  ------------------
  945|      0|            size_t bufferViewTailSize;
  946|      0|            const uint8_t* bufferViewPointer = bufferView->GetPointerAndTailSize(byteOffset, bufferViewTailSize);
  947|      0|            if (dataSize > bufferViewTailSize) {
  ------------------
  |  Branch (947:17): [True: 0, False: 0]
  ------------------
  948|      0|                throw DeadlyImportError("Invalid buffer when reading ", id.c_str(), name.empty() ? "" : " (" + name + ")");
  ------------------
  |  Branch (948:85): [True: 0, False: 0]
  ------------------
  949|      0|            }
  950|      0|            sparse->PopulateData(dataSize, bufferViewPointer);
  951|      0|        }
  952|      0|        else {
  953|      0|            sparse->PopulateData(dataSize, nullptr);
  954|      0|        }
  955|      0|        sparse->PatchData(elementSize);
  956|      0|    }
  957|  13.3k|}
_ZN5glTF28Accessor16GetNumComponentsEv:
  959|  26.6k|inline unsigned int Accessor::GetNumComponents() {
  960|  26.6k|    return AttribType::GetNumComponents(type);
  961|  26.6k|}
_ZN5glTF28Accessor20GetBytesPerComponentEv:
  963|  26.1k|inline unsigned int Accessor::GetBytesPerComponent() {
  964|  26.1k|    return int(ComponentTypeSize(componentType));
  965|  26.1k|}
_ZN5glTF28Accessor14GetElementSizeEv:
  967|  26.1k|inline unsigned int Accessor::GetElementSize() {
  968|  26.1k|    return GetNumComponents() * GetBytesPerComponent();
  969|  26.1k|}
_ZN5glTF28Accessor10GetPointerEv:
  971|  6.80k|inline uint8_t *Accessor::GetPointer() {
  972|  6.80k|    if (decodedBuffer)
  ------------------
  |  Branch (972:9): [True: 0, False: 6.80k]
  ------------------
  973|      0|        return decodedBuffer->GetPointer();
  974|       |
  975|  6.80k|    if (sparse)
  ------------------
  |  Branch (975:9): [True: 0, False: 6.80k]
  ------------------
  976|      0|        return sparse->data.data();
  977|       |
  978|  6.80k|    if (!bufferView || !bufferView->buffer) return nullptr;
  ------------------
  |  Branch (978:9): [True: 113, False: 6.69k]
  |  Branch (978:24): [True: 0, False: 6.69k]
  ------------------
  979|  6.69k|    uint8_t *basePtr = bufferView->buffer->GetPointer();
  980|  6.69k|    if (!basePtr) return nullptr;
  ------------------
  |  Branch (980:9): [True: 0, False: 6.69k]
  ------------------
  981|       |
  982|  6.69k|    size_t offset = byteOffset + bufferView->byteOffset;
  983|       |
  984|       |    // Check if region is encoded.
  985|  6.69k|    if (bufferView->buffer->EncodedRegion_Current != nullptr) {
  ------------------
  |  Branch (985:9): [True: 0, False: 6.69k]
  ------------------
  986|      0|        const size_t begin = bufferView->buffer->EncodedRegion_Current->Offset;
  987|      0|        const size_t end = begin + bufferView->buffer->EncodedRegion_Current->DecodedData_Length;
  988|       |
  989|      0|        if ((offset >= begin) && (offset < end))
  ------------------
  |  Branch (989:13): [True: 0, False: 0]
  |  Branch (989:34): [True: 0, False: 0]
  ------------------
  990|      0|            return &bufferView->buffer->EncodedRegion_Current->DecodedData[offset - begin];
  991|      0|    }
  992|       |
  993|  6.69k|    return basePtr + offset;
  994|  6.69k|}
_ZN5glTF28Accessor9GetStrideEv:
  996|  14.8k|inline size_t Accessor::GetStride() {
  997|       |    // Decoded buffer is always packed
  998|  14.8k|    if (decodedBuffer)
  ------------------
  |  Branch (998:9): [True: 0, False: 14.8k]
  ------------------
  999|      0|        return GetElementSize();
 1000|       |
 1001|       |    // Sparse and normal bufferView
 1002|  14.8k|    return (bufferView && bufferView->byteStride ? bufferView->byteStride : GetElementSize());
  ------------------
  |  Branch (1002:13): [True: 14.8k, False: 52]
  |  Branch (1002:27): [True: 3.85k, False: 10.9k]
  ------------------
 1003|  14.8k|}
_ZN5glTF28Accessor14GetMaxByteSizeEv:
 1005|  34.1k|inline size_t Accessor::GetMaxByteSize() {
 1006|  34.1k|    if (decodedBuffer)
  ------------------
  |  Branch (1006:9): [True: 0, False: 34.1k]
  ------------------
 1007|      0|        return decodedBuffer->byteLength;
 1008|       |
 1009|  34.1k|    if (sparse) {
  ------------------
  |  Branch (1009:9): [True: 0, False: 34.1k]
  ------------------
 1010|      0|        return sparse->data.size();
 1011|      0|    }
 1012|       |
 1013|  34.1k|    if (bufferView) {
  ------------------
  |  Branch (1013:9): [True: 34.1k, False: 0]
  ------------------
 1014|  34.1k|        return byteOffset <= bufferView->byteLength ? bufferView->byteLength - byteOffset : 0;
  ------------------
  |  Branch (1014:16): [True: 34.1k, False: 0]
  ------------------
 1015|  34.1k|    }
 1016|       |
 1017|      0|    return 0;
 1018|  34.1k|}
_ZN5glTF25Image4ReadERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEERNS_5AssetE:
 1136|    177|inline void Image::Read(Value &obj, Asset &r) {
 1137|       |    //basisu: no need to handle .ktx2, .basis, load as is
 1138|    177|    if (!mDataLength) {
  ------------------
  |  Branch (1138:9): [True: 177, False: 0]
  ------------------
 1139|    177|        Value *curUri = FindString(obj, "uri");
 1140|    177|        if (nullptr != curUri) {
  ------------------
  |  Branch (1140:13): [True: 106, False: 71]
  ------------------
 1141|    106|            const char *uristr = curUri->GetString();
 1142|       |
 1143|    106|            glTFCommon::Util::DataURI dataURI;
 1144|    106|            if (ParseDataURI(uristr, curUri->GetStringLength(), dataURI)) {
  ------------------
  |  Branch (1144:17): [True: 89, False: 17]
  ------------------
 1145|     89|                mimeType = dataURI.mediaType;
 1146|     89|                if (dataURI.base64) {
  ------------------
  |  Branch (1146:21): [True: 85, False: 4]
  ------------------
 1147|     85|                    uint8_t *ptr = nullptr;
 1148|     85|                    mDataLength = Base64::Decode(dataURI.data, dataURI.dataLength, ptr);
 1149|     85|                    mData.reset(ptr);
 1150|     85|                }
 1151|     89|            } else {
 1152|     17|                this->uri = uristr;
 1153|     17|            }
 1154|    106|        } else if (Value *bufferViewVal = FindUInt(obj, "bufferView")) {
  ------------------
  |  Branch (1154:27): [True: 67, False: 4]
  ------------------
 1155|     67|            this->bufferView = r.bufferViews.Retrieve(bufferViewVal->GetUint());
 1156|     67|            if (Value *mtype = FindString(obj, "mimeType")) {
  ------------------
  |  Branch (1156:24): [True: 63, False: 4]
  ------------------
 1157|     63|                this->mimeType = mtype->GetString();
 1158|     63|            }
 1159|     67|            if (!this->bufferView || this->mimeType.empty()) {
  ------------------
  |  Branch (1159:17): [True: 3, False: 64]
  |  Branch (1159:38): [True: 1, False: 63]
  ------------------
 1160|      1|                throw DeadlyImportError("GLTF2: ", getContextForErrorMessages(id, name), " does not have a URI, so it must have a valid bufferView and mimetype");
 1161|      1|            }
 1162|       |
 1163|     66|            Ref<Buffer> buffer = this->bufferView->buffer;
 1164|       |
 1165|     66|            this->mDataLength = this->bufferView->byteLength;
 1166|       |            // maybe this memcpy could be avoided if aiTexture does not delete[] pcData at destruction.
 1167|       |
 1168|     66|            this->mData.reset(new uint8_t[this->mDataLength]);
 1169|     66|            memcpy(this->mData.get(), buffer->GetPointer() + this->bufferView->byteOffset, this->mDataLength);
 1170|     66|        } else {
 1171|      4|            throw DeadlyImportError("GLTF2: ", getContextForErrorMessages(id, name), " should have either a URI of a bufferView and mimetype");
 1172|      4|        }
 1173|    177|    }
 1174|    177|}
_ZN5glTF25Image9StealDataEv:
 1176|    111|inline uint8_t *Image::StealData() {
 1177|    111|    mDataLength = 0;
 1178|    111|    return mData.release();
 1179|    111|}
_ZN5glTF27Sampler4ReadERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEERNS_5AssetE:
 1199|    144|inline void Sampler::Read(Value &obj, Asset & /*r*/) {
 1200|    144|    SetDefaults();
 1201|       |
 1202|    144|    ReadMember(obj, "name", name);
 1203|    144|    ReadMember(obj, "magFilter", magFilter);
 1204|    144|    ReadMember(obj, "minFilter", minFilter);
 1205|    144|    ReadMember(obj, "wrapS", wrapS);
 1206|    144|    ReadMember(obj, "wrapT", wrapT);
 1207|    144|}
_ZN5glTF27Sampler11SetDefaultsEv:
 1209|    288|inline void Sampler::SetDefaults() {
 1210|       |    //only wrapping modes have defaults
 1211|    288|    wrapS = SamplerWrap::Repeat;
 1212|    288|    wrapT = SamplerWrap::Repeat;
 1213|    288|    magFilter = SamplerMagFilter::UNSET;
 1214|    288|    minFilter = SamplerMinFilter::UNSET;
 1215|    288|}
_ZN5glTF27Texture4ReadERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEERNS_5AssetE:
 1217|    203|inline void Texture::Read(Value &obj, Asset &r) {
 1218|    203|    if (Value *sourceVal = FindUInt(obj, "source")) {
  ------------------
  |  Branch (1218:16): [True: 184, False: 19]
  ------------------
 1219|    184|        source = r.images.Retrieve(sourceVal->GetUint());
 1220|    184|    }
 1221|       |
 1222|    203|    if (Value *samplerVal = FindUInt(obj, "sampler")) {
  ------------------
  |  Branch (1222:16): [True: 152, False: 51]
  ------------------
 1223|    152|        sampler = r.samplers.Retrieve(samplerVal->GetUint());
 1224|    152|    }
 1225|       |
 1226|    203|    if (Value *extensions = FindObject(obj, "extensions")) {
  ------------------
  |  Branch (1226:16): [True: 0, False: 203]
  ------------------
 1227|      0|        if (r.extensionsUsed.KHR_texture_basisu) {
  ------------------
  |  Branch (1227:13): [True: 0, False: 0]
  ------------------
 1228|      0|            if (Value *curBasisU = FindObject(*extensions, "KHR_texture_basisu")) {
  ------------------
  |  Branch (1228:24): [True: 0, False: 0]
  ------------------
 1229|       |
 1230|      0|                if (Value *sourceVal = FindUInt(*curBasisU, "source")) {
  ------------------
  |  Branch (1230:28): [True: 0, False: 0]
  ------------------
 1231|      0|                    source = r.images.Retrieve(sourceVal->GetUint());
 1232|      0|                }
 1233|      0|            }
 1234|      0|        } else if(r.extensionsUsed.EXT_texture_webp) {
  ------------------
  |  Branch (1234:19): [True: 0, False: 0]
  ------------------
 1235|      0|            if (Value *curBasisU = FindObject(*extensions, "EXT_texture_webp")) {
  ------------------
  |  Branch (1235:24): [True: 0, False: 0]
  ------------------
 1236|       |
 1237|      0|                if (Value *sourceVal = FindUInt(*curBasisU, "source")) {
  ------------------
  |  Branch (1237:28): [True: 0, False: 0]
  ------------------
 1238|      0|                    source = r.images.Retrieve(sourceVal->GetUint());
 1239|      0|                }
 1240|      0|            }
 1241|      0|        }
 1242|      0|    }
 1243|    203|}
_ZN5glTF28Material20SetTexturePropertiesERNS_5AssetEPN9rapidjson12GenericValueINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEEEERNS_11TextureInfoE:
 1245|    295|void Material::SetTextureProperties(Asset &r, Value *prop, TextureInfo &out) {
 1246|    295|    if (r.extensionsUsed.KHR_texture_transform) {
  ------------------
  |  Branch (1246:9): [True: 3, False: 292]
  ------------------
 1247|      3|        if (Value *pKHR_texture_transform = FindExtension(*prop, "KHR_texture_transform")) {
  ------------------
  |  Branch (1247:20): [True: 0, False: 3]
  ------------------
 1248|      0|            out.textureTransformSupported = true;
 1249|      0|            if (Value *array = FindArray(*pKHR_texture_transform, "offset")) {
  ------------------
  |  Branch (1249:24): [True: 0, False: 0]
  ------------------
 1250|      0|                out.TextureTransformExt_t.offset[0] = (*array)[0].GetFloat();
 1251|      0|                out.TextureTransformExt_t.offset[1] = (*array)[1].GetFloat();
 1252|      0|            } else {
 1253|      0|                out.TextureTransformExt_t.offset[0] = 0;
 1254|      0|                out.TextureTransformExt_t.offset[1] = 0;
 1255|      0|            }
 1256|       |
 1257|      0|            if (!ReadMember(*pKHR_texture_transform, "rotation", out.TextureTransformExt_t.rotation)) {
  ------------------
  |  Branch (1257:17): [True: 0, False: 0]
  ------------------
 1258|      0|                out.TextureTransformExt_t.rotation = 0;
 1259|      0|            }
 1260|       |
 1261|      0|            if (Value *array = FindArray(*pKHR_texture_transform, "scale")) {
  ------------------
  |  Branch (1261:24): [True: 0, False: 0]
  ------------------
 1262|      0|                out.TextureTransformExt_t.scale[0] = (*array)[0].GetFloat();
 1263|      0|                out.TextureTransformExt_t.scale[1] = (*array)[1].GetFloat();
 1264|      0|            } else {
 1265|      0|                out.TextureTransformExt_t.scale[0] = 1;
 1266|      0|                out.TextureTransformExt_t.scale[1] = 1;
 1267|      0|            }
 1268|      0|        }
 1269|      3|    }
 1270|       |
 1271|    295|    if (Value *indexProp = FindUInt(*prop, "index")) {
  ------------------
  |  Branch (1271:16): [True: 291, False: 4]
  ------------------
 1272|    291|        out.texture = r.textures.Retrieve(indexProp->GetUint());
 1273|    291|    }
 1274|       |
 1275|    295|    if (Value *texcoord = FindUInt(*prop, "texCoord")) {
  ------------------
  |  Branch (1275:16): [True: 1, False: 294]
  ------------------
 1276|      1|        out.texCoord = texcoord->GetUint();
 1277|      1|    }
 1278|    295|}
_ZN5glTF28Material19ReadTexturePropertyERNS_5AssetERN9rapidjson12GenericValueINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEEEEPKcRNS_11TextureInfoE:
 1280|  8.71k|inline void Material::ReadTextureProperty(Asset &r, Value &vals, const char *propName, TextureInfo &out) {
 1281|  8.71k|    if (Value *prop = FindMember(vals, propName)) {
  ------------------
  |  Branch (1281:16): [True: 295, False: 8.42k]
  ------------------
 1282|    295|        SetTextureProperties(r, prop, out);
 1283|    295|    }
 1284|  8.71k|}
_ZN5glTF28Material19ReadTexturePropertyERNS_5AssetERN9rapidjson12GenericValueINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEEEEPKcRNS_17NormalTextureInfoE:
 1286|  3.06k|inline void Material::ReadTextureProperty(Asset &r, Value &vals, const char *propName, NormalTextureInfo &out) {
 1287|  3.06k|    if (Value *prop = FindMember(vals, propName)) {
  ------------------
  |  Branch (1287:16): [True: 0, False: 3.06k]
  ------------------
 1288|      0|        SetTextureProperties(r, prop, out);
 1289|       |
 1290|      0|        if (Value *scale = FindNumber(*prop, "scale")) {
  ------------------
  |  Branch (1290:20): [True: 0, False: 0]
  ------------------
 1291|      0|            out.scale = static_cast<float>(scale->GetDouble());
 1292|      0|        }
 1293|      0|    }
 1294|  3.06k|}
_ZN5glTF28Material19ReadTexturePropertyERNS_5AssetERN9rapidjson12GenericValueINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEEEEPKcRNS_20OcclusionTextureInfoE:
 1296|  3.06k|inline void Material::ReadTextureProperty(Asset &r, Value &vals, const char *propName, OcclusionTextureInfo &out) {
 1297|  3.06k|    if (Value *prop = FindMember(vals, propName)) {
  ------------------
  |  Branch (1297:16): [True: 0, False: 3.06k]
  ------------------
 1298|      0|        SetTextureProperties(r, prop, out);
 1299|       |
 1300|      0|        if (Value *strength = FindNumber(*prop, "strength")) {
  ------------------
  |  Branch (1300:20): [True: 0, False: 0]
  ------------------
 1301|      0|            out.strength = static_cast<float>(strength->GetDouble());
 1302|      0|        }
 1303|      0|    }
 1304|  3.06k|}
_ZN5glTF28Material4ReadERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEERNS_5AssetE:
 1306|  3.10k|inline void Material::Read(Value &material, Asset &r) {
 1307|  3.10k|    SetDefaults();
 1308|       |
 1309|  3.10k|    if (Value *curPbrMetallicRoughness = FindObject(material, "pbrMetallicRoughness")) {
  ------------------
  |  Branch (1309:16): [True: 2.84k, False: 260]
  ------------------
 1310|  2.84k|        ReadMember(*curPbrMetallicRoughness, "baseColorFactor", this->pbrMetallicRoughness.baseColorFactor);
 1311|  2.84k|        ReadTextureProperty(r, *curPbrMetallicRoughness, "baseColorTexture", this->pbrMetallicRoughness.baseColorTexture);
 1312|  2.84k|        ReadTextureProperty(r, *curPbrMetallicRoughness, "metallicRoughnessTexture", this->pbrMetallicRoughness.metallicRoughnessTexture);
 1313|  2.84k|        ReadMember(*curPbrMetallicRoughness, "metallicFactor", this->pbrMetallicRoughness.metallicFactor);
 1314|  2.84k|        ReadMember(*curPbrMetallicRoughness, "roughnessFactor", this->pbrMetallicRoughness.roughnessFactor);
 1315|  2.84k|    }
 1316|       |
 1317|  3.10k|    ReadTextureProperty(r, material, "normalTexture", this->normalTexture);
 1318|  3.10k|    ReadTextureProperty(r, material, "occlusionTexture", this->occlusionTexture);
 1319|  3.10k|    ReadTextureProperty(r, material, "emissiveTexture", this->emissiveTexture);
 1320|  3.10k|    ReadMember(material, "emissiveFactor", this->emissiveFactor);
 1321|       |
 1322|  3.10k|    ReadMember(material, "doubleSided", this->doubleSided);
 1323|  3.10k|    ReadMember(material, "alphaMode", this->alphaMode);
 1324|  3.10k|    ReadMember(material, "alphaCutoff", this->alphaCutoff);
 1325|       |
 1326|  3.10k|    if (Value *extensions = FindObject(material, "extensions")) {
  ------------------
  |  Branch (1326:16): [True: 0, False: 3.10k]
  ------------------
 1327|      0|        if (r.extensionsUsed.KHR_materials_pbrSpecularGlossiness) {
  ------------------
  |  Branch (1327:13): [True: 0, False: 0]
  ------------------
 1328|      0|            if (Value *curPbrSpecularGlossiness = FindObject(*extensions, "KHR_materials_pbrSpecularGlossiness")) {
  ------------------
  |  Branch (1328:24): [True: 0, False: 0]
  ------------------
 1329|      0|                PbrSpecularGlossiness pbrSG;
 1330|       |
 1331|      0|                ReadMember(*curPbrSpecularGlossiness, "diffuseFactor", pbrSG.diffuseFactor);
 1332|      0|                ReadTextureProperty(r, *curPbrSpecularGlossiness, "diffuseTexture", pbrSG.diffuseTexture);
 1333|      0|                ReadTextureProperty(r, *curPbrSpecularGlossiness, "specularGlossinessTexture", pbrSG.specularGlossinessTexture);
 1334|      0|                ReadMember(*curPbrSpecularGlossiness, "specularFactor", pbrSG.specularFactor);
 1335|      0|                ReadMember(*curPbrSpecularGlossiness, "glossinessFactor", pbrSG.glossinessFactor);
 1336|       |
 1337|      0|                this->pbrSpecularGlossiness = Nullable<PbrSpecularGlossiness>(pbrSG);
 1338|      0|            }
 1339|      0|        }
 1340|       |
 1341|      0|        if (r.extensionsUsed.KHR_materials_specular) {
  ------------------
  |  Branch (1341:13): [True: 0, False: 0]
  ------------------
 1342|      0|            if (Value *curMatSpecular = FindObject(*extensions, "KHR_materials_specular")) {
  ------------------
  |  Branch (1342:24): [True: 0, False: 0]
  ------------------
 1343|      0|                MaterialSpecular specular;
 1344|       |
 1345|      0|                ReadMember(*curMatSpecular, "specularFactor", specular.specularFactor);
 1346|      0|                ReadTextureProperty(r, *curMatSpecular, "specularTexture", specular.specularTexture);
 1347|      0|                ReadMember(*curMatSpecular, "specularColorFactor", specular.specularColorFactor);
 1348|      0|                ReadTextureProperty(r, *curMatSpecular, "specularColorTexture", specular.specularColorTexture);
 1349|       |
 1350|      0|                this->materialSpecular = Nullable<MaterialSpecular>(specular);
 1351|      0|            }
 1352|      0|        }
 1353|       |
 1354|       |        // Extension KHR_texture_transform is handled in ReadTextureProperty
 1355|       |
 1356|      0|        if (r.extensionsUsed.KHR_materials_sheen) {
  ------------------
  |  Branch (1356:13): [True: 0, False: 0]
  ------------------
 1357|      0|            if (Value *curMaterialSheen = FindObject(*extensions, "KHR_materials_sheen")) {
  ------------------
  |  Branch (1357:24): [True: 0, False: 0]
  ------------------
 1358|      0|                MaterialSheen sheen;
 1359|       |
 1360|      0|                ReadMember(*curMaterialSheen, "sheenColorFactor", sheen.sheenColorFactor);
 1361|      0|                ReadTextureProperty(r, *curMaterialSheen, "sheenColorTexture", sheen.sheenColorTexture);
 1362|      0|                ReadMember(*curMaterialSheen, "sheenRoughnessFactor", sheen.sheenRoughnessFactor);
 1363|      0|                ReadTextureProperty(r, *curMaterialSheen, "sheenRoughnessTexture", sheen.sheenRoughnessTexture);
 1364|       |
 1365|      0|                this->materialSheen = Nullable<MaterialSheen>(sheen);
 1366|      0|            }
 1367|      0|        }
 1368|       |
 1369|      0|        if (r.extensionsUsed.KHR_materials_clearcoat) {
  ------------------
  |  Branch (1369:13): [True: 0, False: 0]
  ------------------
 1370|      0|            if (Value *curMaterialClearcoat = FindObject(*extensions, "KHR_materials_clearcoat")) {
  ------------------
  |  Branch (1370:24): [True: 0, False: 0]
  ------------------
 1371|      0|                MaterialClearcoat clearcoat;
 1372|       |
 1373|      0|                ReadMember(*curMaterialClearcoat, "clearcoatFactor", clearcoat.clearcoatFactor);
 1374|      0|                ReadTextureProperty(r, *curMaterialClearcoat, "clearcoatTexture", clearcoat.clearcoatTexture);
 1375|      0|                ReadMember(*curMaterialClearcoat, "clearcoatRoughnessFactor", clearcoat.clearcoatRoughnessFactor);
 1376|      0|                ReadTextureProperty(r, *curMaterialClearcoat, "clearcoatRoughnessTexture", clearcoat.clearcoatRoughnessTexture);
 1377|      0|                ReadTextureProperty(r, *curMaterialClearcoat, "clearcoatNormalTexture", clearcoat.clearcoatNormalTexture);
 1378|       |
 1379|      0|                this->materialClearcoat = Nullable<MaterialClearcoat>(clearcoat);
 1380|      0|            }
 1381|      0|        }
 1382|       |
 1383|      0|        if (r.extensionsUsed.KHR_materials_transmission) {
  ------------------
  |  Branch (1383:13): [True: 0, False: 0]
  ------------------
 1384|      0|            if (Value *curMaterialTransmission = FindObject(*extensions, "KHR_materials_transmission")) {
  ------------------
  |  Branch (1384:24): [True: 0, False: 0]
  ------------------
 1385|      0|                MaterialTransmission transmission;
 1386|       |
 1387|      0|                ReadMember(*curMaterialTransmission, "transmissionFactor", transmission.transmissionFactor);
 1388|      0|                ReadTextureProperty(r, *curMaterialTransmission, "transmissionTexture", transmission.transmissionTexture);
 1389|       |
 1390|      0|                this->materialTransmission = Nullable<MaterialTransmission>(transmission);
 1391|      0|            }
 1392|      0|        }
 1393|       |
 1394|      0|        if (r.extensionsUsed.KHR_materials_volume) {
  ------------------
  |  Branch (1394:13): [True: 0, False: 0]
  ------------------
 1395|      0|            if (Value *curMaterialVolume = FindObject(*extensions, "KHR_materials_volume")) {
  ------------------
  |  Branch (1395:24): [True: 0, False: 0]
  ------------------
 1396|      0|                MaterialVolume volume;
 1397|       |
 1398|      0|                ReadMember(*curMaterialVolume, "thicknessFactor", volume.thicknessFactor);
 1399|      0|                ReadTextureProperty(r, *curMaterialVolume, "thicknessTexture", volume.thicknessTexture);
 1400|      0|                ReadMember(*curMaterialVolume, "attenuationDistance", volume.attenuationDistance);
 1401|      0|                ReadMember(*curMaterialVolume, "attenuationColor", volume.attenuationColor);
 1402|       |
 1403|      0|                this->materialVolume = Nullable<MaterialVolume>(volume);
 1404|      0|            }
 1405|      0|        }
 1406|       |
 1407|      0|        if (r.extensionsUsed.KHR_materials_ior) {
  ------------------
  |  Branch (1407:13): [True: 0, False: 0]
  ------------------
 1408|      0|            if (Value *curMaterialIOR = FindObject(*extensions, "KHR_materials_ior")) {
  ------------------
  |  Branch (1408:24): [True: 0, False: 0]
  ------------------
 1409|      0|                MaterialIOR ior;
 1410|       |
 1411|      0|                ReadMember(*curMaterialIOR, "ior", ior.ior);
 1412|       |
 1413|      0|                this->materialIOR = Nullable<MaterialIOR>(ior);
 1414|      0|            }
 1415|      0|        }
 1416|       |
 1417|      0|        if (r.extensionsUsed.KHR_materials_emissive_strength) {
  ------------------
  |  Branch (1417:13): [True: 0, False: 0]
  ------------------
 1418|      0|            if (Value *curMaterialEmissiveStrength = FindObject(*extensions, "KHR_materials_emissive_strength")) {
  ------------------
  |  Branch (1418:24): [True: 0, False: 0]
  ------------------
 1419|      0|                MaterialEmissiveStrength emissiveStrength;
 1420|       |
 1421|      0|                ReadMember(*curMaterialEmissiveStrength, "emissiveStrength", emissiveStrength.emissiveStrength);
 1422|       |
 1423|      0|                this->materialEmissiveStrength = Nullable<MaterialEmissiveStrength>(emissiveStrength);
 1424|      0|            }
 1425|      0|        }
 1426|       |
 1427|      0|        if (r.extensionsUsed.KHR_materials_anisotropy) {
  ------------------
  |  Branch (1427:13): [True: 0, False: 0]
  ------------------
 1428|      0|            if (Value *curMaterialAnisotropy = FindObject(*extensions, "KHR_materials_anisotropy")) {
  ------------------
  |  Branch (1428:24): [True: 0, False: 0]
  ------------------
 1429|      0|                MaterialAnisotropy anisotropy;
 1430|       |
 1431|      0|                ReadMember(*curMaterialAnisotropy, "anisotropyStrength", anisotropy.anisotropyStrength);
 1432|      0|                ReadMember(*curMaterialAnisotropy, "anisotropyRotation", anisotropy.anisotropyRotation);
 1433|      0|                ReadTextureProperty(r, *curMaterialAnisotropy, "anisotropyTexture", anisotropy.anisotropyTexture);
 1434|       |
 1435|      0|                this->materialAnisotropy = Nullable<MaterialAnisotropy>(anisotropy);
 1436|      0|            }
 1437|      0|        }
 1438|       |
 1439|      0|        unlit = nullptr != FindObject(*extensions, "KHR_materials_unlit");
 1440|      0|    }
 1441|  3.10k|}
_ZN5glTF28Material11SetDefaultsEv:
 1443|  8.56k|inline void Material::SetDefaults() {
 1444|       |    //pbr materials
 1445|  8.56k|    SetVector(pbrMetallicRoughness.baseColorFactor, defaultBaseColor);
 1446|  8.56k|    pbrMetallicRoughness.metallicFactor = 1.0f;
 1447|  8.56k|    pbrMetallicRoughness.roughnessFactor = 1.0f;
 1448|       |
 1449|  8.56k|    SetVector(emissiveFactor, defaultEmissiveFactor);
 1450|  8.56k|    alphaMode = "OPAQUE";
 1451|  8.56k|    alphaCutoff = 0.5f;
 1452|  8.56k|    doubleSided = false;
 1453|  8.56k|    unlit = false;
 1454|  8.56k|}
_ZN5glTF221PbrSpecularGlossiness11SetDefaultsEv:
 1456|  5.45k|inline void PbrSpecularGlossiness::SetDefaults() {
 1457|       |    //pbrSpecularGlossiness properties
 1458|  5.45k|    SetVector(diffuseFactor, defaultDiffuseFactor);
 1459|  5.45k|    SetVector(specularFactor, defaultSpecularFactor);
 1460|  5.45k|    glossinessFactor = 1.0f;
 1461|  5.45k|}
_ZN5glTF216MaterialSpecular11SetDefaultsEv:
 1463|  5.45k|inline void MaterialSpecular::SetDefaults() {
 1464|       |    //KHR_materials_specular properties
 1465|  5.45k|    SetVector(specularColorFactor, defaultSpecularColorFactor);
 1466|  5.45k|    specularFactor = 1.f;
 1467|  5.45k|}
_ZN5glTF213MaterialSheen11SetDefaultsEv:
 1469|  5.45k|inline void MaterialSheen::SetDefaults() {
 1470|       |    //KHR_materials_sheen properties
 1471|  5.45k|    SetVector(sheenColorFactor, defaultSheenFactor);
 1472|  5.45k|    sheenRoughnessFactor = 0.f;
 1473|  5.45k|}
_ZN5glTF214MaterialVolume11SetDefaultsEv:
 1475|  5.45k|inline void MaterialVolume::SetDefaults() {
 1476|       |    //KHR_materials_volume properties
 1477|  5.45k|    thicknessFactor = 0.f;
 1478|  5.45k|    attenuationDistance = std::numeric_limits<float>::infinity();
 1479|  5.45k|    SetVector(attenuationColor, defaultAttenuationColor);
 1480|  5.45k|}
_ZN5glTF211MaterialIOR11SetDefaultsEv:
 1482|  5.45k|inline void MaterialIOR::SetDefaults() {
 1483|       |    //KHR_materials_ior properties
 1484|  5.45k|    ior = 1.5f;
 1485|  5.45k|}
_ZN5glTF224MaterialEmissiveStrength11SetDefaultsEv:
 1487|  5.45k|inline void MaterialEmissiveStrength::SetDefaults() {
 1488|       |    //KHR_materials_emissive_strength properties
 1489|  5.45k|    emissiveStrength = 0.f;
 1490|  5.45k|}
_ZN5glTF218MaterialAnisotropy11SetDefaultsEv:
 1492|  5.45k|inline void MaterialAnisotropy::SetDefaults() {
 1493|       |    //KHR_materials_anisotropy properties
 1494|  5.45k|    anisotropyStrength = 0.f;
 1495|  5.45k|    anisotropyRotation = 0.f;
 1496|  5.45k|}
_ZN5glTF24Mesh4ReadERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEERNS_5AssetE:
 1498|  4.49k|inline void Mesh::Read(Value &pJSON_Object, Asset &pAsset_Root) {
 1499|  4.49k|    Value *curName = FindMember(pJSON_Object, "name");
 1500|  4.49k|    if (nullptr != curName && curName->IsString()) {
  ------------------
  |  Branch (1500:9): [True: 3.09k, False: 1.40k]
  |  Branch (1500:31): [True: 3.09k, False: 1]
  ------------------
 1501|  3.09k|        name = curName->GetString();
 1502|  3.09k|    }
 1503|       |
 1504|       |    /****************** Mesh primitives ******************/
 1505|  4.49k|    Value *curPrimitives = FindArray(pJSON_Object, "primitives");
 1506|  4.49k|    if (nullptr != curPrimitives) {
  ------------------
  |  Branch (1506:9): [True: 4.11k, False: 377]
  ------------------
 1507|  4.11k|        this->primitives.resize(curPrimitives->Size());
 1508|  8.54k|        for (unsigned int i = 0; i < curPrimitives->Size(); ++i) {
  ------------------
  |  Branch (1508:34): [True: 4.44k, False: 4.10k]
  ------------------
 1509|  4.44k|            Value &primitive = (*curPrimitives)[i];
 1510|       |
 1511|  4.44k|            Primitive &prim = this->primitives[i];
 1512|  4.44k|            prim.mode = MemberOrDefault(primitive, "mode", PrimitiveMode_TRIANGLES);
 1513|       |
 1514|  4.44k|            if (Value *indices = FindUInt(primitive, "indices")) {
  ------------------
  |  Branch (1514:24): [True: 3.58k, False: 855]
  ------------------
 1515|  3.58k|                prim.indices = pAsset_Root.accessors.Retrieve(indices->GetUint());
 1516|  3.58k|            }
 1517|       |
 1518|  4.44k|            if (Value *material = FindUInt(primitive, "material")) {
  ------------------
  |  Branch (1518:24): [True: 3.18k, False: 1.25k]
  ------------------
 1519|  3.18k|                prim.material = pAsset_Root.materials.Retrieve(material->GetUint());
 1520|  3.18k|            }
 1521|       |
 1522|  4.44k|            if (Value *attrs = FindObject(primitive, "attributes")) {
  ------------------
  |  Branch (1522:24): [True: 3.85k, False: 583]
  ------------------
 1523|  14.0k|                for (Value::MemberIterator it = attrs->MemberBegin(); it != attrs->MemberEnd(); ++it) {
  ------------------
  |  Branch (1523:71): [True: 10.1k, False: 3.83k]
  ------------------
 1524|  10.1k|                    if (!it->value.IsUint()) continue;
  ------------------
  |  Branch (1524:25): [True: 31, False: 10.1k]
  ------------------
 1525|  10.1k|                    const char *attr = it->name.GetString();
 1526|       |                    // Valid attribute semantics include POSITION, NORMAL, TANGENT, TEXCOORD, COLOR, JOINT, JOINTMATRIX,
 1527|       |                    // and WEIGHT.Attribute semantics can be of the form[semantic]_[set_index], e.g., TEXCOORD_0, TEXCOORD_1, etc.
 1528|       |
 1529|  10.1k|                    int undPos = 0;
 1530|  10.1k|                    Mesh::AccessorList *vec = nullptr;
 1531|  10.1k|                    if (GetAttribVector(prim, attr, vec, undPos)) {
  ------------------
  |  Branch (1531:25): [True: 9.66k, False: 482]
  ------------------
 1532|  9.66k|                        size_t idx = (attr[undPos] == '_') ? atoi(attr + undPos + 1) : 0;
  ------------------
  |  Branch (1532:38): [True: 2.66k, False: 7.00k]
  ------------------
 1533|  9.66k|                        if ((*vec).size() != idx) {
  ------------------
  |  Branch (1533:29): [True: 18, False: 9.65k]
  ------------------
 1534|     18|                            throw DeadlyImportError("GLTF: Invalid attribute in mesh: ", name, " primitive: ", i, "attrib: ", attr,
 1535|     18|                                    ". All indices for indexed attribute semantics must start with 0 and be continuous positive integers: TEXCOORD_0, TEXCOORD_1, etc.");
 1536|     18|                        }
 1537|  9.65k|                        (*vec).resize(idx + 1);
 1538|  9.65k|                        (*vec)[idx] = pAsset_Root.accessors.Retrieve(it->value.GetUint());
 1539|  9.65k|                    }
 1540|  10.1k|                }
 1541|  3.85k|            }
 1542|       |
 1543|       |#ifdef ASSIMP_ENABLE_DRACO
 1544|       |            // KHR_draco_mesh_compression spec: Draco can only be used for glTF Triangles or Triangle Strips
 1545|       |            if (pAsset_Root.extensionsUsed.KHR_draco_mesh_compression && (prim.mode == PrimitiveMode_TRIANGLES || prim.mode == PrimitiveMode_TRIANGLE_STRIP)) {
 1546|       |                // Look for draco mesh compression extension and bufferView
 1547|       |                // Skip if any missing
 1548|       |                if (Value *dracoExt = FindExtension(primitive, "KHR_draco_mesh_compression")) {
 1549|       |                    if (Value *bufView = FindUInt(*dracoExt, "bufferView")) {
 1550|       |                        // Attempt to load indices and attributes using draco compression
 1551|       |                        auto bufferView = pAsset_Root.bufferViews.Retrieve(bufView->GetUint());
 1552|       |                        // Attempt to perform the draco decode on the buffer data
 1553|       |                        const char *bufferViewData = reinterpret_cast<const char *>(bufferView->buffer->GetPointer() + bufferView->byteOffset);
 1554|       |                        draco::DecoderBuffer decoderBuffer;
 1555|       |                        decoderBuffer.Init(bufferViewData, bufferView->byteLength);
 1556|       |                        draco::Decoder decoder;
 1557|       |                        auto decodeResult = decoder.DecodeMeshFromBuffer(&decoderBuffer);
 1558|       |                        if (!decodeResult.ok()) {
 1559|       |                            // A corrupt Draco isn't actually fatal if the primitive data is also provided in a standard buffer, but does anyone do that?
 1560|       |                            throw DeadlyImportError("GLTF: Invalid Draco mesh compression in mesh: ", name, " primitive: ", i, ": ", decodeResult.status().error_msg_string());
 1561|       |                        }
 1562|       |
 1563|       |                        // Now we have a draco mesh
 1564|       |                        const std::unique_ptr<draco::Mesh> &pDracoMesh = decodeResult.value();
 1565|       |
 1566|       |                        // Redirect the accessors to the decoded data
 1567|       |
 1568|       |                        // Indices
 1569|       |                        SetDecodedIndexBuffer_Draco(*pDracoMesh, prim);
 1570|       |
 1571|       |                        // Vertex attributes
 1572|       |                        if (Value *attrs = FindObject(*dracoExt, "attributes")) {
 1573|       |                            for (Value::MemberIterator it = attrs->MemberBegin(); it != attrs->MemberEnd(); ++it) {
 1574|       |                                if (!it->value.IsUint()) continue;
 1575|       |                                const char *attr = it->name.GetString();
 1576|       |
 1577|       |                                int undPos = 0;
 1578|       |                                Mesh::AccessorList *vec = nullptr;
 1579|       |                                if (GetAttribVector(prim, attr, vec, undPos)) {
 1580|       |                                    size_t idx = (attr[undPos] == '_') ? atoi(attr + undPos + 1) : 0;
 1581|       |                                    if (idx >= (*vec).size()) {
 1582|       |                                        throw DeadlyImportError("GLTF: Invalid draco attribute in mesh: ", name, " primitive: ", i, " attrib: ", attr,
 1583|       |                                                ". All indices for indexed attribute semantics must start with 0 and be continuous positive integers: TEXCOORD_0, TEXCOORD_1, etc.");
 1584|       |                                    }
 1585|       |
 1586|       |                                    if (!(*vec)[idx]) {
 1587|       |                                        throw DeadlyImportError("GLTF: Invalid draco attribute in mesh: ", name, " primitive: ", i, " attrib: ", attr,
 1588|       |                                                ". All draco-encoded attributes must also define an accessor.");
 1589|       |                                    }
 1590|       |
 1591|       |                                    Accessor &attribAccessor = *(*vec)[idx];
 1592|       |                                    if (attribAccessor.count == 0)
 1593|       |                                        throw DeadlyImportError("GLTF: Invalid draco attribute in mesh: ", name, " primitive: ", i, " attrib: ", attr);
 1594|       |
 1595|       |                                    // Redirect this accessor to the appropriate Draco vertex attribute data
 1596|       |                                    const uint32_t dracoAttribId = it->value.GetUint();
 1597|       |                                    SetDecodedAttributeBuffer_Draco(*pDracoMesh, dracoAttribId, attribAccessor);
 1598|       |                                }
 1599|       |                            }
 1600|       |                        }
 1601|       |                    }
 1602|       |                }
 1603|       |            }
 1604|       |#endif
 1605|       |
 1606|  4.42k|            Value *targetsArray = FindArray(primitive, "targets");
 1607|  4.42k|            if (nullptr != targetsArray) {
  ------------------
  |  Branch (1607:17): [True: 19, False: 4.40k]
  ------------------
 1608|     19|                prim.targets.resize(targetsArray->Size());
 1609|     53|                for (unsigned int j = 0; j < targetsArray->Size(); ++j) {
  ------------------
  |  Branch (1609:42): [True: 34, False: 19]
  ------------------
 1610|     34|                    Value &target = (*targetsArray)[j];
 1611|     34|                    if (!target.IsObject()) {
  ------------------
  |  Branch (1611:25): [True: 2, False: 32]
  ------------------
 1612|      2|                        continue;
 1613|      2|                    }
 1614|     80|                    for (Value::MemberIterator it = target.MemberBegin(); it != target.MemberEnd(); ++it) {
  ------------------
  |  Branch (1614:75): [True: 48, False: 32]
  ------------------
 1615|     48|                        if (!it->value.IsUint()) {
  ------------------
  |  Branch (1615:29): [True: 7, False: 41]
  ------------------
 1616|      7|                            continue;
 1617|      7|                        }
 1618|     41|                        const char *attr = it->name.GetString();
 1619|       |                        // Valid attribute semantics include POSITION, NORMAL, TANGENT
 1620|     41|                        int undPos = 0;
 1621|     41|                        Mesh::AccessorList *vec = nullptr;
 1622|     41|                        if (GetAttribTargetVector(prim, j, attr, vec, undPos)) {
  ------------------
  |  Branch (1622:29): [True: 17, False: 24]
  ------------------
 1623|     17|                            size_t idx = (attr[undPos] == '_') ? atoi(attr + undPos + 1) : 0;
  ------------------
  |  Branch (1623:42): [True: 0, False: 17]
  ------------------
 1624|     17|                            if ((*vec).size() <= idx) {
  ------------------
  |  Branch (1624:33): [True: 15, False: 2]
  ------------------
 1625|     15|                                (*vec).resize(idx + 1);
 1626|     15|                            }
 1627|     17|                            (*vec)[idx] = pAsset_Root.accessors.Retrieve(it->value.GetUint());
 1628|     17|                        }
 1629|     41|                    }
 1630|     32|                }
 1631|     19|            }
 1632|       |
 1633|  4.42k|            if(this->targetNames.empty())
  ------------------
  |  Branch (1633:16): [True: 3.73k, False: 684]
  ------------------
 1634|  3.73k|            {
 1635|  3.73k|                Value *curExtras = FindObject(primitive, "extras");
 1636|  3.73k|                if (nullptr != curExtras) {
  ------------------
  |  Branch (1636:21): [True: 0, False: 3.73k]
  ------------------
 1637|      0|                    if (Value *curTargetNames = FindArray(*curExtras, "targetNames")) {
  ------------------
  |  Branch (1637:32): [True: 0, False: 0]
  ------------------
 1638|      0|                        this->targetNames.resize(curTargetNames->Size());
 1639|      0|                        for (unsigned int j = 0; j < curTargetNames->Size(); ++j) {
  ------------------
  |  Branch (1639:50): [True: 0, False: 0]
  ------------------
 1640|      0|                            Value &targetNameValue = (*curTargetNames)[j];
 1641|      0|                            if (targetNameValue.IsString()) {
  ------------------
  |  Branch (1641:33): [True: 0, False: 0]
  ------------------
 1642|      0|                                this->targetNames[j] = targetNameValue.GetString();
 1643|      0|                            }
 1644|      0|                        }
 1645|      0|                    }
 1646|      0|                }
 1647|  3.73k|            }
 1648|  4.42k|        }
 1649|  4.11k|    }
 1650|       |
 1651|  4.47k|    Value *curWeights = FindArray(pJSON_Object, "weights");
 1652|  4.47k|    if (nullptr != curWeights) {
  ------------------
  |  Branch (1652:9): [True: 21, False: 4.45k]
  ------------------
 1653|     21|        this->weights.resize(curWeights->Size());
 1654|     41|        for (unsigned int i = 0; i < curWeights->Size(); ++i) {
  ------------------
  |  Branch (1654:34): [True: 20, False: 21]
  ------------------
 1655|     20|            Value &weightValue = (*curWeights)[i];
 1656|     20|            if (weightValue.IsNumber()) {
  ------------------
  |  Branch (1656:17): [True: 19, False: 1]
  ------------------
 1657|     19|                this->weights[i] = weightValue.GetFloat();
 1658|     19|            }
 1659|     20|        }
 1660|     21|    }
 1661|       |
 1662|  4.47k|    Value *curExtras = FindObject(pJSON_Object, "extras");
 1663|  4.47k|    if (nullptr != curExtras) {
  ------------------
  |  Branch (1663:9): [True: 0, False: 4.47k]
  ------------------
 1664|      0|        if (Value *curTargetNames = FindArray(*curExtras, "targetNames")) {
  ------------------
  |  Branch (1664:20): [True: 0, False: 0]
  ------------------
 1665|      0|            this->targetNames.resize(curTargetNames->Size());
 1666|      0|            for (unsigned int i = 0; i < curTargetNames->Size(); ++i) {
  ------------------
  |  Branch (1666:38): [True: 0, False: 0]
  ------------------
 1667|      0|                Value &targetNameValue = (*curTargetNames)[i];
 1668|      0|                if (targetNameValue.IsString()) {
  ------------------
  |  Branch (1668:21): [True: 0, False: 0]
  ------------------
 1669|      0|                    this->targetNames[i] = targetNameValue.GetString();
 1670|      0|                }
 1671|      0|            }
 1672|      0|        }
 1673|      0|    }
 1674|  4.47k|}
_ZN5glTF26Camera4ReadERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEERNS_5AssetE:
 1676|    104|inline void Camera::Read(Value &obj, Asset & /*r*/) {
 1677|    104|    std::string type_string = std::string(MemberOrDefault(obj, "type", "perspective"));
 1678|    104|    if (type_string == "orthographic") {
  ------------------
  |  Branch (1678:9): [True: 19, False: 85]
  ------------------
 1679|     19|        type = Camera::Orthographic;
 1680|     85|    } else {
 1681|     85|        type = Camera::Perspective;
 1682|     85|    }
 1683|       |
 1684|    104|    const char *subobjId = (type == Camera::Orthographic) ? "orthographic" : "perspective";
  ------------------
  |  Branch (1684:28): [True: 19, False: 85]
  ------------------
 1685|       |
 1686|    104|    Value *it = FindObject(obj, subobjId);
 1687|    104|    if (!it) throw DeadlyImportError("GLTF: Camera missing its parameters");
  ------------------
  |  Branch (1687:9): [True: 11, False: 93]
  ------------------
 1688|       |
 1689|     93|    if (type == Camera::Perspective) {
  ------------------
  |  Branch (1689:9): [True: 74, False: 19]
  ------------------
 1690|     74|        cameraProperties.perspective.aspectRatio = MemberOrDefault(*it, "aspectRatio", 0.f);
 1691|     74|        cameraProperties.perspective.yfov = MemberOrDefault(*it, "yfov", 3.1415f / 2.f);
 1692|     74|        cameraProperties.perspective.zfar = MemberOrDefault(*it, "zfar", 100.f);
 1693|     74|        cameraProperties.perspective.znear = MemberOrDefault(*it, "znear", 0.01f);
 1694|     74|    } else {
 1695|     19|        cameraProperties.ortographic.xmag = MemberOrDefault(*it, "xmag", 1.f);
 1696|     19|        cameraProperties.ortographic.ymag = MemberOrDefault(*it, "ymag", 1.f);
 1697|     19|        cameraProperties.ortographic.zfar = MemberOrDefault(*it, "zfar", 100.f);
 1698|     19|        cameraProperties.ortographic.znear = MemberOrDefault(*it, "znear", 0.01f);
 1699|     19|    }
 1700|     93|}
_ZN5glTF24Node4ReadERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEERNS_5AssetE:
 1733|  15.3k|inline void Node::Read(Value &obj, Asset &r) {
 1734|  15.3k|    if (name.empty()) {
  ------------------
  |  Branch (1734:9): [True: 7.86k, False: 7.49k]
  ------------------
 1735|  7.86k|        name = id;
 1736|  7.86k|    }
 1737|       |
 1738|  15.3k|    Value *curChildren = FindArray(obj, "children");
 1739|  15.3k|    if (nullptr != curChildren) {
  ------------------
  |  Branch (1739:9): [True: 5.95k, False: 9.39k]
  ------------------
 1740|  5.95k|        this->children.reserve(curChildren->Size());
 1741|  18.2k|        for (unsigned int i = 0; i < curChildren->Size(); ++i) {
  ------------------
  |  Branch (1741:34): [True: 12.2k, False: 5.95k]
  ------------------
 1742|  12.2k|            Value &child = (*curChildren)[i];
 1743|  12.2k|            if (child.IsUint()) {
  ------------------
  |  Branch (1743:17): [True: 11.7k, False: 527]
  ------------------
 1744|       |                // get/create the child node
 1745|  11.7k|                Ref<Node> chn = r.nodes.Retrieve(child.GetUint());
 1746|  11.7k|                if (chn) {
  ------------------
  |  Branch (1746:21): [True: 11.2k, False: 488]
  ------------------
 1747|  11.2k|                    this->children.push_back(chn);
 1748|  11.2k|                }
 1749|  11.7k|            }
 1750|  12.2k|        }
 1751|  5.95k|    }
 1752|       |
 1753|  15.3k|    Value *curMatrix = FindArray(obj, "matrix");
 1754|  15.3k|    if (nullptr != curMatrix) {
  ------------------
  |  Branch (1754:9): [True: 9.64k, False: 5.71k]
  ------------------
 1755|  9.64k|        ReadValue(*curMatrix, this->matrix);
 1756|  9.64k|    } else {
 1757|  5.71k|        ReadMember(obj, "translation", translation);
 1758|  5.71k|        ReadMember(obj, "scale", scale);
 1759|  5.71k|        ReadMember(obj, "rotation", rotation);
 1760|  5.71k|    }
 1761|       |
 1762|  15.3k|    Value *curMesh = FindUInt(obj, "mesh");
 1763|  15.3k|    if (nullptr != curMesh) {
  ------------------
  |  Branch (1763:9): [True: 6.48k, False: 8.86k]
  ------------------
 1764|  6.48k|        unsigned int numMeshes = 1;
 1765|  6.48k|        this->meshes.reserve(numMeshes);
 1766|  6.48k|        Ref<Mesh> meshRef = r.meshes.Retrieve((*curMesh).GetUint());
 1767|  6.48k|        if (meshRef) {
  ------------------
  |  Branch (1767:13): [True: 5.70k, False: 779]
  ------------------
 1768|  5.70k|            this->meshes.push_back(meshRef);
 1769|  5.70k|        }
 1770|  6.48k|    }
 1771|       |
 1772|       |    // Do not retrieve a skin here, just take a reference, to avoid infinite recursion
 1773|       |    // Skins will be properly loaded later
 1774|  15.3k|    Value *curSkin = FindUInt(obj, "skin");
 1775|  15.3k|    if (nullptr != curSkin) {
  ------------------
  |  Branch (1775:9): [True: 646, False: 14.7k]
  ------------------
 1776|    646|        this->skin = r.skins.Get(curSkin->GetUint());
 1777|    646|    }
 1778|       |
 1779|  15.3k|    Value *curCamera = FindUInt(obj, "camera");
 1780|  15.3k|    if (nullptr != curCamera) {
  ------------------
  |  Branch (1780:9): [True: 127, False: 15.2k]
  ------------------
 1781|    127|        this->camera = r.cameras.Retrieve(curCamera->GetUint());
 1782|    127|        if (this->camera) {
  ------------------
  |  Branch (1782:13): [True: 98, False: 29]
  ------------------
 1783|     98|            this->camera->id = this->id;
 1784|     98|        }
 1785|    127|    }
 1786|       |
 1787|  15.3k|    Value *curExtensions = FindObject(obj, "extensions");
 1788|  15.3k|    if (nullptr != curExtensions) {
  ------------------
  |  Branch (1788:9): [True: 0, False: 15.3k]
  ------------------
 1789|      0|        if (r.extensionsUsed.KHR_lights_punctual) {
  ------------------
  |  Branch (1789:13): [True: 0, False: 0]
  ------------------
 1790|      0|            if (Value *ext = FindObject(*curExtensions, "KHR_lights_punctual")) {
  ------------------
  |  Branch (1790:24): [True: 0, False: 0]
  ------------------
 1791|      0|                Value *curLight = FindUInt(*ext, "light");
 1792|      0|                if (nullptr != curLight) {
  ------------------
  |  Branch (1792:21): [True: 0, False: 0]
  ------------------
 1793|      0|                    this->light = r.lights.Retrieve(curLight->GetUint());
 1794|      0|                    if (this->light) {
  ------------------
  |  Branch (1794:25): [True: 0, False: 0]
  ------------------
 1795|      0|                        this->light->id = this->id;
 1796|      0|                    }
 1797|      0|                }
 1798|      0|            }
 1799|      0|        }
 1800|      0|    }
 1801|  15.3k|}
_ZN5glTF25Scene4ReadERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEERNS_5AssetE:
 1803|  3.18k|inline void Scene::Read(Value &obj, Asset &r) {
 1804|  3.18k|    if (Value *scene_name = FindString(obj, "name")) {
  ------------------
  |  Branch (1804:16): [True: 151, False: 3.03k]
  ------------------
 1805|    151|        if (scene_name->IsString()) {
  ------------------
  |  Branch (1805:13): [True: 151, False: 0]
  ------------------
 1806|    151|            this->name = scene_name->GetString();
 1807|    151|        }
 1808|    151|    }
 1809|  3.18k|    if (Value *array = FindArray(obj, "nodes")) {
  ------------------
  |  Branch (1809:16): [True: 3.06k, False: 126]
  ------------------
 1810|  7.35k|        for (unsigned int i = 0; i < array->Size(); ++i) {
  ------------------
  |  Branch (1810:34): [True: 4.29k, False: 3.06k]
  ------------------
 1811|  4.29k|            if (!(*array)[i].IsUint()) continue;
  ------------------
  |  Branch (1811:17): [True: 66, False: 4.22k]
  ------------------
 1812|  4.22k|            Ref<Node> node = r.nodes.Retrieve((*array)[i].GetUint());
 1813|  4.22k|            if (node)
  ------------------
  |  Branch (1813:17): [True: 3.29k, False: 930]
  ------------------
 1814|  3.29k|                this->nodes.push_back(node);
 1815|  4.22k|        }
 1816|  3.06k|    }
 1817|  3.18k|}
_ZN5glTF24Skin4ReadERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEERNS_5AssetE:
 1819|  3.68k|inline void Skin::Read(Value &obj, Asset &r) {
 1820|  3.68k|    if (Value *matrices = FindUInt(obj, "inverseBindMatrices")) {
  ------------------
  |  Branch (1820:16): [True: 554, False: 3.12k]
  ------------------
 1821|    554|        inverseBindMatrices = r.accessors.Retrieve(matrices->GetUint());
 1822|    554|    }
 1823|       |
 1824|  3.68k|    if (Value *joints = FindArray(obj, "joints")) {
  ------------------
  |  Branch (1824:16): [True: 508, False: 3.17k]
  ------------------
 1825|  3.25k|        for (unsigned i = 0; i < joints->Size(); ++i) {
  ------------------
  |  Branch (1825:30): [True: 2.74k, False: 508]
  ------------------
 1826|  2.74k|            if (!(*joints)[i].IsUint()) continue;
  ------------------
  |  Branch (1826:17): [True: 58, False: 2.68k]
  ------------------
 1827|  2.68k|            Ref<Node> node = r.nodes.Retrieve((*joints)[i].GetUint());
 1828|  2.68k|            if (node) {
  ------------------
  |  Branch (1828:17): [True: 2.67k, False: 19]
  ------------------
 1829|  2.67k|                this->jointNames.push_back(node);
 1830|  2.67k|            }
 1831|  2.68k|        }
 1832|    508|    }
 1833|  3.68k|}
_ZN5glTF29Animation4ReadERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEERNS_5AssetE:
 1835|    352|inline void Animation::Read(Value &obj, Asset &r) {
 1836|    352|    Value *curSamplers = FindArray(obj, "samplers");
 1837|    352|    if (nullptr != curSamplers) {
  ------------------
  |  Branch (1837:9): [True: 217, False: 135]
  ------------------
 1838|    490|        for (unsigned i = 0; i < curSamplers->Size(); ++i) {
  ------------------
  |  Branch (1838:30): [True: 273, False: 217]
  ------------------
 1839|    273|            Value &sampler = (*curSamplers)[i];
 1840|       |
 1841|    273|            Sampler s;
 1842|    273|            if (Value *input = FindUInt(sampler, "input")) {
  ------------------
  |  Branch (1842:24): [True: 212, False: 61]
  ------------------
 1843|    212|                s.input = r.accessors.Retrieve(input->GetUint());
 1844|    212|            }
 1845|    273|            if (Value *output = FindUInt(sampler, "output")) {
  ------------------
  |  Branch (1845:24): [True: 171, False: 102]
  ------------------
 1846|    171|                s.output = r.accessors.Retrieve(output->GetUint());
 1847|    171|            }
 1848|    273|            s.interpolation = Interpolation_LINEAR;
 1849|    273|            if (Value *interpolation = FindString(sampler, "interpolation")) {
  ------------------
  |  Branch (1849:24): [True: 136, False: 137]
  ------------------
 1850|    136|                const std::string interp = interpolation->GetString();
 1851|    136|                if (interp == "LINEAR") {
  ------------------
  |  Branch (1851:21): [True: 117, False: 19]
  ------------------
 1852|    117|                    s.interpolation = Interpolation_LINEAR;
 1853|    117|                } else if (interp == "STEP") {
  ------------------
  |  Branch (1853:28): [True: 0, False: 19]
  ------------------
 1854|      0|                    s.interpolation = Interpolation_STEP;
 1855|     19|                } else if (interp == "CUBICSPLINE") {
  ------------------
  |  Branch (1855:28): [True: 0, False: 19]
  ------------------
 1856|      0|                    s.interpolation = Interpolation_CUBICSPLINE;
 1857|      0|                }
 1858|    136|            }
 1859|    273|            this->samplers.push_back(s);
 1860|    273|        }
 1861|    217|    }
 1862|       |
 1863|    352|    Value *curChannels = FindArray(obj, "channels");
 1864|    352|    if (nullptr != curChannels) {
  ------------------
  |  Branch (1864:9): [True: 218, False: 134]
  ------------------
 1865|    553|        for (unsigned i = 0; i < curChannels->Size(); ++i) {
  ------------------
  |  Branch (1865:30): [True: 335, False: 218]
  ------------------
 1866|    335|            Value &channel = (*curChannels)[i];
 1867|       |
 1868|    335|            Channel c;
 1869|    335|            Value *curSampler = FindUInt(channel, "sampler");
 1870|    335|            if (nullptr != curSampler) {
  ------------------
  |  Branch (1870:17): [True: 192, False: 143]
  ------------------
 1871|    192|                c.sampler = curSampler->GetUint();
 1872|    192|            }
 1873|       |
 1874|    335|            if (Value *target = FindObject(channel, "target")) {
  ------------------
  |  Branch (1874:24): [True: 157, False: 178]
  ------------------
 1875|    157|                if (Value *node = FindUInt(*target, "node")) {
  ------------------
  |  Branch (1875:28): [True: 127, False: 30]
  ------------------
 1876|    127|                    c.target.node = r.nodes.Retrieve(node->GetUint());
 1877|    127|                }
 1878|    157|                if (Value *path = FindString(*target, "path")) {
  ------------------
  |  Branch (1878:28): [True: 136, False: 21]
  ------------------
 1879|    136|                    const std::string p = path->GetString();
 1880|    136|                    if (p == "translation") {
  ------------------
  |  Branch (1880:25): [True: 0, False: 136]
  ------------------
 1881|      0|                        c.target.path = AnimationPath_TRANSLATION;
 1882|    136|                    } else if (p == "rotation") {
  ------------------
  |  Branch (1882:32): [True: 106, False: 30]
  ------------------
 1883|    106|                        c.target.path = AnimationPath_ROTATION;
 1884|    106|                    } else if (p == "scale") {
  ------------------
  |  Branch (1884:32): [True: 0, False: 30]
  ------------------
 1885|      0|                        c.target.path = AnimationPath_SCALE;
 1886|     30|                    } else if (p == "weights") {
  ------------------
  |  Branch (1886:32): [True: 5, False: 25]
  ------------------
 1887|      5|                        c.target.path = AnimationPath_WEIGHTS;
 1888|      5|                    }
 1889|    136|                }
 1890|    157|            }
 1891|    335|            this->channels.push_back(c);
 1892|    335|        }
 1893|    218|    }
 1894|    352|}
_ZN5glTF213AssetMetadata4ReadERN9rapidjson15GenericDocumentINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEES6_EE:
 1896|  7.70k|inline void AssetMetadata::Read(Document &doc) {
 1897|  7.70k|    if (Value *obj = FindObject(doc, "asset")) {
  ------------------
  |  Branch (1897:16): [True: 7.53k, False: 171]
  ------------------
 1898|  7.53k|        ReadMember(*obj, "copyright", copyright);
 1899|  7.53k|        ReadMember(*obj, "generator", generator);
 1900|       |
 1901|  7.53k|        if (Value *versionString = FindStringInContext(*obj, "version", "\"asset\"")) {
  ------------------
  |  Branch (1901:20): [True: 7.00k, False: 538]
  ------------------
 1902|  7.00k|            version = versionString->GetString();
 1903|  7.00k|        }
 1904|  7.53k|        Value *curProfile = FindObjectInContext(*obj, "profile", "\"asset\"");
 1905|  7.53k|        if (nullptr != curProfile) {
  ------------------
  |  Branch (1905:13): [True: 54, False: 7.48k]
  ------------------
 1906|     54|            ReadMember(*curProfile, "api", this->profile.api);
 1907|     54|            ReadMember(*curProfile, "version", this->profile.version);
 1908|     54|        }
 1909|  7.53k|    }
 1910|       |
 1911|  7.70k|    if (version.empty() || version[0] != '2') {
  ------------------
  |  Branch (1911:9): [True: 286, False: 7.42k]
  |  Branch (1911:28): [True: 418, False: 7.00k]
  ------------------
 1912|    574|        throw DeadlyImportError("GLTF: Unsupported glTF version: ", version);
 1913|    574|    }
 1914|  7.70k|}
_ZN5glTF25Asset16ReadBinaryHeaderERN6Assimp8IOStreamERNSt3__16vectorIcNS4_9allocatorIcEEEE:
 1920|  3.45k|inline void Asset::ReadBinaryHeader(IOStream &stream, std::vector<char> &sceneData) {
 1921|  3.45k|    ASSIMP_LOG_DEBUG("Reading GLTF2 binary");
 1922|  3.45k|    GLB_Header header;
 1923|  3.45k|    if (stream.Read(&header, sizeof(header), 1) != 1) {
  ------------------
  |  Branch (1923:9): [True: 0, False: 3.45k]
  ------------------
 1924|      0|        throw DeadlyImportError("GLTF: Unable to read the file header");
 1925|      0|    }
 1926|       |
 1927|  3.45k|    if (strncmp((char *)header.magic, AI_GLB_MAGIC_NUMBER, sizeof(header.magic)) != 0) {
  ------------------
  |  |  147|  3.45k|#define AI_GLB_MAGIC_NUMBER "glTF"
  ------------------
  |  Branch (1927:9): [True: 0, False: 3.45k]
  ------------------
 1928|      0|        throw DeadlyImportError("GLTF: Invalid binary glTF file");
 1929|      0|    }
 1930|       |
 1931|  3.45k|    AI_SWAP4(header.version);
 1932|  3.45k|    asset.version = ai_to_string(header.version);
 1933|  3.45k|    if (header.version != 2) {
  ------------------
  |  Branch (1933:9): [True: 170, False: 3.28k]
  ------------------
 1934|    170|        throw DeadlyImportError("GLTF: Unsupported binary glTF version");
 1935|    170|    }
 1936|       |
 1937|  3.28k|    GLB_Chunk chunk;
 1938|  3.28k|    if (stream.Read(&chunk, sizeof(chunk), 1) != 1) {
  ------------------
  |  Branch (1938:9): [True: 0, False: 3.28k]
  ------------------
 1939|      0|        throw DeadlyImportError("GLTF: Unable to read JSON chunk");
 1940|      0|    }
 1941|       |
 1942|  3.28k|    AI_SWAP4(chunk.chunkLength);
 1943|  3.28k|    AI_SWAP4(chunk.chunkType);
 1944|       |
 1945|  3.28k|    if (chunk.chunkType != ChunkType_JSON) {
  ------------------
  |  Branch (1945:9): [True: 46, False: 3.23k]
  ------------------
 1946|     46|        throw DeadlyImportError("GLTF: JSON chunk missing");
 1947|     46|    }
 1948|       |
 1949|       |    // read the scene data, ensure null termination
 1950|  3.23k|    static_assert(std::numeric_limits<uint32_t>::max() <= std::numeric_limits<size_t>::max(), "size_t must be at least 32bits");
 1951|  3.23k|    mSceneLength = chunk.chunkLength; // Can't be larger than 4GB (max. uint32_t)
 1952|  3.23k|    sceneData.resize(mSceneLength + 1);
 1953|  3.23k|    sceneData[mSceneLength] = '\0';
 1954|       |
 1955|  3.23k|    if (stream.Read(&sceneData[0], 1, mSceneLength) != mSceneLength) {
  ------------------
  |  Branch (1955:9): [True: 74, False: 3.16k]
  ------------------
 1956|     74|        throw DeadlyImportError("GLTF: Could not read the file contents");
 1957|     74|    }
 1958|       |
 1959|  3.16k|    uint32_t padding = ((chunk.chunkLength + 3) & ~3) - chunk.chunkLength;
 1960|  3.16k|    if (padding > 0) {
  ------------------
  |  Branch (1960:9): [True: 86, False: 3.07k]
  ------------------
 1961|     86|        stream.Seek(padding, aiOrigin_CUR);
 1962|     86|    }
 1963|       |
 1964|  3.16k|    AI_SWAP4(header.length);
 1965|  3.16k|    mBodyOffset = 12 + 8 + chunk.chunkLength + padding + 8;
 1966|  3.16k|    if (header.length >= mBodyOffset) {
  ------------------
  |  Branch (1966:9): [True: 3.11k, False: 48]
  ------------------
 1967|  3.11k|        if (stream.Read(&chunk, sizeof(chunk), 1) != 1) {
  ------------------
  |  Branch (1967:13): [True: 36, False: 3.07k]
  ------------------
 1968|     36|            throw DeadlyImportError("GLTF: Unable to read BIN chunk");
 1969|     36|        }
 1970|       |
 1971|  3.07k|        AI_SWAP4(chunk.chunkLength);
 1972|  3.07k|        AI_SWAP4(chunk.chunkType);
 1973|       |
 1974|  3.07k|        if (chunk.chunkType != ChunkType_BIN) {
  ------------------
  |  Branch (1974:13): [True: 90, False: 2.98k]
  ------------------
 1975|     90|            throw DeadlyImportError("GLTF: BIN chunk missing");
 1976|     90|        }
 1977|       |
 1978|  2.98k|        mBodyLength = chunk.chunkLength;
 1979|  2.98k|    } else {
 1980|     48|        mBodyOffset = mBodyLength = 0;
 1981|     48|    }
 1982|  3.16k|}
_ZN5glTF25Asset12ReadDocumentERN6Assimp8IOStreamEbRNSt3__16vectorIcNS4_9allocatorIcEEEE:
 1984|  9.60k|inline rapidjson::Document Asset::ReadDocument(IOStream &stream, bool isBinary, std::vector<char> &sceneData) {
 1985|  9.60k|    ASSIMP_LOG_DEBUG("Loading GLTF2 asset");
 1986|       |
 1987|       |    // is binary? then read the header
 1988|  9.60k|    if (isBinary) {
  ------------------
  |  Branch (1988:9): [True: 3.45k, False: 6.15k]
  ------------------
 1989|  3.45k|        SetAsBinary(); // also creates the body buffer
 1990|  3.45k|        ReadBinaryHeader(stream, sceneData);
 1991|  6.15k|    } else {
 1992|  6.15k|        mSceneLength = stream.FileSize();
 1993|  6.15k|        mBodyLength = 0;
 1994|       |
 1995|       |        // Binary format only supports up to 4GB of JSON, use that as a maximum
 1996|  6.15k|        if (mSceneLength >= std::numeric_limits<uint32_t>::max()) {
  ------------------
  |  Branch (1996:13): [True: 0, False: 6.15k]
  ------------------
 1997|      0|            throw DeadlyImportError("GLTF: JSON size greater than 4GB");
 1998|      0|        }
 1999|       |
 2000|       |        // read the scene data, ensure null termination
 2001|  6.15k|        sceneData.resize(mSceneLength + 1);
 2002|  6.15k|        sceneData[mSceneLength] = '\0';
 2003|       |
 2004|  6.15k|        if (stream.Read(&sceneData[0], 1, mSceneLength) != mSceneLength) {
  ------------------
  |  Branch (2004:13): [True: 0, False: 6.15k]
  ------------------
 2005|      0|            throw DeadlyImportError("GLTF: Could not read the file contents");
 2006|      0|        }
 2007|  6.15k|    }
 2008|       |
 2009|       |    // Smallest legal JSON file is "{}" Smallest loadable glTF file is larger than that but catch it later
 2010|  9.60k|    if (mSceneLength < 2) {
  ------------------
  |  Branch (2010:9): [True: 2, False: 9.60k]
  ------------------
 2011|      2|        throw DeadlyImportError("GLTF: No JSON file contents");
 2012|      2|    }
 2013|       |
 2014|       |    // parse the JSON document
 2015|  9.60k|    ASSIMP_LOG_DEBUG("Parsing GLTF2 JSON");
 2016|  9.60k|    Document doc;
 2017|  9.60k|    doc.ParseInsitu(&sceneData[0]);
 2018|       |
 2019|  9.60k|    if (doc.HasParseError()) {
  ------------------
  |  Branch (2019:9): [True: 1.23k, False: 8.36k]
  ------------------
 2020|  1.23k|        char buffer[32];
 2021|  1.23k|        ai_snprintf(buffer, 32, "%d", static_cast<int>(doc.GetErrorOffset()));
 2022|  1.23k|        throw DeadlyImportError("GLTF: JSON parse error, offset ", buffer, ": ", GetParseError_En(doc.GetParseError()));
 2023|  1.23k|    }
 2024|       |
 2025|  8.36k|    if (!doc.IsObject()) {
  ------------------
  |  Branch (2025:9): [True: 188, False: 8.18k]
  ------------------
 2026|    188|        throw DeadlyImportError("GLTF: JSON document root must be a JSON object");
 2027|    188|    }
 2028|       |
 2029|  8.18k|    return doc;
 2030|  8.36k|}
_ZN5glTF25Asset4LoadERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEb:
 2033|  3.53k|{
 2034|  3.53k|    mCurrentAssetDir.clear();
 2035|  3.53k|    if (0 != strncmp(pFile.c_str(), AI_MEMORYIO_MAGIC_FILENAME, AI_MEMORYIO_MAGIC_FILENAME_LENGTH)) {
  ------------------
  |  Branch (2035:9): [True: 0, False: 3.53k]
  ------------------
 2036|      0|        mCurrentAssetDir = glTFCommon::getCurrentAssetDir(pFile);
 2037|      0|    }
 2038|       |
 2039|  3.53k|    shared_ptr<IOStream> stream(OpenFile(pFile.c_str(), "rb", true));
 2040|  3.53k|    if (!stream) {
  ------------------
  |  Branch (2040:9): [True: 0, False: 3.53k]
  ------------------
 2041|      0|        throw DeadlyImportError("GLTF: Could not open file for reading");
 2042|      0|    }
 2043|       |
 2044|  3.53k|    std::vector<char> sceneData;
 2045|  3.53k|    rapidjson::Document doc = ReadDocument(*stream, isBinary, sceneData);
 2046|       |
 2047|       |    // If a schemaDocumentProvider is available, see if the glTF schema is present.
 2048|       |    // If so, use it to validate the document.
 2049|  3.53k|    if (mSchemaDocumentProvider) {
  ------------------
  |  Branch (2049:9): [True: 0, False: 3.53k]
  ------------------
 2050|      0|        if (const rapidjson::SchemaDocument *gltfSchema = mSchemaDocumentProvider->GetRemoteDocument("glTF.schema.json", 16)) {
  ------------------
  |  Branch (2050:46): [True: 0, False: 0]
  ------------------
 2051|       |            // The schemas are found here: https://github.com/KhronosGroup/glTF/tree/main/specification/2.0/schema
 2052|      0|            rapidjson::SchemaValidator validator(*gltfSchema);
 2053|      0|            if (!doc.Accept(validator)) {
  ------------------
  |  Branch (2053:17): [True: 0, False: 0]
  ------------------
 2054|      0|                rapidjson::StringBuffer pathBuffer;
 2055|      0|                validator.GetInvalidSchemaPointer().StringifyUriFragment(pathBuffer);
 2056|      0|                rapidjson::StringBuffer argumentBuffer;
 2057|      0|                validator.GetInvalidDocumentPointer().StringifyUriFragment(argumentBuffer);
 2058|      0|                throw DeadlyImportError("GLTF: The JSON document did not satisfy the glTF2 schema. Schema keyword: ", validator.GetInvalidSchemaKeyword(), ", document path: ", pathBuffer.GetString(), ", argument: ", argumentBuffer.GetString());
 2059|      0|            }
 2060|      0|        }
 2061|      0|    }
 2062|       |
 2063|       |    // Fill the buffer instance for the current file embedded contents
 2064|  3.53k|    if (mBodyLength > 0) {
  ------------------
  |  Branch (2064:9): [True: 1.47k, False: 2.05k]
  ------------------
 2065|  1.47k|        if (!mBodyBuffer->LoadFromStream(*stream, mBodyLength, mBodyOffset)) {
  ------------------
  |  Branch (2065:13): [True: 12, False: 1.46k]
  ------------------
 2066|     12|            throw DeadlyImportError("GLTF: Unable to read gltf file");
 2067|     12|        }
 2068|  1.47k|    }
 2069|       |
 2070|       |    // Load the metadata
 2071|  3.51k|    asset.Read(doc);
 2072|  3.51k|    ReadExtensionsUsed(doc);
 2073|  3.51k|    ReadExtensionsRequired(doc);
 2074|       |
 2075|  3.51k|#ifndef ASSIMP_ENABLE_DRACO
 2076|       |    // Is Draco required?
 2077|  3.51k|    if (extensionsRequired.KHR_draco_mesh_compression) {
  ------------------
  |  Branch (2077:9): [True: 2, False: 3.51k]
  ------------------
 2078|      2|        throw DeadlyImportError("GLTF: Draco mesh compression not supported.");
 2079|      2|    }
 2080|  3.51k|#endif
 2081|       |
 2082|       |    // Prepare the dictionaries
 2083|  51.9k|    for (size_t i = 0; i < mDicts.size(); ++i) {
  ------------------
  |  Branch (2083:24): [True: 48.4k, False: 3.51k]
  ------------------
 2084|  48.4k|        mDicts[i]->AttachToDocument(doc);
 2085|  48.4k|    }
 2086|       |
 2087|       |    // Read the "extensions" property, then add it to each scene's metadata.
 2088|  3.51k|    CustomExtension customExtensions;
 2089|  3.51k|    if (Value *extensionsObject = FindObject(doc, "extensions")) {
  ------------------
  |  Branch (2089:16): [True: 0, False: 3.51k]
  ------------------
 2090|      0|        customExtensions = glTF2::ReadExtensions("extensions", *extensionsObject);
 2091|      0|    }
 2092|       |
 2093|       |    // Read the "scene" property, which specifies which scene to load
 2094|       |    // and recursively load everything referenced by it
 2095|  3.51k|    unsigned int sceneIndex = 0;
 2096|  3.51k|    Value *curScene = FindUInt(doc, "scene");
 2097|  3.51k|    if (nullptr != curScene) {
  ------------------
  |  Branch (2097:9): [True: 2.03k, False: 1.48k]
  ------------------
 2098|  2.03k|        sceneIndex = curScene->GetUint();
 2099|  2.03k|    }
 2100|       |
 2101|  3.51k|    if (Value *scenesArray = FindArray(doc, "scenes")) {
  ------------------
  |  Branch (2101:16): [True: 3.24k, False: 275]
  ------------------
 2102|  3.24k|        if (sceneIndex < scenesArray->Size()) {
  ------------------
  |  Branch (2102:13): [True: 3.18k, False: 52]
  ------------------
 2103|  3.18k|            this->scene = scenes.Retrieve(sceneIndex);
 2104|       |
 2105|  3.18k|            this->scene->customExtensions = customExtensions;
 2106|  3.18k|        }
 2107|  3.24k|    }
 2108|       |
 2109|  3.51k|    if (Value *skinsArray = FindArray(doc, "skins")) {
  ------------------
  |  Branch (2109:16): [True: 645, False: 2.87k]
  ------------------
 2110|  4.32k|        for (unsigned int i = 0; i < skinsArray->Size(); ++i) {
  ------------------
  |  Branch (2110:34): [True: 3.68k, False: 645]
  ------------------
 2111|  3.68k|            skins.Retrieve(i);
 2112|  3.68k|        }
 2113|    645|    }
 2114|       |
 2115|  3.51k|    if (Value *animsArray = FindArray(doc, "animations")) {
  ------------------
  |  Branch (2115:16): [True: 291, False: 3.22k]
  ------------------
 2116|    644|        for (unsigned int i = 0; i < animsArray->Size(); ++i) {
  ------------------
  |  Branch (2116:34): [True: 353, False: 291]
  ------------------
 2117|    353|            animations.Retrieve(i);
 2118|    353|        }
 2119|    291|    }
 2120|       |
 2121|       |    // Clean up
 2122|  36.4k|    for (size_t i = 0; i < mDicts.size(); ++i) {
  ------------------
  |  Branch (2122:24): [True: 32.9k, False: 3.51k]
  ------------------
 2123|  32.9k|        mDicts[i]->DetachFromDocument();
 2124|  32.9k|    }
 2125|  3.51k|}
_ZN5glTF25Asset7CanReadERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEb:
 2127|  6.07k|inline bool Asset::CanRead(const std::string &pFile, bool isBinary) {
 2128|  6.07k|    try {
 2129|  6.07k|        shared_ptr<IOStream> stream(OpenFile(pFile.c_str(), "rb", true));
 2130|  6.07k|        if (!stream) {
  ------------------
  |  Branch (2130:13): [True: 0, False: 6.07k]
  ------------------
 2131|      0|            return false;
 2132|      0|        }
 2133|  6.07k|        std::vector<char> sceneData;
 2134|  6.07k|        rapidjson::Document doc = ReadDocument(*stream, isBinary, sceneData);
 2135|  6.07k|        asset.Read(doc);
 2136|  6.07k|    } catch (...) {
 2137|  2.54k|        return false;
 2138|  2.54k|    }
 2139|  3.53k|    return true;
 2140|  6.07k|}
_ZN5glTF25Asset11SetAsBinaryEv:
 2142|  3.45k|inline void Asset::SetAsBinary() {
 2143|  3.45k|    if (!mBodyBuffer) {
  ------------------
  |  Branch (2143:9): [True: 3.45k, False: 0]
  ------------------
 2144|  3.45k|        mBodyBuffer = buffers.Create("binary_glTF");
 2145|  3.45k|        mBodyBuffer->MarkAsSpecial();
 2146|  3.45k|    }
 2147|  3.45k|}
_ZN5glTF25Asset22ReadExtensionsRequiredERN9rapidjson15GenericDocumentINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEES6_EE:
 2154|  3.47k|inline void Asset::ReadExtensionsRequired(Document &doc) {
 2155|  3.47k|    Value *extsRequired = FindArray(doc, "extensionsRequired");
 2156|  3.47k|    if (nullptr == extsRequired) {
  ------------------
  |  Branch (2156:9): [True: 3.44k, False: 30]
  ------------------
 2157|  3.44k|        return;
 2158|  3.44k|    }
 2159|       |
 2160|     30|    std::gltf_unordered_map<std::string, bool> exts;
 2161|  2.81k|    for (unsigned int i = 0; i < extsRequired->Size(); ++i) {
  ------------------
  |  Branch (2161:30): [True: 2.78k, False: 30]
  ------------------
 2162|  2.78k|        if ((*extsRequired)[i].IsString()) {
  ------------------
  |  Branch (2162:13): [True: 2.76k, False: 28]
  ------------------
 2163|  2.76k|            exts[(*extsRequired)[i].GetString()] = true;
 2164|  2.76k|        }
 2165|  2.78k|    }
 2166|       |
 2167|     30|    CHECK_REQUIRED_EXT(KHR_draco_mesh_compression);
  ------------------
  |  | 2152|     30|    if (exts.find(#EXT) != exts.end()) extensionsRequired.EXT = true;
  |  |  ------------------
  |  |  |  Branch (2152:9): [True: 2, False: 28]
  |  |  ------------------
  ------------------
 2168|     30|    CHECK_REQUIRED_EXT(KHR_texture_basisu);
  ------------------
  |  | 2152|     30|    if (exts.find(#EXT) != exts.end()) extensionsRequired.EXT = true;
  |  |  ------------------
  |  |  |  Branch (2152:9): [True: 0, False: 30]
  |  |  ------------------
  ------------------
 2169|     30|    CHECK_REQUIRED_EXT(EXT_texture_webp);
  ------------------
  |  | 2152|     30|    if (exts.find(#EXT) != exts.end()) extensionsRequired.EXT = true;
  |  |  ------------------
  |  |  |  Branch (2152:9): [True: 0, False: 30]
  |  |  ------------------
  ------------------
 2170|       |
 2171|     30|#undef CHECK_REQUIRED_EXT
 2172|     30|}
_ZN5glTF25Asset18ReadExtensionsUsedERN9rapidjson15GenericDocumentINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEES6_EE:
 2174|  3.47k|inline void Asset::ReadExtensionsUsed(Document &doc) {
 2175|  3.47k|    Value *extsUsed = FindArray(doc, "extensionsUsed");
 2176|  3.47k|    if (!extsUsed) return;
  ------------------
  |  Branch (2176:9): [True: 2.85k, False: 616]
  ------------------
 2177|       |
 2178|    616|    std::gltf_unordered_map<std::string, bool> exts;
 2179|       |
 2180|  4.87k|    for (unsigned int i = 0; i < extsUsed->Size(); ++i) {
  ------------------
  |  Branch (2180:30): [True: 4.25k, False: 616]
  ------------------
 2181|  4.25k|        if ((*extsUsed)[i].IsString()) {
  ------------------
  |  Branch (2181:13): [True: 4.24k, False: 13]
  ------------------
 2182|  4.24k|            exts[(*extsUsed)[i].GetString()] = true;
 2183|  4.24k|        }
 2184|  4.25k|    }
 2185|       |
 2186|    616|    CHECK_EXT(KHR_materials_pbrSpecularGlossiness);
  ------------------
  |  |  237|    616|    if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true;
  |  |  ------------------
  |  |  |  Branch (237:9): [True: 3, False: 613]
  |  |  ------------------
  ------------------
 2187|    616|    CHECK_EXT(KHR_materials_specular);
  ------------------
  |  |  237|    616|    if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true;
  |  |  ------------------
  |  |  |  Branch (237:9): [True: 0, False: 616]
  |  |  ------------------
  ------------------
 2188|    616|    CHECK_EXT(KHR_materials_unlit);
  ------------------
  |  |  237|    616|    if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true;
  |  |  ------------------
  |  |  |  Branch (237:9): [True: 0, False: 616]
  |  |  ------------------
  ------------------
 2189|    616|    CHECK_EXT(KHR_lights_punctual);
  ------------------
  |  |  237|    616|    if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true;
  |  |  ------------------
  |  |  |  Branch (237:9): [True: 0, False: 616]
  |  |  ------------------
  ------------------
 2190|    616|    CHECK_EXT(KHR_texture_transform);
  ------------------
  |  |  237|    616|    if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true;
  |  |  ------------------
  |  |  |  Branch (237:9): [True: 6, False: 610]
  |  |  ------------------
  ------------------
 2191|    616|    CHECK_EXT(KHR_materials_sheen);
  ------------------
  |  |  237|    616|    if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true;
  |  |  ------------------
  |  |  |  Branch (237:9): [True: 0, False: 616]
  |  |  ------------------
  ------------------
 2192|    616|    CHECK_EXT(KHR_materials_clearcoat);
  ------------------
  |  |  237|    616|    if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true;
  |  |  ------------------
  |  |  |  Branch (237:9): [True: 1, False: 615]
  |  |  ------------------
  ------------------
 2193|    616|    CHECK_EXT(KHR_materials_transmission);
  ------------------
  |  |  237|    616|    if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true;
  |  |  ------------------
  |  |  |  Branch (237:9): [True: 0, False: 616]
  |  |  ------------------
  ------------------
 2194|    616|    CHECK_EXT(KHR_materials_volume);
  ------------------
  |  |  237|    616|    if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true;
  |  |  ------------------
  |  |  |  Branch (237:9): [True: 219, False: 397]
  |  |  ------------------
  ------------------
 2195|    616|    CHECK_EXT(KHR_materials_ior);
  ------------------
  |  |  237|    616|    if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true;
  |  |  ------------------
  |  |  |  Branch (237:9): [True: 0, False: 616]
  |  |  ------------------
  ------------------
 2196|    616|    CHECK_EXT(KHR_materials_emissive_strength);
  ------------------
  |  |  237|    616|    if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true;
  |  |  ------------------
  |  |  |  Branch (237:9): [True: 0, False: 616]
  |  |  ------------------
  ------------------
 2197|    616|    CHECK_EXT(KHR_materials_anisotropy);
  ------------------
  |  |  237|    616|    if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true;
  |  |  ------------------
  |  |  |  Branch (237:9): [True: 0, False: 616]
  |  |  ------------------
  ------------------
 2198|    616|    CHECK_EXT(KHR_draco_mesh_compression);
  ------------------
  |  |  237|    616|    if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true;
  |  |  ------------------
  |  |  |  Branch (237:9): [True: 79, False: 537]
  |  |  ------------------
  ------------------
 2199|    616|    CHECK_EXT(KHR_texture_basisu);
  ------------------
  |  |  237|    616|    if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true;
  |  |  ------------------
  |  |  |  Branch (237:9): [True: 0, False: 616]
  |  |  ------------------
  ------------------
 2200|    616|    CHECK_EXT(EXT_texture_webp);
  ------------------
  |  |  237|    616|    if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true;
  |  |  ------------------
  |  |  |  Branch (237:9): [True: 0, False: 616]
  |  |  ------------------
  ------------------
 2201|       |
 2202|    616|#undef CHECK_EXT
 2203|    616|}
_ZN5glTF25Asset8OpenFileERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEPKcb:
 2205|  9.87k|inline IOStream *Asset::OpenFile(const std::string &path, const char *mode, bool /*absolute*/) {
 2206|  9.87k|#ifdef ASSIMP_API
 2207|  9.87k|    return mIOSystem->Open(path, mode);
 2208|       |#else
 2209|       |    if (path.size() < 2) return nullptr;
 2210|       |    if (!absolute && path[1] != ':' && path[0] != '/') { // relative?
 2211|       |        path = mCurrentAssetDir + path;
 2212|       |    }
 2213|       |    FILE *f = fopen(path.c_str(), mode);
 2214|       |    return f ? new IOStream(f) : nullptr;
 2215|       |#endif
 2216|  9.87k|}
_ZN5glTF28Accessor7Indexer8GetValueIjEET_i:
 1117|  28.6k|T Accessor::Indexer::GetValue(int i) {
 1118|  28.6k|    ai_assert(data);
 1119|  28.6k|    if (i * stride >= accessor.GetMaxByteSize()) {
  ------------------
  |  Branch (1119:9): [True: 0, False: 28.6k]
  ------------------
 1120|      0|        throw DeadlyImportError("GLTF: Invalid index ", i, ", count out of range for buffer with stride ", stride, " and size ", accessor.GetMaxByteSize(), ".");
 1121|      0|    }
 1122|       |    // Ensure that the memcpy doesn't overwrite the local.
 1123|  28.6k|    const size_t sizeToCopy = std::min(elemSize, sizeof(T));
 1124|  28.6k|    T value = T();
 1125|       |    // Assume platform endianness matches GLTF binary data (which is little-endian).
 1126|  28.6k|    memcpy(&value, data + i * stride, sizeToCopy);
 1127|  28.6k|    return value;
 1128|  28.6k|}
_ZN5glTF28LazyDictINS_8AccessorEE16AttachToDocumentERN9rapidjson15GenericDocumentINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEES8_EE:
  405|  3.47k|inline void LazyDict<T>::AttachToDocument(Document &doc) {
  406|  3.47k|    Value *container = nullptr;
  407|  3.47k|    const char *context = nullptr;
  408|       |
  409|  3.47k|    if (mExtId) {
  ------------------
  |  Branch (409:9): [True: 0, False: 3.47k]
  ------------------
  410|      0|        if (Value *exts = FindObject(doc, "extensions")) {
  ------------------
  |  Branch (410:20): [True: 0, False: 0]
  ------------------
  411|      0|            container = FindObjectInContext(*exts, mExtId, "extensions");
  412|      0|            context = mExtId;
  413|      0|        }
  414|  3.47k|    } else {
  415|  3.47k|        container = &doc;
  416|  3.47k|        context = "the document";
  417|  3.47k|    }
  418|       |
  419|  3.47k|    if (container) {
  ------------------
  |  Branch (419:9): [True: 3.47k, False: 0]
  ------------------
  420|  3.47k|        mDict = FindArrayInContext(*container, mDictId, context);
  421|  3.47k|    }
  422|  3.47k|}
_ZN5glTF28LazyDictINS_8AccessorEE18DetachFromDocumentEv:
  425|  2.35k|inline void LazyDict<T>::DetachFromDocument() {
  426|  2.35k|    mDict = nullptr;
  427|  2.35k|}
_ZN5glTF28LazyDictINS_9AnimationEE16AttachToDocumentERN9rapidjson15GenericDocumentINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEES8_EE:
  405|  3.46k|inline void LazyDict<T>::AttachToDocument(Document &doc) {
  406|  3.46k|    Value *container = nullptr;
  407|  3.46k|    const char *context = nullptr;
  408|       |
  409|  3.46k|    if (mExtId) {
  ------------------
  |  Branch (409:9): [True: 0, False: 3.46k]
  ------------------
  410|      0|        if (Value *exts = FindObject(doc, "extensions")) {
  ------------------
  |  Branch (410:20): [True: 0, False: 0]
  ------------------
  411|      0|            container = FindObjectInContext(*exts, mExtId, "extensions");
  412|      0|            context = mExtId;
  413|      0|        }
  414|  3.46k|    } else {
  415|  3.46k|        container = &doc;
  416|  3.46k|        context = "the document";
  417|  3.46k|    }
  418|       |
  419|  3.46k|    if (container) {
  ------------------
  |  Branch (419:9): [True: 3.46k, False: 0]
  ------------------
  420|  3.46k|        mDict = FindArrayInContext(*container, mDictId, context);
  421|  3.46k|    }
  422|  3.46k|}
_ZN5glTF28LazyDictINS_9AnimationEE18DetachFromDocumentEv:
  425|  2.35k|inline void LazyDict<T>::DetachFromDocument() {
  426|  2.35k|    mDict = nullptr;
  427|  2.35k|}
_ZN5glTF28LazyDictINS_6BufferEE16AttachToDocumentERN9rapidjson15GenericDocumentINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEES8_EE:
  405|  3.46k|inline void LazyDict<T>::AttachToDocument(Document &doc) {
  406|  3.46k|    Value *container = nullptr;
  407|  3.46k|    const char *context = nullptr;
  408|       |
  409|  3.46k|    if (mExtId) {
  ------------------
  |  Branch (409:9): [True: 0, False: 3.46k]
  ------------------
  410|      0|        if (Value *exts = FindObject(doc, "extensions")) {
  ------------------
  |  Branch (410:20): [True: 0, False: 0]
  ------------------
  411|      0|            container = FindObjectInContext(*exts, mExtId, "extensions");
  412|      0|            context = mExtId;
  413|      0|        }
  414|  3.46k|    } else {
  415|  3.46k|        container = &doc;
  416|  3.46k|        context = "the document";
  417|  3.46k|    }
  418|       |
  419|  3.46k|    if (container) {
  ------------------
  |  Branch (419:9): [True: 3.46k, False: 0]
  ------------------
  420|  3.46k|        mDict = FindArrayInContext(*container, mDictId, context);
  421|  3.46k|    }
  422|  3.46k|}
_ZN5glTF28LazyDictINS_6BufferEE18DetachFromDocumentEv:
  425|  2.35k|inline void LazyDict<T>::DetachFromDocument() {
  426|  2.35k|    mDict = nullptr;
  427|  2.35k|}
_ZN5glTF28LazyDictINS_10BufferViewEE16AttachToDocumentERN9rapidjson15GenericDocumentINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEES8_EE:
  405|  3.46k|inline void LazyDict<T>::AttachToDocument(Document &doc) {
  406|  3.46k|    Value *container = nullptr;
  407|  3.46k|    const char *context = nullptr;
  408|       |
  409|  3.46k|    if (mExtId) {
  ------------------
  |  Branch (409:9): [True: 0, False: 3.46k]
  ------------------
  410|      0|        if (Value *exts = FindObject(doc, "extensions")) {
  ------------------
  |  Branch (410:20): [True: 0, False: 0]
  ------------------
  411|      0|            container = FindObjectInContext(*exts, mExtId, "extensions");
  412|      0|            context = mExtId;
  413|      0|        }
  414|  3.46k|    } else {
  415|  3.46k|        container = &doc;
  416|  3.46k|        context = "the document";
  417|  3.46k|    }
  418|       |
  419|  3.46k|    if (container) {
  ------------------
  |  Branch (419:9): [True: 3.46k, False: 0]
  ------------------
  420|  3.46k|        mDict = FindArrayInContext(*container, mDictId, context);
  421|  3.46k|    }
  422|  3.46k|}
_ZN5glTF28LazyDictINS_10BufferViewEE18DetachFromDocumentEv:
  425|  2.35k|inline void LazyDict<T>::DetachFromDocument() {
  426|  2.35k|    mDict = nullptr;
  427|  2.35k|}
_ZN5glTF28LazyDictINS_6CameraEE16AttachToDocumentERN9rapidjson15GenericDocumentINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEES8_EE:
  405|  3.46k|inline void LazyDict<T>::AttachToDocument(Document &doc) {
  406|  3.46k|    Value *container = nullptr;
  407|  3.46k|    const char *context = nullptr;
  408|       |
  409|  3.46k|    if (mExtId) {
  ------------------
  |  Branch (409:9): [True: 0, False: 3.46k]
  ------------------
  410|      0|        if (Value *exts = FindObject(doc, "extensions")) {
  ------------------
  |  Branch (410:20): [True: 0, False: 0]
  ------------------
  411|      0|            container = FindObjectInContext(*exts, mExtId, "extensions");
  412|      0|            context = mExtId;
  413|      0|        }
  414|  3.46k|    } else {
  415|  3.46k|        container = &doc;
  416|  3.46k|        context = "the document";
  417|  3.46k|    }
  418|       |
  419|  3.46k|    if (container) {
  ------------------
  |  Branch (419:9): [True: 3.46k, False: 0]
  ------------------
  420|  3.46k|        mDict = FindArrayInContext(*container, mDictId, context);
  421|  3.46k|    }
  422|  3.46k|}
_ZN5glTF28LazyDictINS_6CameraEE18DetachFromDocumentEv:
  425|  2.35k|inline void LazyDict<T>::DetachFromDocument() {
  426|  2.35k|    mDict = nullptr;
  427|  2.35k|}
_ZN5glTF28LazyDictINS_5LightEE16AttachToDocumentERN9rapidjson15GenericDocumentINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEES8_EE:
  405|  3.46k|inline void LazyDict<T>::AttachToDocument(Document &doc) {
  406|  3.46k|    Value *container = nullptr;
  407|  3.46k|    const char *context = nullptr;
  408|       |
  409|  3.46k|    if (mExtId) {
  ------------------
  |  Branch (409:9): [True: 3.46k, False: 0]
  ------------------
  410|  3.46k|        if (Value *exts = FindObject(doc, "extensions")) {
  ------------------
  |  Branch (410:20): [True: 0, False: 3.46k]
  ------------------
  411|      0|            container = FindObjectInContext(*exts, mExtId, "extensions");
  412|      0|            context = mExtId;
  413|      0|        }
  414|  3.46k|    } else {
  415|      0|        container = &doc;
  416|      0|        context = "the document";
  417|      0|    }
  418|       |
  419|  3.46k|    if (container) {
  ------------------
  |  Branch (419:9): [True: 0, False: 3.46k]
  ------------------
  420|      0|        mDict = FindArrayInContext(*container, mDictId, context);
  421|      0|    }
  422|  3.46k|}
_ZN5glTF28LazyDictINS_5LightEE18DetachFromDocumentEv:
  425|  2.35k|inline void LazyDict<T>::DetachFromDocument() {
  426|  2.35k|    mDict = nullptr;
  427|  2.35k|}
_ZN5glTF28LazyDictINS_5ImageEE16AttachToDocumentERN9rapidjson15GenericDocumentINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEES8_EE:
  405|  3.46k|inline void LazyDict<T>::AttachToDocument(Document &doc) {
  406|  3.46k|    Value *container = nullptr;
  407|  3.46k|    const char *context = nullptr;
  408|       |
  409|  3.46k|    if (mExtId) {
  ------------------
  |  Branch (409:9): [True: 0, False: 3.46k]
  ------------------
  410|      0|        if (Value *exts = FindObject(doc, "extensions")) {
  ------------------
  |  Branch (410:20): [True: 0, False: 0]
  ------------------
  411|      0|            container = FindObjectInContext(*exts, mExtId, "extensions");
  412|      0|            context = mExtId;
  413|      0|        }
  414|  3.46k|    } else {
  415|  3.46k|        container = &doc;
  416|  3.46k|        context = "the document";
  417|  3.46k|    }
  418|       |
  419|  3.46k|    if (container) {
  ------------------
  |  Branch (419:9): [True: 3.46k, False: 0]
  ------------------
  420|  3.46k|        mDict = FindArrayInContext(*container, mDictId, context);
  421|  3.46k|    }
  422|  3.46k|}
_ZN5glTF28LazyDictINS_5ImageEE18DetachFromDocumentEv:
  425|  2.35k|inline void LazyDict<T>::DetachFromDocument() {
  426|  2.35k|    mDict = nullptr;
  427|  2.35k|}
_ZN5glTF28LazyDictINS_8MaterialEE16AttachToDocumentERN9rapidjson15GenericDocumentINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEES8_EE:
  405|  3.46k|inline void LazyDict<T>::AttachToDocument(Document &doc) {
  406|  3.46k|    Value *container = nullptr;
  407|  3.46k|    const char *context = nullptr;
  408|       |
  409|  3.46k|    if (mExtId) {
  ------------------
  |  Branch (409:9): [True: 0, False: 3.46k]
  ------------------
  410|      0|        if (Value *exts = FindObject(doc, "extensions")) {
  ------------------
  |  Branch (410:20): [True: 0, False: 0]
  ------------------
  411|      0|            container = FindObjectInContext(*exts, mExtId, "extensions");
  412|      0|            context = mExtId;
  413|      0|        }
  414|  3.46k|    } else {
  415|  3.46k|        container = &doc;
  416|  3.46k|        context = "the document";
  417|  3.46k|    }
  418|       |
  419|  3.46k|    if (container) {
  ------------------
  |  Branch (419:9): [True: 3.46k, False: 0]
  ------------------
  420|  3.46k|        mDict = FindArrayInContext(*container, mDictId, context);
  421|  3.46k|    }
  422|  3.46k|}
_ZN5glTF28LazyDictINS_8MaterialEE18DetachFromDocumentEv:
  425|  2.35k|inline void LazyDict<T>::DetachFromDocument() {
  426|  2.35k|    mDict = nullptr;
  427|  2.35k|}
_ZN5glTF28LazyDictINS_4MeshEE16AttachToDocumentERN9rapidjson15GenericDocumentINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEES8_EE:
  405|  3.46k|inline void LazyDict<T>::AttachToDocument(Document &doc) {
  406|  3.46k|    Value *container = nullptr;
  407|  3.46k|    const char *context = nullptr;
  408|       |
  409|  3.46k|    if (mExtId) {
  ------------------
  |  Branch (409:9): [True: 0, False: 3.46k]
  ------------------
  410|      0|        if (Value *exts = FindObject(doc, "extensions")) {
  ------------------
  |  Branch (410:20): [True: 0, False: 0]
  ------------------
  411|      0|            container = FindObjectInContext(*exts, mExtId, "extensions");
  412|      0|            context = mExtId;
  413|      0|        }
  414|  3.46k|    } else {
  415|  3.46k|        container = &doc;
  416|  3.46k|        context = "the document";
  417|  3.46k|    }
  418|       |
  419|  3.46k|    if (container) {
  ------------------
  |  Branch (419:9): [True: 3.46k, False: 0]
  ------------------
  420|  3.46k|        mDict = FindArrayInContext(*container, mDictId, context);
  421|  3.46k|    }
  422|  3.46k|}
_ZN5glTF28LazyDictINS_4MeshEE18DetachFromDocumentEv:
  425|  2.35k|inline void LazyDict<T>::DetachFromDocument() {
  426|  2.35k|    mDict = nullptr;
  427|  2.35k|}
_ZN5glTF28LazyDictINS_4NodeEE16AttachToDocumentERN9rapidjson15GenericDocumentINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEES8_EE:
  405|  3.46k|inline void LazyDict<T>::AttachToDocument(Document &doc) {
  406|  3.46k|    Value *container = nullptr;
  407|  3.46k|    const char *context = nullptr;
  408|       |
  409|  3.46k|    if (mExtId) {
  ------------------
  |  Branch (409:9): [True: 0, False: 3.46k]
  ------------------
  410|      0|        if (Value *exts = FindObject(doc, "extensions")) {
  ------------------
  |  Branch (410:20): [True: 0, False: 0]
  ------------------
  411|      0|            container = FindObjectInContext(*exts, mExtId, "extensions");
  412|      0|            context = mExtId;
  413|      0|        }
  414|  3.46k|    } else {
  415|  3.46k|        container = &doc;
  416|  3.46k|        context = "the document";
  417|  3.46k|    }
  418|       |
  419|  3.46k|    if (container) {
  ------------------
  |  Branch (419:9): [True: 3.46k, False: 0]
  ------------------
  420|  3.46k|        mDict = FindArrayInContext(*container, mDictId, context);
  421|  3.46k|    }
  422|  3.46k|}
_ZN5glTF28LazyDictINS_4NodeEE18DetachFromDocumentEv:
  425|  2.35k|inline void LazyDict<T>::DetachFromDocument() {
  426|  2.35k|    mDict = nullptr;
  427|  2.35k|}
_ZN5glTF28LazyDictINS_7SamplerEE16AttachToDocumentERN9rapidjson15GenericDocumentINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEES8_EE:
  405|  3.46k|inline void LazyDict<T>::AttachToDocument(Document &doc) {
  406|  3.46k|    Value *container = nullptr;
  407|  3.46k|    const char *context = nullptr;
  408|       |
  409|  3.46k|    if (mExtId) {
  ------------------
  |  Branch (409:9): [True: 0, False: 3.46k]
  ------------------
  410|      0|        if (Value *exts = FindObject(doc, "extensions")) {
  ------------------
  |  Branch (410:20): [True: 0, False: 0]
  ------------------
  411|      0|            container = FindObjectInContext(*exts, mExtId, "extensions");
  412|      0|            context = mExtId;
  413|      0|        }
  414|  3.46k|    } else {
  415|  3.46k|        container = &doc;
  416|  3.46k|        context = "the document";
  417|  3.46k|    }
  418|       |
  419|  3.46k|    if (container) {
  ------------------
  |  Branch (419:9): [True: 3.46k, False: 0]
  ------------------
  420|  3.46k|        mDict = FindArrayInContext(*container, mDictId, context);
  421|  3.46k|    }
  422|  3.46k|}
_ZN5glTF28LazyDictINS_7SamplerEE18DetachFromDocumentEv:
  425|  2.35k|inline void LazyDict<T>::DetachFromDocument() {
  426|  2.35k|    mDict = nullptr;
  427|  2.35k|}
_ZN5glTF28LazyDictINS_5SceneEE16AttachToDocumentERN9rapidjson15GenericDocumentINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEES8_EE:
  405|  3.45k|inline void LazyDict<T>::AttachToDocument(Document &doc) {
  406|  3.45k|    Value *container = nullptr;
  407|  3.45k|    const char *context = nullptr;
  408|       |
  409|  3.45k|    if (mExtId) {
  ------------------
  |  Branch (409:9): [True: 0, False: 3.45k]
  ------------------
  410|      0|        if (Value *exts = FindObject(doc, "extensions")) {
  ------------------
  |  Branch (410:20): [True: 0, False: 0]
  ------------------
  411|      0|            container = FindObjectInContext(*exts, mExtId, "extensions");
  412|      0|            context = mExtId;
  413|      0|        }
  414|  3.45k|    } else {
  415|  3.45k|        container = &doc;
  416|  3.45k|        context = "the document";
  417|  3.45k|    }
  418|       |
  419|  3.45k|    if (container) {
  ------------------
  |  Branch (419:9): [True: 3.45k, False: 0]
  ------------------
  420|  3.45k|        mDict = FindArrayInContext(*container, mDictId, context);
  421|  3.45k|    }
  422|  3.45k|}
_ZN5glTF28LazyDictINS_5SceneEE18DetachFromDocumentEv:
  425|  2.35k|inline void LazyDict<T>::DetachFromDocument() {
  426|  2.35k|    mDict = nullptr;
  427|  2.35k|}
_ZN5glTF28LazyDictINS_4SkinEE16AttachToDocumentERN9rapidjson15GenericDocumentINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEES8_EE:
  405|  3.45k|inline void LazyDict<T>::AttachToDocument(Document &doc) {
  406|  3.45k|    Value *container = nullptr;
  407|  3.45k|    const char *context = nullptr;
  408|       |
  409|  3.45k|    if (mExtId) {
  ------------------
  |  Branch (409:9): [True: 0, False: 3.45k]
  ------------------
  410|      0|        if (Value *exts = FindObject(doc, "extensions")) {
  ------------------
  |  Branch (410:20): [True: 0, False: 0]
  ------------------
  411|      0|            container = FindObjectInContext(*exts, mExtId, "extensions");
  412|      0|            context = mExtId;
  413|      0|        }
  414|  3.45k|    } else {
  415|  3.45k|        container = &doc;
  416|  3.45k|        context = "the document";
  417|  3.45k|    }
  418|       |
  419|  3.45k|    if (container) {
  ------------------
  |  Branch (419:9): [True: 3.45k, False: 0]
  ------------------
  420|  3.45k|        mDict = FindArrayInContext(*container, mDictId, context);
  421|  3.45k|    }
  422|  3.45k|}
_ZN5glTF28LazyDictINS_4SkinEE18DetachFromDocumentEv:
  425|  2.35k|inline void LazyDict<T>::DetachFromDocument() {
  426|  2.35k|    mDict = nullptr;
  427|  2.35k|}
_ZN5glTF28LazyDictINS_7TextureEE16AttachToDocumentERN9rapidjson15GenericDocumentINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEES8_EE:
  405|  3.45k|inline void LazyDict<T>::AttachToDocument(Document &doc) {
  406|  3.45k|    Value *container = nullptr;
  407|  3.45k|    const char *context = nullptr;
  408|       |
  409|  3.45k|    if (mExtId) {
  ------------------
  |  Branch (409:9): [True: 0, False: 3.45k]
  ------------------
  410|      0|        if (Value *exts = FindObject(doc, "extensions")) {
  ------------------
  |  Branch (410:20): [True: 0, False: 0]
  ------------------
  411|      0|            container = FindObjectInContext(*exts, mExtId, "extensions");
  412|      0|            context = mExtId;
  413|      0|        }
  414|  3.45k|    } else {
  415|  3.45k|        container = &doc;
  416|  3.45k|        context = "the document";
  417|  3.45k|    }
  418|       |
  419|  3.45k|    if (container) {
  ------------------
  |  Branch (419:9): [True: 3.45k, False: 0]
  ------------------
  420|  3.45k|        mDict = FindArrayInContext(*container, mDictId, context);
  421|  3.45k|    }
  422|  3.45k|}
_ZN5glTF28LazyDictINS_7TextureEE18DetachFromDocumentEv:
  425|  2.35k|inline void LazyDict<T>::DetachFromDocument() {
  426|  2.35k|    mDict = nullptr;
  427|  2.35k|}
_ZN5glTF28LazyDictINS_6BufferEE8RetrieveEj:
  473|  8.05k|Ref<T> LazyDict<T>::Retrieve(unsigned int i) {
  474|  8.05k|    typename Dict::iterator it = mObjsByOIndex.find(i);
  475|  8.05k|    if (it != mObjsByOIndex.end()) { // already created?
  ------------------
  |  Branch (475:9): [True: 6.54k, False: 1.51k]
  ------------------
  476|  6.54k|        return Ref<T>(mObjs, it->second);
  477|  6.54k|    }
  478|       |
  479|       |    // read it from the JSON object
  480|  1.51k|    if (!mDict) {
  ------------------
  |  Branch (480:9): [True: 3, False: 1.50k]
  ------------------
  481|      3|        throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\"");
  482|      3|    }
  483|       |
  484|  1.50k|    if (!mDict->IsArray()) {
  ------------------
  |  Branch (484:9): [True: 0, False: 1.50k]
  ------------------
  485|      0|        throw DeadlyImportError("GLTF: Field \"", mDictId, "\"  is not an array");
  486|      0|    }
  487|       |
  488|  1.50k|    if (i >= mDict->Size()) {
  ------------------
  |  Branch (488:9): [True: 32, False: 1.47k]
  ------------------
  489|     32|        throw DeadlyImportError("GLTF: Array index ", i, " is out of bounds (", mDict->Size(), ") for \"", mDictId, "\"");
  490|     32|    }
  491|       |
  492|  1.47k|    Value &obj = (*mDict)[i];
  493|       |
  494|  1.47k|    if (!obj.IsObject()) {
  ------------------
  |  Branch (494:9): [True: 1, False: 1.47k]
  ------------------
  495|      1|        throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" is not a JSON object");
  496|      1|    }
  497|       |
  498|  1.47k|    if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) {
  ------------------
  |  Branch (498:9): [True: 0, False: 1.47k]
  ------------------
  499|      0|        throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" has recursive reference to itself");
  500|      0|    }
  501|  1.47k|    mRecursiveReferenceCheck.insert(i);
  502|       |
  503|       |    // Unique ptr prevents memory leak in case of Read throws an exception
  504|  1.47k|    auto inst = std::unique_ptr<T>(new T());
  505|       |    // Try to make this human readable so it can be used in error messages.
  506|  1.47k|    inst->id = std::string(mDictId) + "[" + ai_to_string(i) + "]";
  507|  1.47k|    inst->oIndex = i;
  508|  1.47k|    ReadMember(obj, "name", inst->name);
  509|  1.47k|    inst->Read(obj, mAsset);
  510|  1.47k|    inst->ReadExtensions(obj);
  511|  1.47k|    inst->ReadExtras(obj);
  512|       |
  513|  1.47k|    Ref<T> result = Add(inst.release());
  514|  1.47k|    mRecursiveReferenceCheck.erase(i);
  515|  1.47k|    return result;
  516|  1.47k|}
_ZN5glTF28LazyDictINS_6BufferEE3AddEPS1_:
  536|  4.52k|Ref<T> LazyDict<T>::Add(T *obj) {
  537|  4.52k|    unsigned int idx = unsigned(mObjs.size());
  538|  4.52k|    mObjs.push_back(obj);
  539|  4.52k|    mObjsByOIndex[obj->oIndex] = idx;
  540|  4.52k|    mObjsById[obj->id] = idx;
  541|  4.52k|    return Ref<T>(mObjs, idx);
  542|  4.52k|}
_ZN5glTF28LazyDictINS_10BufferViewEE8RetrieveEj:
  473|  8.74k|Ref<T> LazyDict<T>::Retrieve(unsigned int i) {
  474|  8.74k|    typename Dict::iterator it = mObjsByOIndex.find(i);
  475|  8.74k|    if (it != mObjsByOIndex.end()) { // already created?
  ------------------
  |  Branch (475:9): [True: 651, False: 8.09k]
  ------------------
  476|    651|        return Ref<T>(mObjs, it->second);
  477|    651|    }
  478|       |
  479|       |    // read it from the JSON object
  480|  8.09k|    if (!mDict) {
  ------------------
  |  Branch (480:9): [True: 9, False: 8.08k]
  ------------------
  481|      9|        throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\"");
  482|      9|    }
  483|       |
  484|  8.08k|    if (!mDict->IsArray()) {
  ------------------
  |  Branch (484:9): [True: 0, False: 8.08k]
  ------------------
  485|      0|        throw DeadlyImportError("GLTF: Field \"", mDictId, "\"  is not an array");
  486|      0|    }
  487|       |
  488|  8.08k|    if (i >= mDict->Size()) {
  ------------------
  |  Branch (488:9): [True: 30, False: 8.05k]
  ------------------
  489|     30|        throw DeadlyImportError("GLTF: Array index ", i, " is out of bounds (", mDict->Size(), ") for \"", mDictId, "\"");
  490|     30|    }
  491|       |
  492|  8.05k|    Value &obj = (*mDict)[i];
  493|       |
  494|  8.05k|    if (!obj.IsObject()) {
  ------------------
  |  Branch (494:9): [True: 1, False: 8.05k]
  ------------------
  495|      1|        throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" is not a JSON object");
  496|      1|    }
  497|       |
  498|  8.05k|    if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) {
  ------------------
  |  Branch (498:9): [True: 0, False: 8.05k]
  ------------------
  499|      0|        throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" has recursive reference to itself");
  500|      0|    }
  501|  8.05k|    mRecursiveReferenceCheck.insert(i);
  502|       |
  503|       |    // Unique ptr prevents memory leak in case of Read throws an exception
  504|  8.05k|    auto inst = std::unique_ptr<T>(new T());
  505|       |    // Try to make this human readable so it can be used in error messages.
  506|  8.05k|    inst->id = std::string(mDictId) + "[" + ai_to_string(i) + "]";
  507|  8.05k|    inst->oIndex = i;
  508|  8.05k|    ReadMember(obj, "name", inst->name);
  509|  8.05k|    inst->Read(obj, mAsset);
  510|  8.05k|    inst->ReadExtensions(obj);
  511|  8.05k|    inst->ReadExtras(obj);
  512|       |
  513|  8.05k|    Ref<T> result = Add(inst.release());
  514|  8.05k|    mRecursiveReferenceCheck.erase(i);
  515|  8.05k|    return result;
  516|  8.05k|}
_ZN5glTF28LazyDictINS_10BufferViewEE3AddEPS1_:
  536|  7.57k|Ref<T> LazyDict<T>::Add(T *obj) {
  537|  7.57k|    unsigned int idx = unsigned(mObjs.size());
  538|  7.57k|    mObjs.push_back(obj);
  539|  7.57k|    mObjsByOIndex[obj->oIndex] = idx;
  540|  7.57k|    mObjsById[obj->id] = idx;
  541|  7.57k|    return Ref<T>(mObjs, idx);
  542|  7.57k|}
_ZN5glTF28LazyDictINS_5ImageEE8RetrieveEj:
  473|    184|Ref<T> LazyDict<T>::Retrieve(unsigned int i) {
  474|    184|    typename Dict::iterator it = mObjsByOIndex.find(i);
  475|    184|    if (it != mObjsByOIndex.end()) { // already created?
  ------------------
  |  Branch (475:9): [True: 0, False: 184]
  ------------------
  476|      0|        return Ref<T>(mObjs, it->second);
  477|      0|    }
  478|       |
  479|       |    // read it from the JSON object
  480|    184|    if (!mDict) {
  ------------------
  |  Branch (480:9): [True: 1, False: 183]
  ------------------
  481|      1|        throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\"");
  482|      1|    }
  483|       |
  484|    183|    if (!mDict->IsArray()) {
  ------------------
  |  Branch (484:9): [True: 0, False: 183]
  ------------------
  485|      0|        throw DeadlyImportError("GLTF: Field \"", mDictId, "\"  is not an array");
  486|      0|    }
  487|       |
  488|    183|    if (i >= mDict->Size()) {
  ------------------
  |  Branch (488:9): [True: 5, False: 178]
  ------------------
  489|      5|        throw DeadlyImportError("GLTF: Array index ", i, " is out of bounds (", mDict->Size(), ") for \"", mDictId, "\"");
  490|      5|    }
  491|       |
  492|    178|    Value &obj = (*mDict)[i];
  493|       |
  494|    178|    if (!obj.IsObject()) {
  ------------------
  |  Branch (494:9): [True: 1, False: 177]
  ------------------
  495|      1|        throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" is not a JSON object");
  496|      1|    }
  497|       |
  498|    177|    if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) {
  ------------------
  |  Branch (498:9): [True: 0, False: 177]
  ------------------
  499|      0|        throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" has recursive reference to itself");
  500|      0|    }
  501|    177|    mRecursiveReferenceCheck.insert(i);
  502|       |
  503|       |    // Unique ptr prevents memory leak in case of Read throws an exception
  504|    177|    auto inst = std::unique_ptr<T>(new T());
  505|       |    // Try to make this human readable so it can be used in error messages.
  506|    177|    inst->id = std::string(mDictId) + "[" + ai_to_string(i) + "]";
  507|    177|    inst->oIndex = i;
  508|    177|    ReadMember(obj, "name", inst->name);
  509|    177|    inst->Read(obj, mAsset);
  510|    177|    inst->ReadExtensions(obj);
  511|    177|    inst->ReadExtras(obj);
  512|       |
  513|    177|    Ref<T> result = Add(inst.release());
  514|    177|    mRecursiveReferenceCheck.erase(i);
  515|    177|    return result;
  516|    177|}
_ZN5glTF28LazyDictINS_5ImageEE3AddEPS1_:
  536|    165|Ref<T> LazyDict<T>::Add(T *obj) {
  537|    165|    unsigned int idx = unsigned(mObjs.size());
  538|    165|    mObjs.push_back(obj);
  539|    165|    mObjsByOIndex[obj->oIndex] = idx;
  540|    165|    mObjsById[obj->id] = idx;
  541|    165|    return Ref<T>(mObjs, idx);
  542|    165|}
_ZN5glTF28LazyDictINS_7SamplerEE8RetrieveEj:
  473|    152|Ref<T> LazyDict<T>::Retrieve(unsigned int i) {
  474|    152|    typename Dict::iterator it = mObjsByOIndex.find(i);
  475|    152|    if (it != mObjsByOIndex.end()) { // already created?
  ------------------
  |  Branch (475:9): [True: 0, False: 152]
  ------------------
  476|      0|        return Ref<T>(mObjs, it->second);
  477|      0|    }
  478|       |
  479|       |    // read it from the JSON object
  480|    152|    if (!mDict) {
  ------------------
  |  Branch (480:9): [True: 3, False: 149]
  ------------------
  481|      3|        throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\"");
  482|      3|    }
  483|       |
  484|    149|    if (!mDict->IsArray()) {
  ------------------
  |  Branch (484:9): [True: 0, False: 149]
  ------------------
  485|      0|        throw DeadlyImportError("GLTF: Field \"", mDictId, "\"  is not an array");
  486|      0|    }
  487|       |
  488|    149|    if (i >= mDict->Size()) {
  ------------------
  |  Branch (488:9): [True: 4, False: 145]
  ------------------
  489|      4|        throw DeadlyImportError("GLTF: Array index ", i, " is out of bounds (", mDict->Size(), ") for \"", mDictId, "\"");
  490|      4|    }
  491|       |
  492|    145|    Value &obj = (*mDict)[i];
  493|       |
  494|    145|    if (!obj.IsObject()) {
  ------------------
  |  Branch (494:9): [True: 1, False: 144]
  ------------------
  495|      1|        throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" is not a JSON object");
  496|      1|    }
  497|       |
  498|    144|    if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) {
  ------------------
  |  Branch (498:9): [True: 0, False: 144]
  ------------------
  499|      0|        throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" has recursive reference to itself");
  500|      0|    }
  501|    144|    mRecursiveReferenceCheck.insert(i);
  502|       |
  503|       |    // Unique ptr prevents memory leak in case of Read throws an exception
  504|    144|    auto inst = std::unique_ptr<T>(new T());
  505|       |    // Try to make this human readable so it can be used in error messages.
  506|    144|    inst->id = std::string(mDictId) + "[" + ai_to_string(i) + "]";
  507|    144|    inst->oIndex = i;
  508|    144|    ReadMember(obj, "name", inst->name);
  509|    144|    inst->Read(obj, mAsset);
  510|    144|    inst->ReadExtensions(obj);
  511|    144|    inst->ReadExtras(obj);
  512|       |
  513|    144|    Ref<T> result = Add(inst.release());
  514|    144|    mRecursiveReferenceCheck.erase(i);
  515|    144|    return result;
  516|    144|}
_ZN5glTF28LazyDictINS_7SamplerEE3AddEPS1_:
  536|    144|Ref<T> LazyDict<T>::Add(T *obj) {
  537|    144|    unsigned int idx = unsigned(mObjs.size());
  538|    144|    mObjs.push_back(obj);
  539|    144|    mObjsByOIndex[obj->oIndex] = idx;
  540|    144|    mObjsById[obj->id] = idx;
  541|    144|    return Ref<T>(mObjs, idx);
  542|    144|}
_ZN5glTF28LazyDictINS_7TextureEE8RetrieveEj:
  473|    291|Ref<T> LazyDict<T>::Retrieve(unsigned int i) {
  474|    291|    typename Dict::iterator it = mObjsByOIndex.find(i);
  475|    291|    if (it != mObjsByOIndex.end()) { // already created?
  ------------------
  |  Branch (475:9): [True: 80, False: 211]
  ------------------
  476|     80|        return Ref<T>(mObjs, it->second);
  477|     80|    }
  478|       |
  479|       |    // read it from the JSON object
  480|    211|    if (!mDict) {
  ------------------
  |  Branch (480:9): [True: 3, False: 208]
  ------------------
  481|      3|        throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\"");
  482|      3|    }
  483|       |
  484|    208|    if (!mDict->IsArray()) {
  ------------------
  |  Branch (484:9): [True: 0, False: 208]
  ------------------
  485|      0|        throw DeadlyImportError("GLTF: Field \"", mDictId, "\"  is not an array");
  486|      0|    }
  487|       |
  488|    208|    if (i >= mDict->Size()) {
  ------------------
  |  Branch (488:9): [True: 4, False: 204]
  ------------------
  489|      4|        throw DeadlyImportError("GLTF: Array index ", i, " is out of bounds (", mDict->Size(), ") for \"", mDictId, "\"");
  490|      4|    }
  491|       |
  492|    204|    Value &obj = (*mDict)[i];
  493|       |
  494|    204|    if (!obj.IsObject()) {
  ------------------
  |  Branch (494:9): [True: 1, False: 203]
  ------------------
  495|      1|        throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" is not a JSON object");
  496|      1|    }
  497|       |
  498|    203|    if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) {
  ------------------
  |  Branch (498:9): [True: 0, False: 203]
  ------------------
  499|      0|        throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" has recursive reference to itself");
  500|      0|    }
  501|    203|    mRecursiveReferenceCheck.insert(i);
  502|       |
  503|       |    // Unique ptr prevents memory leak in case of Read throws an exception
  504|    203|    auto inst = std::unique_ptr<T>(new T());
  505|       |    // Try to make this human readable so it can be used in error messages.
  506|    203|    inst->id = std::string(mDictId) + "[" + ai_to_string(i) + "]";
  507|    203|    inst->oIndex = i;
  508|    203|    ReadMember(obj, "name", inst->name);
  509|    203|    inst->Read(obj, mAsset);
  510|    203|    inst->ReadExtensions(obj);
  511|    203|    inst->ReadExtras(obj);
  512|       |
  513|    203|    Ref<T> result = Add(inst.release());
  514|    203|    mRecursiveReferenceCheck.erase(i);
  515|    203|    return result;
  516|    203|}
_ZN5glTF28LazyDictINS_7TextureEE3AddEPS1_:
  536|    174|Ref<T> LazyDict<T>::Add(T *obj) {
  537|    174|    unsigned int idx = unsigned(mObjs.size());
  538|    174|    mObjs.push_back(obj);
  539|    174|    mObjsByOIndex[obj->oIndex] = idx;
  540|    174|    mObjsById[obj->id] = idx;
  541|    174|    return Ref<T>(mObjs, idx);
  542|    174|}
_ZN5glTF28LazyDictINS_8AccessorEE8RetrieveEj:
  473|  14.1k|Ref<T> LazyDict<T>::Retrieve(unsigned int i) {
  474|  14.1k|    typename Dict::iterator it = mObjsByOIndex.find(i);
  475|  14.1k|    if (it != mObjsByOIndex.end()) { // already created?
  ------------------
  |  Branch (475:9): [True: 668, False: 13.5k]
  ------------------
  476|    668|        return Ref<T>(mObjs, it->second);
  477|    668|    }
  478|       |
  479|       |    // read it from the JSON object
  480|  13.5k|    if (!mDict) {
  ------------------
  |  Branch (480:9): [True: 21, False: 13.5k]
  ------------------
  481|     21|        throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\"");
  482|     21|    }
  483|       |
  484|  13.5k|    if (!mDict->IsArray()) {
  ------------------
  |  Branch (484:9): [True: 0, False: 13.5k]
  ------------------
  485|      0|        throw DeadlyImportError("GLTF: Field \"", mDictId, "\"  is not an array");
  486|      0|    }
  487|       |
  488|  13.5k|    if (i >= mDict->Size()) {
  ------------------
  |  Branch (488:9): [True: 87, False: 13.4k]
  ------------------
  489|     87|        throw DeadlyImportError("GLTF: Array index ", i, " is out of bounds (", mDict->Size(), ") for \"", mDictId, "\"");
  490|     87|    }
  491|       |
  492|  13.4k|    Value &obj = (*mDict)[i];
  493|       |
  494|  13.4k|    if (!obj.IsObject()) {
  ------------------
  |  Branch (494:9): [True: 1, False: 13.4k]
  ------------------
  495|      1|        throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" is not a JSON object");
  496|      1|    }
  497|       |
  498|  13.4k|    if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) {
  ------------------
  |  Branch (498:9): [True: 0, False: 13.4k]
  ------------------
  499|      0|        throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" has recursive reference to itself");
  500|      0|    }
  501|  13.4k|    mRecursiveReferenceCheck.insert(i);
  502|       |
  503|       |    // Unique ptr prevents memory leak in case of Read throws an exception
  504|  13.4k|    auto inst = std::unique_ptr<T>(new T());
  505|       |    // Try to make this human readable so it can be used in error messages.
  506|  13.4k|    inst->id = std::string(mDictId) + "[" + ai_to_string(i) + "]";
  507|  13.4k|    inst->oIndex = i;
  508|  13.4k|    ReadMember(obj, "name", inst->name);
  509|  13.4k|    inst->Read(obj, mAsset);
  510|  13.4k|    inst->ReadExtensions(obj);
  511|  13.4k|    inst->ReadExtras(obj);
  512|       |
  513|  13.4k|    Ref<T> result = Add(inst.release());
  514|  13.4k|    mRecursiveReferenceCheck.erase(i);
  515|  13.4k|    return result;
  516|  13.4k|}
_ZN5glTF28LazyDictINS_8AccessorEE3AddEPS1_:
  536|  12.7k|Ref<T> LazyDict<T>::Add(T *obj) {
  537|  12.7k|    unsigned int idx = unsigned(mObjs.size());
  538|  12.7k|    mObjs.push_back(obj);
  539|  12.7k|    mObjsByOIndex[obj->oIndex] = idx;
  540|  12.7k|    mObjsById[obj->id] = idx;
  541|  12.7k|    return Ref<T>(mObjs, idx);
  542|  12.7k|}
_ZN5glTF28LazyDictINS_8MaterialEE8RetrieveEj:
  473|  3.18k|Ref<T> LazyDict<T>::Retrieve(unsigned int i) {
  474|  3.18k|    typename Dict::iterator it = mObjsByOIndex.find(i);
  475|  3.18k|    if (it != mObjsByOIndex.end()) { // already created?
  ------------------
  |  Branch (475:9): [True: 71, False: 3.11k]
  ------------------
  476|     71|        return Ref<T>(mObjs, it->second);
  477|     71|    }
  478|       |
  479|       |    // read it from the JSON object
  480|  3.11k|    if (!mDict) {
  ------------------
  |  Branch (480:9): [True: 2, False: 3.11k]
  ------------------
  481|      2|        throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\"");
  482|      2|    }
  483|       |
  484|  3.11k|    if (!mDict->IsArray()) {
  ------------------
  |  Branch (484:9): [True: 0, False: 3.11k]
  ------------------
  485|      0|        throw DeadlyImportError("GLTF: Field \"", mDictId, "\"  is not an array");
  486|      0|    }
  487|       |
  488|  3.11k|    if (i >= mDict->Size()) {
  ------------------
  |  Branch (488:9): [True: 7, False: 3.10k]
  ------------------
  489|      7|        throw DeadlyImportError("GLTF: Array index ", i, " is out of bounds (", mDict->Size(), ") for \"", mDictId, "\"");
  490|      7|    }
  491|       |
  492|  3.10k|    Value &obj = (*mDict)[i];
  493|       |
  494|  3.10k|    if (!obj.IsObject()) {
  ------------------
  |  Branch (494:9): [True: 2, False: 3.10k]
  ------------------
  495|      2|        throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" is not a JSON object");
  496|      2|    }
  497|       |
  498|  3.10k|    if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) {
  ------------------
  |  Branch (498:9): [True: 0, False: 3.10k]
  ------------------
  499|      0|        throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" has recursive reference to itself");
  500|      0|    }
  501|  3.10k|    mRecursiveReferenceCheck.insert(i);
  502|       |
  503|       |    // Unique ptr prevents memory leak in case of Read throws an exception
  504|  3.10k|    auto inst = std::unique_ptr<T>(new T());
  505|       |    // Try to make this human readable so it can be used in error messages.
  506|  3.10k|    inst->id = std::string(mDictId) + "[" + ai_to_string(i) + "]";
  507|  3.10k|    inst->oIndex = i;
  508|  3.10k|    ReadMember(obj, "name", inst->name);
  509|  3.10k|    inst->Read(obj, mAsset);
  510|  3.10k|    inst->ReadExtensions(obj);
  511|  3.10k|    inst->ReadExtras(obj);
  512|       |
  513|  3.10k|    Ref<T> result = Add(inst.release());
  514|  3.10k|    mRecursiveReferenceCheck.erase(i);
  515|  3.10k|    return result;
  516|  3.10k|}
_ZN5glTF28LazyDictINS_8MaterialEE3AddEPS1_:
  536|  3.06k|Ref<T> LazyDict<T>::Add(T *obj) {
  537|  3.06k|    unsigned int idx = unsigned(mObjs.size());
  538|  3.06k|    mObjs.push_back(obj);
  539|  3.06k|    mObjsByOIndex[obj->oIndex] = idx;
  540|  3.06k|    mObjsById[obj->id] = idx;
  541|  3.06k|    return Ref<T>(mObjs, idx);
  542|  3.06k|}
_ZN5glTF28LazyDictINS_4NodeEE8RetrieveEj:
  473|  18.8k|Ref<T> LazyDict<T>::Retrieve(unsigned int i) {
  474|  18.8k|    typename Dict::iterator it = mObjsByOIndex.find(i);
  475|  18.8k|    if (it != mObjsByOIndex.end()) { // already created?
  ------------------
  |  Branch (475:9): [True: 3.31k, False: 15.4k]
  ------------------
  476|  3.31k|        return Ref<T>(mObjs, it->second);
  477|  3.31k|    }
  478|       |
  479|       |    // read it from the JSON object
  480|  15.4k|    if (!mDict) {
  ------------------
  |  Branch (480:9): [True: 12, False: 15.4k]
  ------------------
  481|     12|        throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\"");
  482|     12|    }
  483|       |
  484|  15.4k|    if (!mDict->IsArray()) {
  ------------------
  |  Branch (484:9): [True: 0, False: 15.4k]
  ------------------
  485|      0|        throw DeadlyImportError("GLTF: Field \"", mDictId, "\"  is not an array");
  486|      0|    }
  487|       |
  488|  15.4k|    if (i >= mDict->Size()) {
  ------------------
  |  Branch (488:9): [True: 92, False: 15.3k]
  ------------------
  489|     92|        throw DeadlyImportError("GLTF: Array index ", i, " is out of bounds (", mDict->Size(), ") for \"", mDictId, "\"");
  490|     92|    }
  491|       |
  492|  15.3k|    Value &obj = (*mDict)[i];
  493|       |
  494|  15.3k|    if (!obj.IsObject()) {
  ------------------
  |  Branch (494:9): [True: 3, False: 15.3k]
  ------------------
  495|      3|        throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" is not a JSON object");
  496|      3|    }
  497|       |
  498|  15.3k|    if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) {
  ------------------
  |  Branch (498:9): [True: 27, False: 15.3k]
  ------------------
  499|     27|        throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" has recursive reference to itself");
  500|     27|    }
  501|  15.3k|    mRecursiveReferenceCheck.insert(i);
  502|       |
  503|       |    // Unique ptr prevents memory leak in case of Read throws an exception
  504|  15.3k|    auto inst = std::unique_ptr<T>(new T());
  505|       |    // Try to make this human readable so it can be used in error messages.
  506|  15.3k|    inst->id = std::string(mDictId) + "[" + ai_to_string(i) + "]";
  507|  15.3k|    inst->oIndex = i;
  508|  15.3k|    ReadMember(obj, "name", inst->name);
  509|  15.3k|    inst->Read(obj, mAsset);
  510|  15.3k|    inst->ReadExtensions(obj);
  511|  15.3k|    inst->ReadExtras(obj);
  512|       |
  513|  15.3k|    Ref<T> result = Add(inst.release());
  514|  15.3k|    mRecursiveReferenceCheck.erase(i);
  515|  15.3k|    return result;
  516|  15.3k|}
_ZN5glTF28LazyDictINS_4NodeEE3AddEPS1_:
  536|  14.0k|Ref<T> LazyDict<T>::Add(T *obj) {
  537|  14.0k|    unsigned int idx = unsigned(mObjs.size());
  538|  14.0k|    mObjs.push_back(obj);
  539|  14.0k|    mObjsByOIndex[obj->oIndex] = idx;
  540|  14.0k|    mObjsById[obj->id] = idx;
  541|  14.0k|    return Ref<T>(mObjs, idx);
  542|  14.0k|}
_ZN5glTF28LazyDictINS_4MeshEE8RetrieveEj:
  473|  6.48k|Ref<T> LazyDict<T>::Retrieve(unsigned int i) {
  474|  6.48k|    typename Dict::iterator it = mObjsByOIndex.find(i);
  475|  6.48k|    if (it != mObjsByOIndex.end()) { // already created?
  ------------------
  |  Branch (475:9): [True: 1.91k, False: 4.57k]
  ------------------
  476|  1.91k|        return Ref<T>(mObjs, it->second);
  477|  1.91k|    }
  478|       |
  479|       |    // read it from the JSON object
  480|  4.57k|    if (!mDict) {
  ------------------
  |  Branch (480:9): [True: 30, False: 4.54k]
  ------------------
  481|     30|        throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\"");
  482|     30|    }
  483|       |
  484|  4.54k|    if (!mDict->IsArray()) {
  ------------------
  |  Branch (484:9): [True: 0, False: 4.54k]
  ------------------
  485|      0|        throw DeadlyImportError("GLTF: Field \"", mDictId, "\"  is not an array");
  486|      0|    }
  487|       |
  488|  4.54k|    if (i >= mDict->Size()) {
  ------------------
  |  Branch (488:9): [True: 39, False: 4.50k]
  ------------------
  489|     39|        throw DeadlyImportError("GLTF: Array index ", i, " is out of bounds (", mDict->Size(), ") for \"", mDictId, "\"");
  490|     39|    }
  491|       |
  492|  4.50k|    Value &obj = (*mDict)[i];
  493|       |
  494|  4.50k|    if (!obj.IsObject()) {
  ------------------
  |  Branch (494:9): [True: 6, False: 4.49k]
  ------------------
  495|      6|        throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" is not a JSON object");
  496|      6|    }
  497|       |
  498|  4.49k|    if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) {
  ------------------
  |  Branch (498:9): [True: 0, False: 4.49k]
  ------------------
  499|      0|        throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" has recursive reference to itself");
  500|      0|    }
  501|  4.49k|    mRecursiveReferenceCheck.insert(i);
  502|       |
  503|       |    // Unique ptr prevents memory leak in case of Read throws an exception
  504|  4.49k|    auto inst = std::unique_ptr<T>(new T());
  505|       |    // Try to make this human readable so it can be used in error messages.
  506|  4.49k|    inst->id = std::string(mDictId) + "[" + ai_to_string(i) + "]";
  507|  4.49k|    inst->oIndex = i;
  508|  4.49k|    ReadMember(obj, "name", inst->name);
  509|  4.49k|    inst->Read(obj, mAsset);
  510|  4.49k|    inst->ReadExtensions(obj);
  511|  4.49k|    inst->ReadExtras(obj);
  512|       |
  513|  4.49k|    Ref<T> result = Add(inst.release());
  514|  4.49k|    mRecursiveReferenceCheck.erase(i);
  515|  4.49k|    return result;
  516|  4.49k|}
_ZN5glTF28LazyDictINS_4MeshEE3AddEPS1_:
  536|  3.79k|Ref<T> LazyDict<T>::Add(T *obj) {
  537|  3.79k|    unsigned int idx = unsigned(mObjs.size());
  538|  3.79k|    mObjs.push_back(obj);
  539|  3.79k|    mObjsByOIndex[obj->oIndex] = idx;
  540|  3.79k|    mObjsById[obj->id] = idx;
  541|  3.79k|    return Ref<T>(mObjs, idx);
  542|  3.79k|}
_ZN5glTF28LazyDictINS_4SkinEE3GetEj:
  519|    646|Ref<T> LazyDict<T>::Get(unsigned int i) {
  520|    646|    return Ref<T>(mObjs, i);
  521|    646|}
_ZN5glTF28LazyDictINS_6CameraEE8RetrieveEj:
  473|    127|Ref<T> LazyDict<T>::Retrieve(unsigned int i) {
  474|    127|    typename Dict::iterator it = mObjsByOIndex.find(i);
  475|    127|    if (it != mObjsByOIndex.end()) { // already created?
  ------------------
  |  Branch (475:9): [True: 5, False: 122]
  ------------------
  476|      5|        return Ref<T>(mObjs, it->second);
  477|      5|    }
  478|       |
  479|       |    // read it from the JSON object
  480|    122|    if (!mDict) {
  ------------------
  |  Branch (480:9): [True: 2, False: 120]
  ------------------
  481|      2|        throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\"");
  482|      2|    }
  483|       |
  484|    120|    if (!mDict->IsArray()) {
  ------------------
  |  Branch (484:9): [True: 0, False: 120]
  ------------------
  485|      0|        throw DeadlyImportError("GLTF: Field \"", mDictId, "\"  is not an array");
  486|      0|    }
  487|       |
  488|    120|    if (i >= mDict->Size()) {
  ------------------
  |  Branch (488:9): [True: 15, False: 105]
  ------------------
  489|     15|        throw DeadlyImportError("GLTF: Array index ", i, " is out of bounds (", mDict->Size(), ") for \"", mDictId, "\"");
  490|     15|    }
  491|       |
  492|    105|    Value &obj = (*mDict)[i];
  493|       |
  494|    105|    if (!obj.IsObject()) {
  ------------------
  |  Branch (494:9): [True: 1, False: 104]
  ------------------
  495|      1|        throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" is not a JSON object");
  496|      1|    }
  497|       |
  498|    104|    if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) {
  ------------------
  |  Branch (498:9): [True: 0, False: 104]
  ------------------
  499|      0|        throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" has recursive reference to itself");
  500|      0|    }
  501|    104|    mRecursiveReferenceCheck.insert(i);
  502|       |
  503|       |    // Unique ptr prevents memory leak in case of Read throws an exception
  504|    104|    auto inst = std::unique_ptr<T>(new T());
  505|       |    // Try to make this human readable so it can be used in error messages.
  506|    104|    inst->id = std::string(mDictId) + "[" + ai_to_string(i) + "]";
  507|    104|    inst->oIndex = i;
  508|    104|    ReadMember(obj, "name", inst->name);
  509|    104|    inst->Read(obj, mAsset);
  510|    104|    inst->ReadExtensions(obj);
  511|    104|    inst->ReadExtras(obj);
  512|       |
  513|    104|    Ref<T> result = Add(inst.release());
  514|    104|    mRecursiveReferenceCheck.erase(i);
  515|    104|    return result;
  516|    104|}
_ZN5glTF28LazyDictINS_6CameraEE3AddEPS1_:
  536|     93|Ref<T> LazyDict<T>::Add(T *obj) {
  537|     93|    unsigned int idx = unsigned(mObjs.size());
  538|     93|    mObjs.push_back(obj);
  539|     93|    mObjsByOIndex[obj->oIndex] = idx;
  540|     93|    mObjsById[obj->id] = idx;
  541|     93|    return Ref<T>(mObjs, idx);
  542|     93|}
_ZN5glTF28LazyDictINS_5SceneEE8RetrieveEj:
  473|  3.18k|Ref<T> LazyDict<T>::Retrieve(unsigned int i) {
  474|  3.18k|    typename Dict::iterator it = mObjsByOIndex.find(i);
  475|  3.18k|    if (it != mObjsByOIndex.end()) { // already created?
  ------------------
  |  Branch (475:9): [True: 0, False: 3.18k]
  ------------------
  476|      0|        return Ref<T>(mObjs, it->second);
  477|      0|    }
  478|       |
  479|       |    // read it from the JSON object
  480|  3.18k|    if (!mDict) {
  ------------------
  |  Branch (480:9): [True: 0, False: 3.18k]
  ------------------
  481|      0|        throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\"");
  482|      0|    }
  483|       |
  484|  3.18k|    if (!mDict->IsArray()) {
  ------------------
  |  Branch (484:9): [True: 0, False: 3.18k]
  ------------------
  485|      0|        throw DeadlyImportError("GLTF: Field \"", mDictId, "\"  is not an array");
  486|      0|    }
  487|       |
  488|  3.18k|    if (i >= mDict->Size()) {
  ------------------
  |  Branch (488:9): [True: 0, False: 3.18k]
  ------------------
  489|      0|        throw DeadlyImportError("GLTF: Array index ", i, " is out of bounds (", mDict->Size(), ") for \"", mDictId, "\"");
  490|      0|    }
  491|       |
  492|  3.18k|    Value &obj = (*mDict)[i];
  493|       |
  494|  3.18k|    if (!obj.IsObject()) {
  ------------------
  |  Branch (494:9): [True: 3, False: 3.18k]
  ------------------
  495|      3|        throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" is not a JSON object");
  496|      3|    }
  497|       |
  498|  3.18k|    if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) {
  ------------------
  |  Branch (498:9): [True: 0, False: 3.18k]
  ------------------
  499|      0|        throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" has recursive reference to itself");
  500|      0|    }
  501|  3.18k|    mRecursiveReferenceCheck.insert(i);
  502|       |
  503|       |    // Unique ptr prevents memory leak in case of Read throws an exception
  504|  3.18k|    auto inst = std::unique_ptr<T>(new T());
  505|       |    // Try to make this human readable so it can be used in error messages.
  506|  3.18k|    inst->id = std::string(mDictId) + "[" + ai_to_string(i) + "]";
  507|  3.18k|    inst->oIndex = i;
  508|  3.18k|    ReadMember(obj, "name", inst->name);
  509|  3.18k|    inst->Read(obj, mAsset);
  510|  3.18k|    inst->ReadExtensions(obj);
  511|  3.18k|    inst->ReadExtras(obj);
  512|       |
  513|  3.18k|    Ref<T> result = Add(inst.release());
  514|  3.18k|    mRecursiveReferenceCheck.erase(i);
  515|  3.18k|    return result;
  516|  3.18k|}
_ZN5glTF28LazyDictINS_5SceneEE3AddEPS1_:
  536|  2.25k|Ref<T> LazyDict<T>::Add(T *obj) {
  537|  2.25k|    unsigned int idx = unsigned(mObjs.size());
  538|  2.25k|    mObjs.push_back(obj);
  539|  2.25k|    mObjsByOIndex[obj->oIndex] = idx;
  540|  2.25k|    mObjsById[obj->id] = idx;
  541|  2.25k|    return Ref<T>(mObjs, idx);
  542|  2.25k|}
_ZN5glTF28LazyDictINS_4SkinEE8RetrieveEj:
  473|  3.68k|Ref<T> LazyDict<T>::Retrieve(unsigned int i) {
  474|  3.68k|    typename Dict::iterator it = mObjsByOIndex.find(i);
  475|  3.68k|    if (it != mObjsByOIndex.end()) { // already created?
  ------------------
  |  Branch (475:9): [True: 0, False: 3.68k]
  ------------------
  476|      0|        return Ref<T>(mObjs, it->second);
  477|      0|    }
  478|       |
  479|       |    // read it from the JSON object
  480|  3.68k|    if (!mDict) {
  ------------------
  |  Branch (480:9): [True: 0, False: 3.68k]
  ------------------
  481|      0|        throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\"");
  482|      0|    }
  483|       |
  484|  3.68k|    if (!mDict->IsArray()) {
  ------------------
  |  Branch (484:9): [True: 0, False: 3.68k]
  ------------------
  485|      0|        throw DeadlyImportError("GLTF: Field \"", mDictId, "\"  is not an array");
  486|      0|    }
  487|       |
  488|  3.68k|    if (i >= mDict->Size()) {
  ------------------
  |  Branch (488:9): [True: 0, False: 3.68k]
  ------------------
  489|      0|        throw DeadlyImportError("GLTF: Array index ", i, " is out of bounds (", mDict->Size(), ") for \"", mDictId, "\"");
  490|      0|    }
  491|       |
  492|  3.68k|    Value &obj = (*mDict)[i];
  493|       |
  494|  3.68k|    if (!obj.IsObject()) {
  ------------------
  |  Branch (494:9): [True: 2, False: 3.68k]
  ------------------
  495|      2|        throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" is not a JSON object");
  496|      2|    }
  497|       |
  498|  3.68k|    if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) {
  ------------------
  |  Branch (498:9): [True: 0, False: 3.68k]
  ------------------
  499|      0|        throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" has recursive reference to itself");
  500|      0|    }
  501|  3.68k|    mRecursiveReferenceCheck.insert(i);
  502|       |
  503|       |    // Unique ptr prevents memory leak in case of Read throws an exception
  504|  3.68k|    auto inst = std::unique_ptr<T>(new T());
  505|       |    // Try to make this human readable so it can be used in error messages.
  506|  3.68k|    inst->id = std::string(mDictId) + "[" + ai_to_string(i) + "]";
  507|  3.68k|    inst->oIndex = i;
  508|  3.68k|    ReadMember(obj, "name", inst->name);
  509|  3.68k|    inst->Read(obj, mAsset);
  510|  3.68k|    inst->ReadExtensions(obj);
  511|  3.68k|    inst->ReadExtras(obj);
  512|       |
  513|  3.68k|    Ref<T> result = Add(inst.release());
  514|  3.68k|    mRecursiveReferenceCheck.erase(i);
  515|  3.68k|    return result;
  516|  3.68k|}
_ZN5glTF28LazyDictINS_4SkinEE3AddEPS1_:
  536|  3.60k|Ref<T> LazyDict<T>::Add(T *obj) {
  537|  3.60k|    unsigned int idx = unsigned(mObjs.size());
  538|  3.60k|    mObjs.push_back(obj);
  539|  3.60k|    mObjsByOIndex[obj->oIndex] = idx;
  540|  3.60k|    mObjsById[obj->id] = idx;
  541|  3.60k|    return Ref<T>(mObjs, idx);
  542|  3.60k|}
_ZN5glTF28LazyDictINS_9AnimationEE8RetrieveEj:
  473|    353|Ref<T> LazyDict<T>::Retrieve(unsigned int i) {
  474|    353|    typename Dict::iterator it = mObjsByOIndex.find(i);
  475|    353|    if (it != mObjsByOIndex.end()) { // already created?
  ------------------
  |  Branch (475:9): [True: 0, False: 353]
  ------------------
  476|      0|        return Ref<T>(mObjs, it->second);
  477|      0|    }
  478|       |
  479|       |    // read it from the JSON object
  480|    353|    if (!mDict) {
  ------------------
  |  Branch (480:9): [True: 0, False: 353]
  ------------------
  481|      0|        throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\"");
  482|      0|    }
  483|       |
  484|    353|    if (!mDict->IsArray()) {
  ------------------
  |  Branch (484:9): [True: 0, False: 353]
  ------------------
  485|      0|        throw DeadlyImportError("GLTF: Field \"", mDictId, "\"  is not an array");
  486|      0|    }
  487|       |
  488|    353|    if (i >= mDict->Size()) {
  ------------------
  |  Branch (488:9): [True: 0, False: 353]
  ------------------
  489|      0|        throw DeadlyImportError("GLTF: Array index ", i, " is out of bounds (", mDict->Size(), ") for \"", mDictId, "\"");
  490|      0|    }
  491|       |
  492|    353|    Value &obj = (*mDict)[i];
  493|       |
  494|    353|    if (!obj.IsObject()) {
  ------------------
  |  Branch (494:9): [True: 1, False: 352]
  ------------------
  495|      1|        throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" is not a JSON object");
  496|      1|    }
  497|       |
  498|    352|    if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) {
  ------------------
  |  Branch (498:9): [True: 0, False: 352]
  ------------------
  499|      0|        throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" has recursive reference to itself");
  500|      0|    }
  501|    352|    mRecursiveReferenceCheck.insert(i);
  502|       |
  503|       |    // Unique ptr prevents memory leak in case of Read throws an exception
  504|    352|    auto inst = std::unique_ptr<T>(new T());
  505|       |    // Try to make this human readable so it can be used in error messages.
  506|    352|    inst->id = std::string(mDictId) + "[" + ai_to_string(i) + "]";
  507|    352|    inst->oIndex = i;
  508|    352|    ReadMember(obj, "name", inst->name);
  509|    352|    inst->Read(obj, mAsset);
  510|    352|    inst->ReadExtensions(obj);
  511|    352|    inst->ReadExtras(obj);
  512|       |
  513|    352|    Ref<T> result = Add(inst.release());
  514|    352|    mRecursiveReferenceCheck.erase(i);
  515|    352|    return result;
  516|    352|}
_ZN5glTF28LazyDictINS_9AnimationEE3AddEPS1_:
  536|    280|Ref<T> LazyDict<T>::Add(T *obj) {
  537|    280|    unsigned int idx = unsigned(mObjs.size());
  538|    280|    mObjs.push_back(obj);
  539|    280|    mObjsByOIndex[obj->oIndex] = idx;
  540|    280|    mObjsById[obj->id] = idx;
  541|    280|    return Ref<T>(mObjs, idx);
  542|    280|}
_ZN5glTF28LazyDictINS_6BufferEE6CreateEPKc:
  545|  3.45k|Ref<T> LazyDict<T>::Create(const char *id) {
  546|  3.45k|    T *inst = new T();
  547|  3.45k|    unsigned int idx = unsigned(mObjs.size());
  548|  3.45k|    inst->id = id;
  549|  3.45k|    inst->index = idx;
  550|  3.45k|    inst->oIndex = idx;
  551|  3.45k|    return Add(inst);
  552|  3.45k|}
_ZN5glTF28LazyDictINS_8AccessorEEC2ERNS_5AssetEPKcS6_:
  390|  9.60k|        mDictId(dictId),
  391|  9.60k|        mExtId(extId),
  392|  9.60k|        mDict(nullptr),
  393|  9.60k|        mAsset(asset) {
  394|  9.60k|    asset.mDicts.push_back(this); // register to the list of dictionaries
  395|  9.60k|}
_ZN5glTF28LazyDictINS_9AnimationEEC2ERNS_5AssetEPKcS6_:
  390|  9.60k|        mDictId(dictId),
  391|  9.60k|        mExtId(extId),
  392|  9.60k|        mDict(nullptr),
  393|  9.60k|        mAsset(asset) {
  394|  9.60k|    asset.mDicts.push_back(this); // register to the list of dictionaries
  395|  9.60k|}
_ZN5glTF28LazyDictINS_6BufferEEC2ERNS_5AssetEPKcS6_:
  390|  9.60k|        mDictId(dictId),
  391|  9.60k|        mExtId(extId),
  392|  9.60k|        mDict(nullptr),
  393|  9.60k|        mAsset(asset) {
  394|  9.60k|    asset.mDicts.push_back(this); // register to the list of dictionaries
  395|  9.60k|}
_ZN5glTF28LazyDictINS_10BufferViewEEC2ERNS_5AssetEPKcS6_:
  390|  9.60k|        mDictId(dictId),
  391|  9.60k|        mExtId(extId),
  392|  9.60k|        mDict(nullptr),
  393|  9.60k|        mAsset(asset) {
  394|  9.60k|    asset.mDicts.push_back(this); // register to the list of dictionaries
  395|  9.60k|}
_ZN5glTF28LazyDictINS_6CameraEEC2ERNS_5AssetEPKcS6_:
  390|  9.60k|        mDictId(dictId),
  391|  9.60k|        mExtId(extId),
  392|  9.60k|        mDict(nullptr),
  393|  9.60k|        mAsset(asset) {
  394|  9.60k|    asset.mDicts.push_back(this); // register to the list of dictionaries
  395|  9.60k|}
_ZN5glTF28LazyDictINS_5LightEEC2ERNS_5AssetEPKcS6_:
  390|  9.60k|        mDictId(dictId),
  391|  9.60k|        mExtId(extId),
  392|  9.60k|        mDict(nullptr),
  393|  9.60k|        mAsset(asset) {
  394|  9.60k|    asset.mDicts.push_back(this); // register to the list of dictionaries
  395|  9.60k|}
_ZN5glTF28LazyDictINS_5ImageEEC2ERNS_5AssetEPKcS6_:
  390|  9.60k|        mDictId(dictId),
  391|  9.60k|        mExtId(extId),
  392|  9.60k|        mDict(nullptr),
  393|  9.60k|        mAsset(asset) {
  394|  9.60k|    asset.mDicts.push_back(this); // register to the list of dictionaries
  395|  9.60k|}
_ZN5glTF28LazyDictINS_8MaterialEEC2ERNS_5AssetEPKcS6_:
  390|  9.60k|        mDictId(dictId),
  391|  9.60k|        mExtId(extId),
  392|  9.60k|        mDict(nullptr),
  393|  9.60k|        mAsset(asset) {
  394|  9.60k|    asset.mDicts.push_back(this); // register to the list of dictionaries
  395|  9.60k|}
_ZN5glTF28LazyDictINS_4MeshEEC2ERNS_5AssetEPKcS6_:
  390|  9.60k|        mDictId(dictId),
  391|  9.60k|        mExtId(extId),
  392|  9.60k|        mDict(nullptr),
  393|  9.60k|        mAsset(asset) {
  394|  9.60k|    asset.mDicts.push_back(this); // register to the list of dictionaries
  395|  9.60k|}
_ZN5glTF28LazyDictINS_4NodeEEC2ERNS_5AssetEPKcS6_:
  390|  9.60k|        mDictId(dictId),
  391|  9.60k|        mExtId(extId),
  392|  9.60k|        mDict(nullptr),
  393|  9.60k|        mAsset(asset) {
  394|  9.60k|    asset.mDicts.push_back(this); // register to the list of dictionaries
  395|  9.60k|}
_ZN5glTF28LazyDictINS_7SamplerEEC2ERNS_5AssetEPKcS6_:
  390|  9.60k|        mDictId(dictId),
  391|  9.60k|        mExtId(extId),
  392|  9.60k|        mDict(nullptr),
  393|  9.60k|        mAsset(asset) {
  394|  9.60k|    asset.mDicts.push_back(this); // register to the list of dictionaries
  395|  9.60k|}
_ZN5glTF28LazyDictINS_5SceneEEC2ERNS_5AssetEPKcS6_:
  390|  9.60k|        mDictId(dictId),
  391|  9.60k|        mExtId(extId),
  392|  9.60k|        mDict(nullptr),
  393|  9.60k|        mAsset(asset) {
  394|  9.60k|    asset.mDicts.push_back(this); // register to the list of dictionaries
  395|  9.60k|}
_ZN5glTF28LazyDictINS_4SkinEEC2ERNS_5AssetEPKcS6_:
  390|  9.60k|        mDictId(dictId),
  391|  9.60k|        mExtId(extId),
  392|  9.60k|        mDict(nullptr),
  393|  9.60k|        mAsset(asset) {
  394|  9.60k|    asset.mDicts.push_back(this); // register to the list of dictionaries
  395|  9.60k|}
_ZN5glTF28LazyDictINS_7TextureEEC2ERNS_5AssetEPKcS6_:
  390|  9.60k|        mDictId(dictId),
  391|  9.60k|        mExtId(extId),
  392|  9.60k|        mDict(nullptr),
  393|  9.60k|        mAsset(asset) {
  394|  9.60k|    asset.mDicts.push_back(this); // register to the list of dictionaries
  395|  9.60k|}
_ZN5glTF28LazyDictINS_7TextureEED2Ev:
  398|  9.60k|inline LazyDict<T>::~LazyDict() {
  399|  9.77k|    for (size_t i = 0; i < mObjs.size(); ++i) {
  ------------------
  |  Branch (399:24): [True: 174, False: 9.60k]
  ------------------
  400|    174|        delete mObjs[i];
  401|    174|    }
  402|  9.60k|}
_ZN5glTF28LazyDictINS_4SkinEED2Ev:
  398|  9.60k|inline LazyDict<T>::~LazyDict() {
  399|  13.2k|    for (size_t i = 0; i < mObjs.size(); ++i) {
  ------------------
  |  Branch (399:24): [True: 3.60k, False: 9.60k]
  ------------------
  400|  3.60k|        delete mObjs[i];
  401|  3.60k|    }
  402|  9.60k|}
_ZN5glTF28LazyDictINS_5SceneEED2Ev:
  398|  9.60k|inline LazyDict<T>::~LazyDict() {
  399|  11.8k|    for (size_t i = 0; i < mObjs.size(); ++i) {
  ------------------
  |  Branch (399:24): [True: 2.25k, False: 9.60k]
  ------------------
  400|  2.25k|        delete mObjs[i];
  401|  2.25k|    }
  402|  9.60k|}
_ZN5glTF28LazyDictINS_7SamplerEED2Ev:
  398|  9.60k|inline LazyDict<T>::~LazyDict() {
  399|  9.74k|    for (size_t i = 0; i < mObjs.size(); ++i) {
  ------------------
  |  Branch (399:24): [True: 144, False: 9.60k]
  ------------------
  400|    144|        delete mObjs[i];
  401|    144|    }
  402|  9.60k|}
_ZN5glTF28LazyDictINS_4NodeEED2Ev:
  398|  9.60k|inline LazyDict<T>::~LazyDict() {
  399|  23.6k|    for (size_t i = 0; i < mObjs.size(); ++i) {
  ------------------
  |  Branch (399:24): [True: 14.0k, False: 9.60k]
  ------------------
  400|  14.0k|        delete mObjs[i];
  401|  14.0k|    }
  402|  9.60k|}
_ZN5glTF28LazyDictINS_4MeshEED2Ev:
  398|  9.60k|inline LazyDict<T>::~LazyDict() {
  399|  13.3k|    for (size_t i = 0; i < mObjs.size(); ++i) {
  ------------------
  |  Branch (399:24): [True: 3.79k, False: 9.60k]
  ------------------
  400|  3.79k|        delete mObjs[i];
  401|  3.79k|    }
  402|  9.60k|}
_ZN5glTF28LazyDictINS_8MaterialEED2Ev:
  398|  9.60k|inline LazyDict<T>::~LazyDict() {
  399|  12.6k|    for (size_t i = 0; i < mObjs.size(); ++i) {
  ------------------
  |  Branch (399:24): [True: 3.06k, False: 9.60k]
  ------------------
  400|  3.06k|        delete mObjs[i];
  401|  3.06k|    }
  402|  9.60k|}
_ZN5glTF28LazyDictINS_5ImageEED2Ev:
  398|  9.60k|inline LazyDict<T>::~LazyDict() {
  399|  9.76k|    for (size_t i = 0; i < mObjs.size(); ++i) {
  ------------------
  |  Branch (399:24): [True: 165, False: 9.60k]
  ------------------
  400|    165|        delete mObjs[i];
  401|    165|    }
  402|  9.60k|}
_ZN5glTF28LazyDictINS_5LightEED2Ev:
  398|  9.60k|inline LazyDict<T>::~LazyDict() {
  399|  9.60k|    for (size_t i = 0; i < mObjs.size(); ++i) {
  ------------------
  |  Branch (399:24): [True: 0, False: 9.60k]
  ------------------
  400|      0|        delete mObjs[i];
  401|      0|    }
  402|  9.60k|}
_ZN5glTF28LazyDictINS_6CameraEED2Ev:
  398|  9.60k|inline LazyDict<T>::~LazyDict() {
  399|  9.69k|    for (size_t i = 0; i < mObjs.size(); ++i) {
  ------------------
  |  Branch (399:24): [True: 93, False: 9.60k]
  ------------------
  400|     93|        delete mObjs[i];
  401|     93|    }
  402|  9.60k|}
_ZN5glTF28LazyDictINS_10BufferViewEED2Ev:
  398|  9.60k|inline LazyDict<T>::~LazyDict() {
  399|  17.1k|    for (size_t i = 0; i < mObjs.size(); ++i) {
  ------------------
  |  Branch (399:24): [True: 7.57k, False: 9.60k]
  ------------------
  400|  7.57k|        delete mObjs[i];
  401|  7.57k|    }
  402|  9.60k|}
_ZN5glTF28LazyDictINS_6BufferEED2Ev:
  398|  9.60k|inline LazyDict<T>::~LazyDict() {
  399|  14.1k|    for (size_t i = 0; i < mObjs.size(); ++i) {
  ------------------
  |  Branch (399:24): [True: 4.52k, False: 9.60k]
  ------------------
  400|  4.52k|        delete mObjs[i];
  401|  4.52k|    }
  402|  9.60k|}
_ZN5glTF28LazyDictINS_9AnimationEED2Ev:
  398|  9.60k|inline LazyDict<T>::~LazyDict() {
  399|  9.88k|    for (size_t i = 0; i < mObjs.size(); ++i) {
  ------------------
  |  Branch (399:24): [True: 280, False: 9.60k]
  ------------------
  400|    280|        delete mObjs[i];
  401|    280|    }
  402|  9.60k|}
_ZN5glTF28LazyDictINS_8AccessorEED2Ev:
  398|  9.60k|inline LazyDict<T>::~LazyDict() {
  399|  22.3k|    for (size_t i = 0; i < mObjs.size(); ++i) {
  ------------------
  |  Branch (399:24): [True: 12.7k, False: 9.60k]
  ------------------
  400|  12.7k|        delete mObjs[i];
  401|  12.7k|    }
  402|  9.60k|}
_ZN5glTF26BufferC2Ev:
  558|  4.92k|        byteLength(0),
  559|  4.92k|        type(Type_arraybuffer),
  560|  4.92k|        EncodedRegion_Current(nullptr),
  561|  4.92k|        mIsSpecial(false) {
  562|       |    // empty
  563|  4.92k|}
glTF2Importer.cpp:_ZN5glTF212_GLOBAL__N_19SetVectorERA4_fRA4_Kf:
  176|  14.0k|void SetVector(vec4 &v, const float (&in)[4]) {
  177|  14.0k|    v[0] = in[0];
  178|  14.0k|    v[1] = in[1];
  179|  14.0k|    v[2] = in[2];
  180|  14.0k|    v[3] = in[3];
  181|  14.0k|}
glTF2Importer.cpp:_ZN5glTF212_GLOBAL__N_19SetVectorERA3_fRA3_Kf:
  183|  30.3k|void SetVector(vec3 &v, const float (&in)[3]) {
  184|  30.3k|    v[0] = in[0];
  185|  30.3k|    v[1] = in[1];
  186|  30.3k|    v[2] = in[2];
  187|  30.3k|}
_ZN5glTF28Accessor7IndexerC2ERS0_:
 1109|  1.31k|    accessor(acc),
 1110|  1.31k|    data(acc.GetPointer()),
 1111|  1.31k|    elemSize(acc.GetElementSize()),
 1112|  1.31k|    stride(acc.GetStride()) {
 1113|  1.31k|}
glTF2Importer.cpp:_ZN5glTF28Accessor11ExtractDataIZL24BuildVertexWeightMappingRNS_4Mesh9PrimitiveERNSt3__16vectorINS6_I14aiVertexWeightNS5_9allocatorIS7_EEEENS8_ISA_EEEEPNS6_IjNS8_IjEEEEE7WeightsEEmRPT_PKSF_:
 1021|    651|size_t Accessor::ExtractData(T *&outData, const std::vector<unsigned int> *remappingIndices) {
 1022|    651|    uint8_t *data = GetPointer();
 1023|    651|    if (!data) {
  ------------------
  |  Branch (1023:9): [True: 7, False: 644]
  ------------------
 1024|      7|        throw DeadlyImportError("GLTF2: data is null when extracting data from ", getContextForErrorMessages(id, name));
 1025|      7|    }
 1026|       |
 1027|    644|    const size_t usedCount = (remappingIndices != nullptr) ? remappingIndices->size() : count;
  ------------------
  |  Branch (1027:30): [True: 503, False: 141]
  ------------------
 1028|    644|    const size_t elemSize = GetElementSize();
 1029|    644|    const size_t totalSize = elemSize * usedCount;
 1030|       |
 1031|    644|    const size_t stride = GetStride();
 1032|       |
 1033|    644|    const size_t targetElemSize = sizeof(T);
 1034|       |
 1035|    644|    if (elemSize > targetElemSize) {
  ------------------
  |  Branch (1035:9): [True: 1, False: 643]
  ------------------
 1036|      1|        throw DeadlyImportError("GLTF: elemSize ", elemSize, " > targetElemSize ", targetElemSize, " in ", getContextForErrorMessages(id, name));
 1037|      1|    }
 1038|       |
 1039|    643|    const size_t maxSize = GetMaxByteSize();
 1040|       |
 1041|    643|    outData = new T[usedCount];
 1042|       |
 1043|    643|    if (remappingIndices != nullptr) {
  ------------------
  |  Branch (1043:9): [True: 502, False: 141]
  ------------------
 1044|    502|        const unsigned int maxIndexCount = static_cast<unsigned int>(maxSize / stride);
 1045|  2.62k|        for (size_t i = 0; i < usedCount; ++i) {
  ------------------
  |  Branch (1045:28): [True: 2.12k, False: 501]
  ------------------
 1046|  2.12k|            size_t srcIdx = (*remappingIndices)[i];
 1047|  2.12k|            if (srcIdx >= maxIndexCount) {
  ------------------
  |  Branch (1047:17): [True: 1, False: 2.12k]
  ------------------
 1048|      1|                throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
 1049|      1|            }
 1050|  2.12k|            memcpy(outData + i, data + srcIdx * stride, elemSize);
 1051|  2.12k|        }
 1052|    502|    } else { // non-indexed cases
 1053|    141|        if (usedCount * stride > maxSize) {
  ------------------
  |  Branch (1053:13): [True: 0, False: 141]
  ------------------
 1054|      0|            throw DeadlyImportError("GLTF: count*stride ", (usedCount * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
 1055|      0|        }
 1056|    141|        if (stride == elemSize && targetElemSize == elemSize) {
  ------------------
  |  Branch (1056:13): [True: 139, False: 2]
  |  Branch (1056:35): [True: 118, False: 21]
  ------------------
 1057|    118|            memcpy(outData, data, totalSize);
 1058|    118|        } else {
 1059|    174|            for (size_t i = 0; i < usedCount; ++i) {
  ------------------
  |  Branch (1059:32): [True: 151, False: 23]
  ------------------
 1060|    151|                memcpy(outData + i, data + i * stride, elemSize);
 1061|    151|            }
 1062|     23|        }
 1063|    141|    }
 1064|    642|    return usedCount;
 1065|    643|}
glTF2Importer.cpp:_ZN5glTF28Accessor11ExtractDataIZL24BuildVertexWeightMappingRNS_4Mesh9PrimitiveERNSt3__16vectorINS6_I14aiVertexWeightNS5_9allocatorIS7_EEEENS8_ISA_EEEEPNS6_IjNS8_IjEEEEE8Indices8EEmRPT_PKSF_:
 1021|     69|size_t Accessor::ExtractData(T *&outData, const std::vector<unsigned int> *remappingIndices) {
 1022|     69|    uint8_t *data = GetPointer();
 1023|     69|    if (!data) {
  ------------------
  |  Branch (1023:9): [True: 5, False: 64]
  ------------------
 1024|      5|        throw DeadlyImportError("GLTF2: data is null when extracting data from ", getContextForErrorMessages(id, name));
 1025|      5|    }
 1026|       |
 1027|     64|    const size_t usedCount = (remappingIndices != nullptr) ? remappingIndices->size() : count;
  ------------------
  |  Branch (1027:30): [True: 32, False: 32]
  ------------------
 1028|     64|    const size_t elemSize = GetElementSize();
 1029|     64|    const size_t totalSize = elemSize * usedCount;
 1030|       |
 1031|     64|    const size_t stride = GetStride();
 1032|       |
 1033|     64|    const size_t targetElemSize = sizeof(T);
 1034|       |
 1035|     64|    if (elemSize > targetElemSize) {
  ------------------
  |  Branch (1035:9): [True: 7, False: 57]
  ------------------
 1036|      7|        throw DeadlyImportError("GLTF: elemSize ", elemSize, " > targetElemSize ", targetElemSize, " in ", getContextForErrorMessages(id, name));
 1037|      7|    }
 1038|       |
 1039|     57|    const size_t maxSize = GetMaxByteSize();
 1040|       |
 1041|     57|    outData = new T[usedCount];
 1042|       |
 1043|     57|    if (remappingIndices != nullptr) {
  ------------------
  |  Branch (1043:9): [True: 29, False: 28]
  ------------------
 1044|     29|        const unsigned int maxIndexCount = static_cast<unsigned int>(maxSize / stride);
 1045|    232|        for (size_t i = 0; i < usedCount; ++i) {
  ------------------
  |  Branch (1045:28): [True: 203, False: 29]
  ------------------
 1046|    203|            size_t srcIdx = (*remappingIndices)[i];
 1047|    203|            if (srcIdx >= maxIndexCount) {
  ------------------
  |  Branch (1047:17): [True: 0, False: 203]
  ------------------
 1048|      0|                throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
 1049|      0|            }
 1050|    203|            memcpy(outData + i, data + srcIdx * stride, elemSize);
 1051|    203|        }
 1052|     29|    } else { // non-indexed cases
 1053|     28|        if (usedCount * stride > maxSize) {
  ------------------
  |  Branch (1053:13): [True: 0, False: 28]
  ------------------
 1054|      0|            throw DeadlyImportError("GLTF: count*stride ", (usedCount * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
 1055|      0|        }
 1056|     28|        if (stride == elemSize && targetElemSize == elemSize) {
  ------------------
  |  Branch (1056:13): [True: 26, False: 2]
  |  Branch (1056:35): [True: 17, False: 9]
  ------------------
 1057|     17|            memcpy(outData, data, totalSize);
 1058|     17|        } else {
 1059|     67|            for (size_t i = 0; i < usedCount; ++i) {
  ------------------
  |  Branch (1059:32): [True: 56, False: 11]
  ------------------
 1060|     56|                memcpy(outData + i, data + i * stride, elemSize);
 1061|     56|            }
 1062|     11|        }
 1063|     28|    }
 1064|     57|    return usedCount;
 1065|     57|}
glTF2Importer.cpp:_ZN5glTF28Accessor11ExtractDataIZL24BuildVertexWeightMappingRNS_4Mesh9PrimitiveERNSt3__16vectorINS6_I14aiVertexWeightNS5_9allocatorIS7_EEEENS8_ISA_EEEEPNS6_IjNS8_IjEEEEE9Indices16EEmRPT_PKSF_:
 1021|    556|size_t Accessor::ExtractData(T *&outData, const std::vector<unsigned int> *remappingIndices) {
 1022|    556|    uint8_t *data = GetPointer();
 1023|    556|    if (!data) {
  ------------------
  |  Branch (1023:9): [True: 11, False: 545]
  ------------------
 1024|     11|        throw DeadlyImportError("GLTF2: data is null when extracting data from ", getContextForErrorMessages(id, name));
 1025|     11|    }
 1026|       |
 1027|    545|    const size_t usedCount = (remappingIndices != nullptr) ? remappingIndices->size() : count;
  ------------------
  |  Branch (1027:30): [True: 454, False: 91]
  ------------------
 1028|    545|    const size_t elemSize = GetElementSize();
 1029|    545|    const size_t totalSize = elemSize * usedCount;
 1030|       |
 1031|    545|    const size_t stride = GetStride();
 1032|       |
 1033|    545|    const size_t targetElemSize = sizeof(T);
 1034|       |
 1035|    545|    if (elemSize > targetElemSize) {
  ------------------
  |  Branch (1035:9): [True: 4, False: 541]
  ------------------
 1036|      4|        throw DeadlyImportError("GLTF: elemSize ", elemSize, " > targetElemSize ", targetElemSize, " in ", getContextForErrorMessages(id, name));
 1037|      4|    }
 1038|       |
 1039|    541|    const size_t maxSize = GetMaxByteSize();
 1040|       |
 1041|    541|    outData = new T[usedCount];
 1042|       |
 1043|    541|    if (remappingIndices != nullptr) {
  ------------------
  |  Branch (1043:9): [True: 450, False: 91]
  ------------------
 1044|    450|        const unsigned int maxIndexCount = static_cast<unsigned int>(maxSize / stride);
 1045|  2.27k|        for (size_t i = 0; i < usedCount; ++i) {
  ------------------
  |  Branch (1045:28): [True: 1.82k, False: 450]
  ------------------
 1046|  1.82k|            size_t srcIdx = (*remappingIndices)[i];
 1047|  1.82k|            if (srcIdx >= maxIndexCount) {
  ------------------
  |  Branch (1047:17): [True: 0, False: 1.82k]
  ------------------
 1048|      0|                throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
 1049|      0|            }
 1050|  1.82k|            memcpy(outData + i, data + srcIdx * stride, elemSize);
 1051|  1.82k|        }
 1052|    450|    } else { // non-indexed cases
 1053|     91|        if (usedCount * stride > maxSize) {
  ------------------
  |  Branch (1053:13): [True: 0, False: 91]
  ------------------
 1054|      0|            throw DeadlyImportError("GLTF: count*stride ", (usedCount * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
 1055|      0|        }
 1056|     91|        if (stride == elemSize && targetElemSize == elemSize) {
  ------------------
  |  Branch (1056:13): [True: 87, False: 4]
  |  Branch (1056:35): [True: 62, False: 25]
  ------------------
 1057|     62|            memcpy(outData, data, totalSize);
 1058|     62|        } else {
 1059|    213|            for (size_t i = 0; i < usedCount; ++i) {
  ------------------
  |  Branch (1059:32): [True: 184, False: 29]
  ------------------
 1060|    184|                memcpy(outData + i, data + i * stride, elemSize);
 1061|    184|            }
 1062|     29|        }
 1063|     91|    }
 1064|    541|    return usedCount;
 1065|    541|}
glTF2Importer.cpp:_ZN5glTF212_GLOBAL__N_114ReadExtensionsEPKcRN9rapidjson12GenericValueINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEEEE:
  110|  19.4k|inline CustomExtension ReadExtensions(const char *name, Value &obj) {
  111|  19.4k|    CustomExtension ret;
  112|  19.4k|    ret.name = name;
  113|  19.4k|    if (obj.IsObject()) {
  ------------------
  |  Branch (113:9): [True: 10, False: 19.3k]
  ------------------
  114|     10|        ret.mValues.isPresent = true;
  115|     47|        for (auto it = obj.MemberBegin(); it != obj.MemberEnd(); ++it) {
  ------------------
  |  Branch (115:43): [True: 37, False: 10]
  ------------------
  116|     37|            auto &val = it->value;
  117|     37|            ret.mValues.value.push_back(ReadExtensions(it->name.GetString(), val));
  118|     37|        }
  119|  19.3k|    } else if (obj.IsArray()) {
  ------------------
  |  Branch (119:16): [True: 16, False: 19.3k]
  ------------------
  120|     16|        ret.mValues.value.reserve(obj.Size());
  121|     16|        ret.mValues.isPresent = true;
  122|    170|        for (unsigned int i = 0; i < obj.Size(); ++i) {
  ------------------
  |  Branch (122:34): [True: 154, False: 16]
  ------------------
  123|    154|            ret.mValues.value.push_back(ReadExtensions(name, obj[i]));
  124|    154|        }
  125|  19.3k|    } else if (obj.IsNumber()) {
  ------------------
  |  Branch (125:16): [True: 9.78k, False: 9.59k]
  ------------------
  126|  9.78k|        if (obj.IsUint64()) {
  ------------------
  |  Branch (126:13): [True: 9.64k, False: 141]
  ------------------
  127|  9.64k|            ret.mUint64Value.value = obj.GetUint64();
  128|  9.64k|            ret.mUint64Value.isPresent = true;
  129|  9.64k|        } else if (obj.IsInt64()) {
  ------------------
  |  Branch (129:20): [True: 15, False: 126]
  ------------------
  130|     15|            ret.mInt64Value.value = obj.GetInt64();
  131|     15|            ret.mInt64Value.isPresent = true;
  132|    126|        } else if (obj.IsDouble()) {
  ------------------
  |  Branch (132:20): [True: 126, False: 0]
  ------------------
  133|    126|            ret.mDoubleValue.value = obj.GetDouble();
  134|    126|            ret.mDoubleValue.isPresent = true;
  135|    126|        }
  136|  9.78k|    } else if (obj.IsString()) {
  ------------------
  |  Branch (136:16): [True: 4.81k, False: 4.78k]
  ------------------
  137|  4.81k|        ReadValue(obj, ret.mStringValue);
  138|  4.81k|        ret.mStringValue.isPresent = true;
  139|  4.81k|    } else if (obj.IsBool()) {
  ------------------
  |  Branch (139:16): [True: 4.78k, False: 0]
  ------------------
  140|  4.78k|        ret.mBoolValue.value = obj.GetBool();
  141|  4.78k|        ret.mBoolValue.isPresent = true;
  142|  4.78k|    }
  143|  19.4k|    return ret;
  144|  19.4k|}
_ZN5glTF25ImageC2Ev:
 1131|    177|        width(0),
 1132|    177|        height(0),
 1133|    177|        mDataLength(0) {
 1134|    177|}
glTF2Importer.cpp:_ZN5glTF212_GLOBAL__N_115GetAttribVectorERNS_4Mesh9PrimitiveEPKcRPNSt3__16vectorIN10glTFCommon3RefINS_8AccessorEEENS6_9allocatorISB_EEEERi:
  199|  10.1k|inline bool GetAttribVector(Mesh::Primitive &p, const char *attr, Mesh::AccessorList *&v, int &pos) {
  200|  10.1k|    if ((pos = Compare(attr, "POSITION"))) {
  ------------------
  |  Branch (200:9): [True: 3.73k, False: 6.41k]
  ------------------
  201|  3.73k|        v = &(p.attributes.position);
  202|  6.41k|    } else if ((pos = Compare(attr, "NORMAL"))) {
  ------------------
  |  Branch (202:16): [True: 3.24k, False: 3.17k]
  ------------------
  203|  3.24k|        v = &(p.attributes.normal);
  204|  3.24k|    } else if ((pos = Compare(attr, "TANGENT"))) {
  ------------------
  |  Branch (204:16): [True: 2, False: 3.16k]
  ------------------
  205|      2|        v = &(p.attributes.tangent);
  206|  3.16k|    } else if ((pos = Compare(attr, "TEXCOORD"))) {
  ------------------
  |  Branch (206:16): [True: 691, False: 2.47k]
  ------------------
  207|    691|        v = &(p.attributes.texcoord);
  208|  2.47k|    } else if ((pos = Compare(attr, "COLOR"))) {
  ------------------
  |  Branch (208:16): [True: 230, False: 2.24k]
  ------------------
  209|    230|        v = &(p.attributes.color);
  210|  2.24k|    } else if ((pos = Compare(attr, "JOINTS"))) {
  ------------------
  |  Branch (210:16): [True: 896, False: 1.35k]
  ------------------
  211|    896|        v = &(p.attributes.joint);
  212|  1.35k|    } else if ((pos = Compare(attr, "JOINTMATRIX"))) {
  ------------------
  |  Branch (212:16): [True: 1, False: 1.35k]
  ------------------
  213|      1|        v = &(p.attributes.jointmatrix);
  214|  1.35k|    } else if ((pos = Compare(attr, "WEIGHTS"))) {
  ------------------
  |  Branch (214:16): [True: 869, False: 482]
  ------------------
  215|    869|        v = &(p.attributes.weight);
  216|    869|    } else
  217|    482|        return false;
  218|  9.66k|    return true;
  219|  10.1k|}
glTF2Importer.cpp:_ZN5glTF212_GLOBAL__N_17CompareILi9EEEiPKcRAT__S2_:
  190|  13.3k|inline int Compare(const char *attr, const char (&str)[N]) {
  191|  13.3k|    return (strncmp(attr, str, N - 1) == 0) ? N - 1 : 0;
  ------------------
  |  Branch (191:12): [True: 4.43k, False: 8.92k]
  ------------------
  192|  13.3k|}
glTF2Importer.cpp:_ZN5glTF212_GLOBAL__N_17CompareILi7EEEiPKcRAT__S2_:
  190|  8.69k|inline int Compare(const char *attr, const char (&str)[N]) {
  191|  8.69k|    return (strncmp(attr, str, N - 1) == 0) ? N - 1 : 0;
  ------------------
  |  Branch (191:12): [True: 4.14k, False: 4.55k]
  ------------------
  192|  8.69k|}
glTF2Importer.cpp:_ZN5glTF212_GLOBAL__N_17CompareILi8EEEiPKcRAT__S2_:
  190|  4.55k|inline int Compare(const char *attr, const char (&str)[N]) {
  191|  4.55k|    return (strncmp(attr, str, N - 1) == 0) ? N - 1 : 0;
  ------------------
  |  Branch (191:12): [True: 877, False: 3.67k]
  ------------------
  192|  4.55k|}
glTF2Importer.cpp:_ZN5glTF212_GLOBAL__N_17CompareILi6EEEiPKcRAT__S2_:
  190|  2.47k|inline int Compare(const char *attr, const char (&str)[N]) {
  191|  2.47k|    return (strncmp(attr, str, N - 1) == 0) ? N - 1 : 0;
  ------------------
  |  Branch (191:12): [True: 230, False: 2.24k]
  ------------------
  192|  2.47k|}
glTF2Importer.cpp:_ZN5glTF212_GLOBAL__N_17CompareILi12EEEiPKcRAT__S2_:
  190|  1.35k|inline int Compare(const char *attr, const char (&str)[N]) {
  191|  1.35k|    return (strncmp(attr, str, N - 1) == 0) ? N - 1 : 0;
  ------------------
  |  Branch (191:12): [True: 1, False: 1.35k]
  ------------------
  192|  1.35k|}
glTF2Importer.cpp:_ZN5glTF212_GLOBAL__N_121GetAttribTargetVectorERNS_4Mesh9PrimitiveEiPKcRPNSt3__16vectorIN10glTFCommon3RefINS_8AccessorEEENS6_9allocatorISB_EEEERi:
  221|     41|inline bool GetAttribTargetVector(Mesh::Primitive &p, const int targetIndex, const char *attr, Mesh::AccessorList *&v, int &pos) {
  222|     41|    if ((pos = Compare(attr, "POSITION"))) {
  ------------------
  |  Branch (222:9): [True: 8, False: 33]
  ------------------
  223|      8|        v = &(p.targets[targetIndex].position);
  224|     33|    } else if ((pos = Compare(attr, "NORMAL"))) {
  ------------------
  |  Branch (224:16): [True: 3, False: 30]
  ------------------
  225|      3|        v = &(p.targets[targetIndex].normal);
  226|     30|    } else if ((pos = Compare(attr, "TANGENT"))) {
  ------------------
  |  Branch (226:16): [True: 6, False: 24]
  ------------------
  227|      6|        v = &(p.targets[targetIndex].tangent);
  228|      6|    } else
  229|     24|        return false;
  230|     17|    return true;
  231|     41|}
glTF2Importer.cpp:_ZN5glTF212_GLOBAL__N_110ReadExtrasERN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEE:
  146|  4.81k|inline Extras ReadExtras(Value &obj) {
  147|  4.81k|    Extras ret;
  148|       |
  149|  4.81k|    ret.mValues.reserve(obj.MemberCount());
  150|  24.0k|    for (auto it = obj.MemberBegin(); it != obj.MemberEnd(); ++it) {
  ------------------
  |  Branch (150:39): [True: 19.2k, False: 4.81k]
  ------------------
  151|  19.2k|        auto &val = it->value;
  152|  19.2k|        ret.mValues.emplace_back(ReadExtensions(it->name.GetString(), val));
  153|  19.2k|    }
  154|       |
  155|  4.81k|    return ret;
  156|  4.81k|}
_ZN5glTF28Accessor11ExtractDataI10aiVector3tIfEEEmRPT_PKNSt3__16vectorIjNS7_9allocatorIjEEEE:
 1021|  3.48k|size_t Accessor::ExtractData(T *&outData, const std::vector<unsigned int> *remappingIndices) {
 1022|  3.48k|    uint8_t *data = GetPointer();
 1023|  3.48k|    if (!data) {
  ------------------
  |  Branch (1023:9): [True: 15, False: 3.47k]
  ------------------
 1024|     15|        throw DeadlyImportError("GLTF2: data is null when extracting data from ", getContextForErrorMessages(id, name));
 1025|     15|    }
 1026|       |
 1027|  3.47k|    const size_t usedCount = (remappingIndices != nullptr) ? remappingIndices->size() : count;
  ------------------
  |  Branch (1027:30): [True: 2.42k, False: 1.04k]
  ------------------
 1028|  3.47k|    const size_t elemSize = GetElementSize();
 1029|  3.47k|    const size_t totalSize = elemSize * usedCount;
 1030|       |
 1031|  3.47k|    const size_t stride = GetStride();
 1032|       |
 1033|  3.47k|    const size_t targetElemSize = sizeof(T);
 1034|       |
 1035|  3.47k|    if (elemSize > targetElemSize) {
  ------------------
  |  Branch (1035:9): [True: 2, False: 3.47k]
  ------------------
 1036|      2|        throw DeadlyImportError("GLTF: elemSize ", elemSize, " > targetElemSize ", targetElemSize, " in ", getContextForErrorMessages(id, name));
 1037|      2|    }
 1038|       |
 1039|  3.47k|    const size_t maxSize = GetMaxByteSize();
 1040|       |
 1041|  3.47k|    outData = new T[usedCount];
 1042|       |
 1043|  3.47k|    if (remappingIndices != nullptr) {
  ------------------
  |  Branch (1043:9): [True: 2.42k, False: 1.04k]
  ------------------
 1044|  2.42k|        const unsigned int maxIndexCount = static_cast<unsigned int>(maxSize / stride);
 1045|  17.9k|        for (size_t i = 0; i < usedCount; ++i) {
  ------------------
  |  Branch (1045:28): [True: 15.4k, False: 2.42k]
  ------------------
 1046|  15.4k|            size_t srcIdx = (*remappingIndices)[i];
 1047|  15.4k|            if (srcIdx >= maxIndexCount) {
  ------------------
  |  Branch (1047:17): [True: 1, False: 15.4k]
  ------------------
 1048|      1|                throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
 1049|      1|            }
 1050|  15.4k|            memcpy(outData + i, data + srcIdx * stride, elemSize);
 1051|  15.4k|        }
 1052|  2.42k|    } else { // non-indexed cases
 1053|  1.04k|        if (usedCount * stride > maxSize) {
  ------------------
  |  Branch (1053:13): [True: 1, False: 1.04k]
  ------------------
 1054|      1|            throw DeadlyImportError("GLTF: count*stride ", (usedCount * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
 1055|      1|        }
 1056|  1.04k|        if (stride == elemSize && targetElemSize == elemSize) {
  ------------------
  |  Branch (1056:13): [True: 745, False: 299]
  |  Branch (1056:35): [True: 336, False: 409]
  ------------------
 1057|    336|            memcpy(outData, data, totalSize);
 1058|    708|        } else {
 1059|  24.4k|            for (size_t i = 0; i < usedCount; ++i) {
  ------------------
  |  Branch (1059:32): [True: 23.7k, False: 708]
  ------------------
 1060|  23.7k|                memcpy(outData + i, data + i * stride, elemSize);
 1061|  23.7k|            }
 1062|    708|        }
 1063|  1.04k|    }
 1064|  3.46k|    return usedCount;
 1065|  3.47k|}
_ZN5glTF28Accessor11ExtractDataI9aiColor4tIfEEEmRPT_PKNSt3__16vectorIjNS7_9allocatorIjEEEE:
 1021|    168|size_t Accessor::ExtractData(T *&outData, const std::vector<unsigned int> *remappingIndices) {
 1022|    168|    uint8_t *data = GetPointer();
 1023|    168|    if (!data) {
  ------------------
  |  Branch (1023:9): [True: 1, False: 167]
  ------------------
 1024|      1|        throw DeadlyImportError("GLTF2: data is null when extracting data from ", getContextForErrorMessages(id, name));
 1025|      1|    }
 1026|       |
 1027|    167|    const size_t usedCount = (remappingIndices != nullptr) ? remappingIndices->size() : count;
  ------------------
  |  Branch (1027:30): [True: 132, False: 35]
  ------------------
 1028|    167|    const size_t elemSize = GetElementSize();
 1029|    167|    const size_t totalSize = elemSize * usedCount;
 1030|       |
 1031|    167|    const size_t stride = GetStride();
 1032|       |
 1033|    167|    const size_t targetElemSize = sizeof(T);
 1034|       |
 1035|    167|    if (elemSize > targetElemSize) {
  ------------------
  |  Branch (1035:9): [True: 0, False: 167]
  ------------------
 1036|      0|        throw DeadlyImportError("GLTF: elemSize ", elemSize, " > targetElemSize ", targetElemSize, " in ", getContextForErrorMessages(id, name));
 1037|      0|    }
 1038|       |
 1039|    167|    const size_t maxSize = GetMaxByteSize();
 1040|       |
 1041|    167|    outData = new T[usedCount];
 1042|       |
 1043|    167|    if (remappingIndices != nullptr) {
  ------------------
  |  Branch (1043:9): [True: 132, False: 35]
  ------------------
 1044|    132|        const unsigned int maxIndexCount = static_cast<unsigned int>(maxSize / stride);
 1045|    613|        for (size_t i = 0; i < usedCount; ++i) {
  ------------------
  |  Branch (1045:28): [True: 481, False: 132]
  ------------------
 1046|    481|            size_t srcIdx = (*remappingIndices)[i];
 1047|    481|            if (srcIdx >= maxIndexCount) {
  ------------------
  |  Branch (1047:17): [True: 0, False: 481]
  ------------------
 1048|      0|                throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
 1049|      0|            }
 1050|    481|            memcpy(outData + i, data + srcIdx * stride, elemSize);
 1051|    481|        }
 1052|    132|    } else { // non-indexed cases
 1053|     35|        if (usedCount * stride > maxSize) {
  ------------------
  |  Branch (1053:13): [True: 0, False: 35]
  ------------------
 1054|      0|            throw DeadlyImportError("GLTF: count*stride ", (usedCount * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
 1055|      0|        }
 1056|     35|        if (stride == elemSize && targetElemSize == elemSize) {
  ------------------
  |  Branch (1056:13): [True: 33, False: 2]
  |  Branch (1056:35): [True: 23, False: 10]
  ------------------
 1057|     23|            memcpy(outData, data, totalSize);
 1058|     23|        } else {
 1059|    260|            for (size_t i = 0; i < usedCount; ++i) {
  ------------------
  |  Branch (1059:32): [True: 248, False: 12]
  ------------------
 1060|    248|                memcpy(outData + i, data + i * stride, elemSize);
 1061|    248|            }
 1062|     12|        }
 1063|     35|    }
 1064|    167|    return usedCount;
 1065|    167|}
_ZN5glTF28Accessor11ExtractDataI9aiColor4tIhEEEmRPT_PKNSt3__16vectorIjNS7_9allocatorIjEEEE:
 1021|     11|size_t Accessor::ExtractData(T *&outData, const std::vector<unsigned int> *remappingIndices) {
 1022|     11|    uint8_t *data = GetPointer();
 1023|     11|    if (!data) {
  ------------------
  |  Branch (1023:9): [True: 1, False: 10]
  ------------------
 1024|      1|        throw DeadlyImportError("GLTF2: data is null when extracting data from ", getContextForErrorMessages(id, name));
 1025|      1|    }
 1026|       |
 1027|     10|    const size_t usedCount = (remappingIndices != nullptr) ? remappingIndices->size() : count;
  ------------------
  |  Branch (1027:30): [True: 0, False: 10]
  ------------------
 1028|     10|    const size_t elemSize = GetElementSize();
 1029|     10|    const size_t totalSize = elemSize * usedCount;
 1030|       |
 1031|     10|    const size_t stride = GetStride();
 1032|       |
 1033|     10|    const size_t targetElemSize = sizeof(T);
 1034|       |
 1035|     10|    if (elemSize > targetElemSize) {
  ------------------
  |  Branch (1035:9): [True: 0, False: 10]
  ------------------
 1036|      0|        throw DeadlyImportError("GLTF: elemSize ", elemSize, " > targetElemSize ", targetElemSize, " in ", getContextForErrorMessages(id, name));
 1037|      0|    }
 1038|       |
 1039|     10|    const size_t maxSize = GetMaxByteSize();
 1040|       |
 1041|     10|    outData = new T[usedCount];
 1042|       |
 1043|     10|    if (remappingIndices != nullptr) {
  ------------------
  |  Branch (1043:9): [True: 0, False: 10]
  ------------------
 1044|      0|        const unsigned int maxIndexCount = static_cast<unsigned int>(maxSize / stride);
 1045|      0|        for (size_t i = 0; i < usedCount; ++i) {
  ------------------
  |  Branch (1045:28): [True: 0, False: 0]
  ------------------
 1046|      0|            size_t srcIdx = (*remappingIndices)[i];
 1047|      0|            if (srcIdx >= maxIndexCount) {
  ------------------
  |  Branch (1047:17): [True: 0, False: 0]
  ------------------
 1048|      0|                throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
 1049|      0|            }
 1050|      0|            memcpy(outData + i, data + srcIdx * stride, elemSize);
 1051|      0|        }
 1052|     10|    } else { // non-indexed cases
 1053|     10|        if (usedCount * stride > maxSize) {
  ------------------
  |  Branch (1053:13): [True: 0, False: 10]
  ------------------
 1054|      0|            throw DeadlyImportError("GLTF: count*stride ", (usedCount * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
 1055|      0|        }
 1056|     10|        if (stride == elemSize && targetElemSize == elemSize) {
  ------------------
  |  Branch (1056:13): [True: 10, False: 0]
  |  Branch (1056:35): [True: 1, False: 9]
  ------------------
 1057|      1|            memcpy(outData, data, totalSize);
 1058|      9|        } else {
 1059|     45|            for (size_t i = 0; i < usedCount; ++i) {
  ------------------
  |  Branch (1059:32): [True: 36, False: 9]
  ------------------
 1060|     36|                memcpy(outData + i, data + i * stride, elemSize);
 1061|     36|            }
 1062|      9|        }
 1063|     10|    }
 1064|     10|    return usedCount;
 1065|     10|}
_ZN5glTF28Accessor11ExtractDataI9aiColor4tItEEEmRPT_PKNSt3__16vectorIjNS7_9allocatorIjEEEE:
 1021|     14|size_t Accessor::ExtractData(T *&outData, const std::vector<unsigned int> *remappingIndices) {
 1022|     14|    uint8_t *data = GetPointer();
 1023|     14|    if (!data) {
  ------------------
  |  Branch (1023:9): [True: 1, False: 13]
  ------------------
 1024|      1|        throw DeadlyImportError("GLTF2: data is null when extracting data from ", getContextForErrorMessages(id, name));
 1025|      1|    }
 1026|       |
 1027|     13|    const size_t usedCount = (remappingIndices != nullptr) ? remappingIndices->size() : count;
  ------------------
  |  Branch (1027:30): [True: 5, False: 8]
  ------------------
 1028|     13|    const size_t elemSize = GetElementSize();
 1029|     13|    const size_t totalSize = elemSize * usedCount;
 1030|       |
 1031|     13|    const size_t stride = GetStride();
 1032|       |
 1033|     13|    const size_t targetElemSize = sizeof(T);
 1034|       |
 1035|     13|    if (elemSize > targetElemSize) {
  ------------------
  |  Branch (1035:9): [True: 0, False: 13]
  ------------------
 1036|      0|        throw DeadlyImportError("GLTF: elemSize ", elemSize, " > targetElemSize ", targetElemSize, " in ", getContextForErrorMessages(id, name));
 1037|      0|    }
 1038|       |
 1039|     13|    const size_t maxSize = GetMaxByteSize();
 1040|       |
 1041|     13|    outData = new T[usedCount];
 1042|       |
 1043|     13|    if (remappingIndices != nullptr) {
  ------------------
  |  Branch (1043:9): [True: 5, False: 8]
  ------------------
 1044|      5|        const unsigned int maxIndexCount = static_cast<unsigned int>(maxSize / stride);
 1045|     15|        for (size_t i = 0; i < usedCount; ++i) {
  ------------------
  |  Branch (1045:28): [True: 10, False: 5]
  ------------------
 1046|     10|            size_t srcIdx = (*remappingIndices)[i];
 1047|     10|            if (srcIdx >= maxIndexCount) {
  ------------------
  |  Branch (1047:17): [True: 0, False: 10]
  ------------------
 1048|      0|                throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
 1049|      0|            }
 1050|     10|            memcpy(outData + i, data + srcIdx * stride, elemSize);
 1051|     10|        }
 1052|      8|    } else { // non-indexed cases
 1053|      8|        if (usedCount * stride > maxSize) {
  ------------------
  |  Branch (1053:13): [True: 0, False: 8]
  ------------------
 1054|      0|            throw DeadlyImportError("GLTF: count*stride ", (usedCount * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
 1055|      0|        }
 1056|      8|        if (stride == elemSize && targetElemSize == elemSize) {
  ------------------
  |  Branch (1056:13): [True: 8, False: 0]
  |  Branch (1056:35): [True: 5, False: 3]
  ------------------
 1057|      5|            memcpy(outData, data, totalSize);
 1058|      5|        } else {
 1059|     15|            for (size_t i = 0; i < usedCount; ++i) {
  ------------------
  |  Branch (1059:32): [True: 12, False: 3]
  ------------------
 1060|     12|                memcpy(outData + i, data + i * stride, elemSize);
 1061|     12|            }
 1062|      3|        }
 1063|      8|    }
 1064|     13|    return usedCount;
 1065|     13|}
_ZN5glTF28Accessor11ExtractDataIA16_fEEmRPT_PKNSt3__16vectorIjNS6_9allocatorIjEEEE:
 1021|    303|size_t Accessor::ExtractData(T *&outData, const std::vector<unsigned int> *remappingIndices) {
 1022|    303|    uint8_t *data = GetPointer();
 1023|    303|    if (!data) {
  ------------------
  |  Branch (1023:9): [True: 9, False: 294]
  ------------------
 1024|      9|        throw DeadlyImportError("GLTF2: data is null when extracting data from ", getContextForErrorMessages(id, name));
 1025|      9|    }
 1026|       |
 1027|    294|    const size_t usedCount = (remappingIndices != nullptr) ? remappingIndices->size() : count;
  ------------------
  |  Branch (1027:30): [True: 0, False: 294]
  ------------------
 1028|    294|    const size_t elemSize = GetElementSize();
 1029|    294|    const size_t totalSize = elemSize * usedCount;
 1030|       |
 1031|    294|    const size_t stride = GetStride();
 1032|       |
 1033|    294|    const size_t targetElemSize = sizeof(T);
 1034|       |
 1035|    294|    if (elemSize > targetElemSize) {
  ------------------
  |  Branch (1035:9): [True: 0, False: 294]
  ------------------
 1036|      0|        throw DeadlyImportError("GLTF: elemSize ", elemSize, " > targetElemSize ", targetElemSize, " in ", getContextForErrorMessages(id, name));
 1037|      0|    }
 1038|       |
 1039|    294|    const size_t maxSize = GetMaxByteSize();
 1040|       |
 1041|    294|    outData = new T[usedCount];
 1042|       |
 1043|    294|    if (remappingIndices != nullptr) {
  ------------------
  |  Branch (1043:9): [True: 0, False: 294]
  ------------------
 1044|      0|        const unsigned int maxIndexCount = static_cast<unsigned int>(maxSize / stride);
 1045|      0|        for (size_t i = 0; i < usedCount; ++i) {
  ------------------
  |  Branch (1045:28): [True: 0, False: 0]
  ------------------
 1046|      0|            size_t srcIdx = (*remappingIndices)[i];
 1047|      0|            if (srcIdx >= maxIndexCount) {
  ------------------
  |  Branch (1047:17): [True: 0, False: 0]
  ------------------
 1048|      0|                throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
 1049|      0|            }
 1050|      0|            memcpy(outData + i, data + srcIdx * stride, elemSize);
 1051|      0|        }
 1052|    294|    } else { // non-indexed cases
 1053|    294|        if (usedCount * stride > maxSize) {
  ------------------
  |  Branch (1053:13): [True: 0, False: 294]
  ------------------
 1054|      0|            throw DeadlyImportError("GLTF: count*stride ", (usedCount * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
 1055|      0|        }
 1056|    294|        if (stride == elemSize && targetElemSize == elemSize) {
  ------------------
  |  Branch (1056:13): [True: 287, False: 7]
  |  Branch (1056:35): [True: 207, False: 80]
  ------------------
 1057|    207|            memcpy(outData, data, totalSize);
 1058|    207|        } else {
 1059|  1.22k|            for (size_t i = 0; i < usedCount; ++i) {
  ------------------
  |  Branch (1059:32): [True: 1.14k, False: 87]
  ------------------
 1060|  1.14k|                memcpy(outData + i, data + i * stride, elemSize);
 1061|  1.14k|            }
 1062|     87|        }
 1063|    294|    }
 1064|    294|    return usedCount;
 1065|    294|}
_ZN5glTF28Accessor11ExtractDataIfEEmRPT_PKNSt3__16vectorIjNS5_9allocatorIjEEEE:
 1021|    120|size_t Accessor::ExtractData(T *&outData, const std::vector<unsigned int> *remappingIndices) {
 1022|    120|    uint8_t *data = GetPointer();
 1023|    120|    if (!data) {
  ------------------
  |  Branch (1023:9): [True: 1, False: 119]
  ------------------
 1024|      1|        throw DeadlyImportError("GLTF2: data is null when extracting data from ", getContextForErrorMessages(id, name));
 1025|      1|    }
 1026|       |
 1027|    119|    const size_t usedCount = (remappingIndices != nullptr) ? remappingIndices->size() : count;
  ------------------
  |  Branch (1027:30): [True: 0, False: 119]
  ------------------
 1028|    119|    const size_t elemSize = GetElementSize();
 1029|    119|    const size_t totalSize = elemSize * usedCount;
 1030|       |
 1031|    119|    const size_t stride = GetStride();
 1032|       |
 1033|    119|    const size_t targetElemSize = sizeof(T);
 1034|       |
 1035|    119|    if (elemSize > targetElemSize) {
  ------------------
  |  Branch (1035:9): [True: 3, False: 116]
  ------------------
 1036|      3|        throw DeadlyImportError("GLTF: elemSize ", elemSize, " > targetElemSize ", targetElemSize, " in ", getContextForErrorMessages(id, name));
 1037|      3|    }
 1038|       |
 1039|    116|    const size_t maxSize = GetMaxByteSize();
 1040|       |
 1041|    116|    outData = new T[usedCount];
 1042|       |
 1043|    116|    if (remappingIndices != nullptr) {
  ------------------
  |  Branch (1043:9): [True: 0, False: 116]
  ------------------
 1044|      0|        const unsigned int maxIndexCount = static_cast<unsigned int>(maxSize / stride);
 1045|      0|        for (size_t i = 0; i < usedCount; ++i) {
  ------------------
  |  Branch (1045:28): [True: 0, False: 0]
  ------------------
 1046|      0|            size_t srcIdx = (*remappingIndices)[i];
 1047|      0|            if (srcIdx >= maxIndexCount) {
  ------------------
  |  Branch (1047:17): [True: 0, False: 0]
  ------------------
 1048|      0|                throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
 1049|      0|            }
 1050|      0|            memcpy(outData + i, data + srcIdx * stride, elemSize);
 1051|      0|        }
 1052|    116|    } else { // non-indexed cases
 1053|    116|        if (usedCount * stride > maxSize) {
  ------------------
  |  Branch (1053:13): [True: 0, False: 116]
  ------------------
 1054|      0|            throw DeadlyImportError("GLTF: count*stride ", (usedCount * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
 1055|      0|        }
 1056|    116|        if (stride == elemSize && targetElemSize == elemSize) {
  ------------------
  |  Branch (1056:13): [True: 114, False: 2]
  |  Branch (1056:35): [True: 84, False: 30]
  ------------------
 1057|     84|            memcpy(outData, data, totalSize);
 1058|     84|        } else {
 1059|    466|            for (size_t i = 0; i < usedCount; ++i) {
  ------------------
  |  Branch (1059:32): [True: 434, False: 32]
  ------------------
 1060|    434|                memcpy(outData + i, data + i * stride, elemSize);
 1061|    434|            }
 1062|     32|        }
 1063|    116|    }
 1064|    116|    return usedCount;
 1065|    116|}
_ZN5glTF28Accessor11ExtractDataI5vec4fEEmRPT_PKNSt3__16vectorIjNS6_9allocatorIjEEEE:
 1021|     44|size_t Accessor::ExtractData(T *&outData, const std::vector<unsigned int> *remappingIndices) {
 1022|     44|    uint8_t *data = GetPointer();
 1023|     44|    if (!data) {
  ------------------
  |  Branch (1023:9): [True: 3, False: 41]
  ------------------
 1024|      3|        throw DeadlyImportError("GLTF2: data is null when extracting data from ", getContextForErrorMessages(id, name));
 1025|      3|    }
 1026|       |
 1027|     41|    const size_t usedCount = (remappingIndices != nullptr) ? remappingIndices->size() : count;
  ------------------
  |  Branch (1027:30): [True: 0, False: 41]
  ------------------
 1028|     41|    const size_t elemSize = GetElementSize();
 1029|     41|    const size_t totalSize = elemSize * usedCount;
 1030|       |
 1031|     41|    const size_t stride = GetStride();
 1032|       |
 1033|     41|    const size_t targetElemSize = sizeof(T);
 1034|       |
 1035|     41|    if (elemSize > targetElemSize) {
  ------------------
  |  Branch (1035:9): [True: 1, False: 40]
  ------------------
 1036|      1|        throw DeadlyImportError("GLTF: elemSize ", elemSize, " > targetElemSize ", targetElemSize, " in ", getContextForErrorMessages(id, name));
 1037|      1|    }
 1038|       |
 1039|     40|    const size_t maxSize = GetMaxByteSize();
 1040|       |
 1041|     40|    outData = new T[usedCount];
 1042|       |
 1043|     40|    if (remappingIndices != nullptr) {
  ------------------
  |  Branch (1043:9): [True: 0, False: 40]
  ------------------
 1044|      0|        const unsigned int maxIndexCount = static_cast<unsigned int>(maxSize / stride);
 1045|      0|        for (size_t i = 0; i < usedCount; ++i) {
  ------------------
  |  Branch (1045:28): [True: 0, False: 0]
  ------------------
 1046|      0|            size_t srcIdx = (*remappingIndices)[i];
 1047|      0|            if (srcIdx >= maxIndexCount) {
  ------------------
  |  Branch (1047:17): [True: 0, False: 0]
  ------------------
 1048|      0|                throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
 1049|      0|            }
 1050|      0|            memcpy(outData + i, data + srcIdx * stride, elemSize);
 1051|      0|        }
 1052|     40|    } else { // non-indexed cases
 1053|     40|        if (usedCount * stride > maxSize) {
  ------------------
  |  Branch (1053:13): [True: 0, False: 40]
  ------------------
 1054|      0|            throw DeadlyImportError("GLTF: count*stride ", (usedCount * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
 1055|      0|        }
 1056|     40|        if (stride == elemSize && targetElemSize == elemSize) {
  ------------------
  |  Branch (1056:13): [True: 38, False: 2]
  |  Branch (1056:35): [True: 4, False: 34]
  ------------------
 1057|      4|            memcpy(outData, data, totalSize);
 1058|     36|        } else {
 1059|    954|            for (size_t i = 0; i < usedCount; ++i) {
  ------------------
  |  Branch (1059:32): [True: 918, False: 36]
  ------------------
 1060|    918|                memcpy(outData + i, data + i * stride, elemSize);
 1061|    918|            }
 1062|     36|        }
 1063|     40|    }
 1064|     40|    return usedCount;
 1065|     40|}
_ZN5glTF28Accessor11ExtractDataI13aiQuaterniontIfEEEmRPT_PKNSt3__16vectorIjNS7_9allocatorIjEEEE:
 1021|     71|size_t Accessor::ExtractData(T *&outData, const std::vector<unsigned int> *remappingIndices) {
 1022|     71|    uint8_t *data = GetPointer();
 1023|     71|    if (!data) {
  ------------------
  |  Branch (1023:9): [True: 2, False: 69]
  ------------------
 1024|      2|        throw DeadlyImportError("GLTF2: data is null when extracting data from ", getContextForErrorMessages(id, name));
 1025|      2|    }
 1026|       |
 1027|     69|    const size_t usedCount = (remappingIndices != nullptr) ? remappingIndices->size() : count;
  ------------------
  |  Branch (1027:30): [True: 0, False: 69]
  ------------------
 1028|     69|    const size_t elemSize = GetElementSize();
 1029|     69|    const size_t totalSize = elemSize * usedCount;
 1030|       |
 1031|     69|    const size_t stride = GetStride();
 1032|       |
 1033|     69|    const size_t targetElemSize = sizeof(T);
 1034|       |
 1035|     69|    if (elemSize > targetElemSize) {
  ------------------
  |  Branch (1035:9): [True: 1, False: 68]
  ------------------
 1036|      1|        throw DeadlyImportError("GLTF: elemSize ", elemSize, " > targetElemSize ", targetElemSize, " in ", getContextForErrorMessages(id, name));
 1037|      1|    }
 1038|       |
 1039|     68|    const size_t maxSize = GetMaxByteSize();
 1040|       |
 1041|     68|    outData = new T[usedCount];
 1042|       |
 1043|     68|    if (remappingIndices != nullptr) {
  ------------------
  |  Branch (1043:9): [True: 0, False: 68]
  ------------------
 1044|      0|        const unsigned int maxIndexCount = static_cast<unsigned int>(maxSize / stride);
 1045|      0|        for (size_t i = 0; i < usedCount; ++i) {
  ------------------
  |  Branch (1045:28): [True: 0, False: 0]
  ------------------
 1046|      0|            size_t srcIdx = (*remappingIndices)[i];
 1047|      0|            if (srcIdx >= maxIndexCount) {
  ------------------
  |  Branch (1047:17): [True: 0, False: 0]
  ------------------
 1048|      0|                throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
 1049|      0|            }
 1050|      0|            memcpy(outData + i, data + srcIdx * stride, elemSize);
 1051|      0|        }
 1052|     68|    } else { // non-indexed cases
 1053|     68|        if (usedCount * stride > maxSize) {
  ------------------
  |  Branch (1053:13): [True: 0, False: 68]
  ------------------
 1054|      0|            throw DeadlyImportError("GLTF: count*stride ", (usedCount * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
 1055|      0|        }
 1056|     68|        if (stride == elemSize && targetElemSize == elemSize) {
  ------------------
  |  Branch (1056:13): [True: 67, False: 1]
  |  Branch (1056:35): [True: 24, False: 43]
  ------------------
 1057|     24|            memcpy(outData, data, totalSize);
 1058|     44|        } else {
 1059|    778|            for (size_t i = 0; i < usedCount; ++i) {
  ------------------
  |  Branch (1059:32): [True: 734, False: 44]
  ------------------
 1060|    734|                memcpy(outData + i, data + i * stride, elemSize);
 1061|    734|            }
 1062|     44|        }
 1063|     68|    }
 1064|     68|    return usedCount;
 1065|     68|}

_ZN6Assimp13glTF2ImporterC2Ev:
  101|  5.13k|        mScene(nullptr) {
  102|       |    // empty
  103|  5.13k|}
_ZNK6Assimp13glTF2Importer7GetInfoEv:
  105|  18.5k|const aiImporterDesc *glTF2Importer::GetInfo() const {
  106|  18.5k|    return &desc;
  107|  18.5k|}
_ZNK6Assimp13glTF2Importer7CanReadERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEPNS_8IOSystemEb:
  109|  6.07k|bool glTF2Importer::CanRead(const std::string &filename, IOSystem *pIOHandler, bool checkSig) const {
  110|  6.07k|    const std::string extension = GetExtension(filename);
  111|  6.07k|    if (!checkSig && (extension != "gltf") && (extension != "glb") && (extension != "vrm")) {
  ------------------
  |  Branch (111:9): [True: 0, False: 6.07k]
  |  Branch (111:22): [True: 0, False: 0]
  |  Branch (111:47): [True: 0, False: 0]
  |  Branch (111:71): [True: 0, False: 0]
  ------------------
  112|      0|        return false;
  113|      0|    }
  114|       |
  115|  6.07k|    if (pIOHandler) {
  ------------------
  |  Branch (115:9): [True: 6.07k, False: 0]
  ------------------
  116|  6.07k|        Asset asset(pIOHandler);
  117|  6.07k|        return asset.CanRead(
  118|  6.07k|            filename,
  119|  6.07k|            CheckMagicToken(
  120|  6.07k|                pIOHandler, filename, AI_GLB_MAGIC_NUMBER, 1, 0,
  ------------------
  |  |  147|  6.07k|#define AI_GLB_MAGIC_NUMBER "glTF"
  ------------------
  121|  6.07k|                static_cast<unsigned int>(strlen(AI_GLB_MAGIC_NUMBER))));
  ------------------
  |  |  147|  6.07k|#define AI_GLB_MAGIC_NUMBER "glTF"
  ------------------
  122|  6.07k|    }
  123|       |
  124|      0|    return false;
  125|  6.07k|}
_ZN6Assimp13glTF2Importer15ImportMaterialsERN5glTF25AssetE:
  397|  2.35k|void glTF2Importer::ImportMaterials(Asset &r) {
  398|  2.35k|    const unsigned int numImportedMaterials = unsigned(r.materials.Size());
  399|  2.35k|    ASSIMP_LOG_DEBUG("Importing ", numImportedMaterials, " materials");
  400|  2.35k|    Material defaultMaterial;
  401|       |
  402|  2.35k|    mScene->mNumMaterials = numImportedMaterials + 1;
  403|  2.35k|    mScene->mMaterials = new aiMaterial *[mScene->mNumMaterials];
  404|  2.35k|    std::fill(mScene->mMaterials, mScene->mMaterials + mScene->mNumMaterials, nullptr);
  405|  2.35k|    mScene->mMaterials[numImportedMaterials] = ImportMaterial(mEmbeddedTexIdxs, r, defaultMaterial);
  406|       |
  407|  4.58k|    for (unsigned int i = 0; i < numImportedMaterials; ++i) {
  ------------------
  |  Branch (407:30): [True: 2.23k, False: 2.35k]
  ------------------
  408|  2.23k|        mScene->mMaterials[i] = ImportMaterial(mEmbeddedTexIdxs, r, r.materials[i]);
  409|  2.23k|    }
  410|  2.35k|}
_ZN6Assimp13glTF2Importer12ImportMeshesERN5glTF25AssetE:
  476|  2.35k|void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
  477|  2.35k|    ASSIMP_LOG_DEBUG("Importing ", r.meshes.Size(), " meshes");
  478|  2.35k|    std::vector<std::unique_ptr<aiMesh>> meshes;
  479|       |
  480|  2.35k|    meshOffsets.clear();
  481|  2.35k|    meshOffsets.reserve(r.meshes.Size() + 1);
  482|  2.35k|    mVertexRemappingTables.clear();
  483|       |
  484|       |    // Count the number of aiMeshes
  485|  2.35k|    unsigned int num_aiMeshes = 0;
  486|  5.16k|    for (unsigned int m = 0; m < r.meshes.Size(); ++m) {
  ------------------
  |  Branch (486:30): [True: 2.81k, False: 2.35k]
  ------------------
  487|  2.81k|        meshOffsets.push_back(num_aiMeshes);
  488|  2.81k|        num_aiMeshes += unsigned(r.meshes[m].primitives.size());
  489|  2.81k|    }
  490|  2.35k|    meshOffsets.push_back(num_aiMeshes); // add a last element so we can always do meshOffsets[n+1] - meshOffsets[n]
  491|       |
  492|  2.35k|    std::vector<unsigned int> reverseMappingIndices;
  493|  2.35k|    std::vector<unsigned int> indexBuffer;
  494|  2.35k|    meshes.reserve(num_aiMeshes);
  495|  2.35k|    mVertexRemappingTables.resize(num_aiMeshes);
  496|       |
  497|  4.08k|    for (unsigned int m = 0; m < r.meshes.Size(); ++m) {
  ------------------
  |  Branch (497:30): [True: 2.07k, False: 2.00k]
  ------------------
  498|  2.07k|        Mesh &mesh = r.meshes[m];
  499|       |
  500|  3.67k|        for (unsigned int p = 0; p < mesh.primitives.size(); ++p) {
  ------------------
  |  Branch (500:34): [True: 1.94k, False: 1.72k]
  ------------------
  501|  1.94k|            Mesh::Primitive &prim = mesh.primitives[p];
  502|       |
  503|  1.94k|            Mesh::Primitive::Attributes &attr = prim.attributes;
  504|       |
  505|       |            // Find out the maximum number of vertices:
  506|  1.94k|            size_t numAllVertices = 0;
  507|  1.94k|            if (!attr.position.empty() && attr.position[0]) {
  ------------------
  |  Branch (507:17): [True: 1.81k, False: 135]
  |  Branch (507:43): [True: 1.81k, False: 0]
  ------------------
  508|  1.81k|                numAllVertices = attr.position[0]->count;
  509|  1.81k|            }
  510|       |
  511|       |            // Extract used vertices:
  512|  1.94k|            bool useIndexBuffer = prim.indices;
  513|  1.94k|            std::vector<unsigned int> *vertexRemappingTable = nullptr;
  514|       |
  515|  1.94k|            if (useIndexBuffer) {
  ------------------
  |  Branch (515:17): [True: 1.31k, False: 638]
  ------------------
  516|  1.31k|                size_t count = prim.indices->count;
  517|  1.31k|                indexBuffer.resize(count);
  518|  1.31k|                reverseMappingIndices.clear();
  519|  1.31k|                vertexRemappingTable = &mVertexRemappingTables[meshes.size()];
  520|  1.31k|                vertexRemappingTable->reserve(count / 3); // this is a very rough heuristic to reduce re-allocations
  521|  1.31k|                Accessor::Indexer data = prim.indices->GetIndexer();
  522|  1.31k|                if (!data.IsValid()) {
  ------------------
  |  Branch (522:21): [True: 52, False: 1.25k]
  ------------------
  523|     52|                    throw DeadlyImportError("GLTF: Invalid accessor without data in mesh ", getContextForErrorMessages(mesh.id, mesh.name));
  524|     52|                }
  525|       |
  526|       |                // Build the vertex remapping table and the modified index buffer (used later instead of the original one)
  527|       |                // In case no index buffer is used, the original vertex arrays are being used so no remapping is required in the first place.
  528|  1.25k|                const unsigned int unusedIndex = ~0u;
  529|  29.9k|                for (unsigned int i = 0; i < count; ++i) {
  ------------------
  |  Branch (529:42): [True: 28.6k, False: 1.25k]
  ------------------
  530|  28.6k|                    unsigned int index = data.GetUInt(i);
  531|  28.6k|                    if (index >= numAllVertices) {
  ------------------
  |  Branch (531:25): [True: 11.9k, False: 16.7k]
  ------------------
  532|       |                        // Out-of-range indices will be filtered out when adding the faces and then lead to a warning. At this stage, we just keep them.
  533|  11.9k|                        indexBuffer[i] = index;
  534|  11.9k|                        continue;
  535|  11.9k|                    }
  536|  16.7k|                    if (index >= reverseMappingIndices.size()) {
  ------------------
  |  Branch (536:25): [True: 7.22k, False: 9.54k]
  ------------------
  537|  7.22k|                        reverseMappingIndices.resize(index + 1, unusedIndex);
  538|  7.22k|                    }
  539|  16.7k|                    if (reverseMappingIndices[index] == unusedIndex) {
  ------------------
  |  Branch (539:25): [True: 8.11k, False: 8.65k]
  ------------------
  540|  8.11k|                        reverseMappingIndices[index] = static_cast<unsigned int>(vertexRemappingTable->size());
  541|  8.11k|                        vertexRemappingTable->push_back(index);
  542|  8.11k|                    }
  543|  16.7k|                    indexBuffer[i] = reverseMappingIndices[index];
  544|  16.7k|                }
  545|  1.25k|            }
  546|       |
  547|  1.89k|            aiMesh *aim = new aiMesh();
  548|  1.89k|            meshes.push_back(std::unique_ptr<aiMesh>(aim));
  549|       |
  550|  1.89k|            aim->mName = mesh.name.empty() ? mesh.id : mesh.name;
  ------------------
  |  Branch (550:26): [True: 422, False: 1.47k]
  ------------------
  551|       |
  552|  1.89k|            if (mesh.primitives.size() > 1) {
  ------------------
  |  Branch (552:17): [True: 15, False: 1.88k]
  ------------------
  553|     15|                ai_uint32 &len = aim->mName.length;
  554|     15|                aim->mName.data[len] = '-';
  555|     15|                len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(AI_MAXLEN - len - 1), p);
  556|     15|            }
  557|       |
  558|  1.89k|            switch (prim.mode) {
  ------------------
  |  Branch (558:21): [True: 1.87k, False: 18]
  ------------------
  559|     50|            case PrimitiveMode_POINTS:
  ------------------
  |  Branch (559:13): [True: 50, False: 1.84k]
  ------------------
  560|     50|                aim->mPrimitiveTypes |= aiPrimitiveType_POINT;
  561|     50|                break;
  562|       |
  563|     71|            case PrimitiveMode_LINES:
  ------------------
  |  Branch (563:13): [True: 71, False: 1.82k]
  ------------------
  564|    190|            case PrimitiveMode_LINE_LOOP:
  ------------------
  |  Branch (564:13): [True: 119, False: 1.77k]
  ------------------
  565|    264|            case PrimitiveMode_LINE_STRIP:
  ------------------
  |  Branch (565:13): [True: 74, False: 1.82k]
  ------------------
  566|    264|                aim->mPrimitiveTypes |= aiPrimitiveType_LINE;
  567|    264|                break;
  568|       |
  569|  1.00k|            case PrimitiveMode_TRIANGLES:
  ------------------
  |  Branch (569:13): [True: 1.00k, False: 894]
  ------------------
  570|  1.36k|            case PrimitiveMode_TRIANGLE_STRIP:
  ------------------
  |  Branch (570:13): [True: 357, False: 1.54k]
  ------------------
  571|  1.56k|            case PrimitiveMode_TRIANGLE_FAN:
  ------------------
  |  Branch (571:13): [True: 205, False: 1.69k]
  ------------------
  572|  1.56k|                aim->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
  573|  1.56k|                break;
  574|  1.89k|            }
  575|       |
  576|  1.89k|            if (!attr.position.empty() && attr.position[0]) {
  ------------------
  |  Branch (576:17): [True: 1.76k, False: 123]
  |  Branch (576:43): [True: 1.76k, False: 0]
  ------------------
  577|  1.76k|                aim->mNumVertices = static_cast<unsigned int>(attr.position[0]->ExtractData(aim->mVertices, vertexRemappingTable));
  578|  1.76k|            }
  579|       |
  580|  1.89k|            if (!attr.normal.empty() && attr.normal[0]) {
  ------------------
  |  Branch (580:17): [True: 1.50k, False: 391]
  |  Branch (580:41): [True: 1.50k, False: 0]
  ------------------
  581|  1.50k|                    if (attr.normal[0]->count != numAllVertices) {
  ------------------
  |  Branch (581:25): [True: 347, False: 1.15k]
  ------------------
  582|    347|                    DefaultLogger::get()->warn("Normal count in mesh \"", mesh.name, "\" does not match the vertex count, normals ignored.");
  583|  1.15k|                } else {
  584|  1.15k|                    attr.normal[0]->ExtractData(aim->mNormals, vertexRemappingTable);
  585|       |
  586|       |                    // only extract tangents if normals are present
  587|  1.15k|                    if (!attr.tangent.empty() && attr.tangent[0]) {
  ------------------
  |  Branch (587:25): [True: 0, False: 1.15k]
  |  Branch (587:50): [True: 0, False: 0]
  ------------------
  588|      0|                        if (attr.tangent[0]->count != numAllVertices) {
  ------------------
  |  Branch (588:29): [True: 0, False: 0]
  ------------------
  589|      0|                            DefaultLogger::get()->warn("Tangent count in mesh \"", mesh.name, "\" does not match the vertex count, tangents ignored.");
  590|      0|                        } else {
  591|       |                            // generate bitangents from normals and tangents according to spec
  592|      0|                            Tangent *tangents = nullptr;
  593|       |
  594|      0|                            attr.tangent[0]->ExtractData(tangents, vertexRemappingTable);
  595|       |
  596|      0|                            aim->mTangents = new aiVector3D[aim->mNumVertices];
  597|      0|                            aim->mBitangents = new aiVector3D[aim->mNumVertices];
  598|       |
  599|      0|                            for (unsigned int i = 0; i < aim->mNumVertices; ++i) {
  ------------------
  |  Branch (599:54): [True: 0, False: 0]
  ------------------
  600|      0|                                aim->mTangents[i] = tangents[i].xyz;
  601|      0|                                aim->mBitangents[i] = (aim->mNormals[i] ^ tangents[i].xyz) * tangents[i].w;
  602|      0|                            }
  603|       |
  604|      0|                            delete[] tangents;
  605|      0|                        }
  606|      0|                    }
  607|  1.15k|                }
  608|  1.50k|            }
  609|       |
  610|  2.10k|            for (size_t c = 0; c < attr.color.size() && c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c) {
  ------------------
  |  Branch (610:32): [True: 208, False: 1.89k]
  |  Branch (610:57): [True: 208, False: 0]
  ------------------
  611|    208|                if (attr.color[c]->count != numAllVertices) {
  ------------------
  |  Branch (611:21): [True: 9, False: 199]
  ------------------
  612|      9|                    DefaultLogger::get()->warn("Color stream size in mesh \"", mesh.name,
  613|      9|                            "\" does not match the vertex count");
  614|      9|                    continue;
  615|      9|                }
  616|       |
  617|    199|                auto componentType = attr.color[c]->componentType;
  618|    199|                if (componentType == glTF2::ComponentType_FLOAT) {
  ------------------
  |  Branch (618:21): [True: 168, False: 31]
  ------------------
  619|    168|                    attr.color[c]->ExtractData(aim->mColors[c], vertexRemappingTable);
  620|    168|                } else {
  621|     31|                    if (componentType == glTF2::ComponentType_UNSIGNED_BYTE) {
  ------------------
  |  Branch (621:25): [True: 11, False: 20]
  ------------------
  622|     11|                        aim->mColors[c] = GetVertexColorsForType<unsigned char>(attr.color[c], vertexRemappingTable);
  623|     20|                    } else if (componentType == glTF2::ComponentType_UNSIGNED_SHORT) {
  ------------------
  |  Branch (623:32): [True: 14, False: 6]
  ------------------
  624|     14|                        aim->mColors[c] = GetVertexColorsForType<unsigned short>(attr.color[c], vertexRemappingTable);
  625|     14|                    }
  626|     31|                }
  627|    199|            }
  628|  2.49k|            for (size_t tc = 0; tc < attr.texcoord.size() && tc < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) {
  ------------------
  |  Branch (628:33): [True: 602, False: 1.89k]
  |  Branch (628:62): [True: 602, False: 0]
  ------------------
  629|    602|                if (!attr.texcoord[tc]) {
  ------------------
  |  Branch (629:21): [True: 0, False: 602]
  ------------------
  630|      0|                    DefaultLogger::get()->warn("Texture coordinate accessor not found or non-contiguous texture coordinate sets.");
  631|      0|                    continue;
  632|      0|                }
  633|       |
  634|    602|                if (attr.texcoord[tc]->count != numAllVertices) {
  ------------------
  |  Branch (634:21): [True: 37, False: 565]
  ------------------
  635|     37|                    DefaultLogger::get()->warn("Texcoord stream size in mesh \"", mesh.name,
  636|     37|                            "\" does not match the vertex count");
  637|     37|                    continue;
  638|     37|                }
  639|       |
  640|    565|                attr.texcoord[tc]->ExtractData(aim->mTextureCoords[tc], vertexRemappingTable);
  641|    565|                aim->mNumUVComponents[tc] = attr.texcoord[tc]->GetNumComponents();
  642|       |
  643|    565|                aiVector3D *values = aim->mTextureCoords[tc];
  644|  6.30k|                for (unsigned int i = 0; i < aim->mNumVertices; ++i) {
  ------------------
  |  Branch (644:42): [True: 5.73k, False: 565]
  ------------------
  645|  5.73k|                    values[i].y = 1 - values[i].y; // Flip Y coords
  646|  5.73k|                }
  647|    565|            }
  648|       |
  649|  1.89k|            std::vector<Mesh::Primitive::Target> &targets = prim.targets;
  650|  1.89k|            if (!targets.empty()) {
  ------------------
  |  Branch (650:17): [True: 11, False: 1.88k]
  ------------------
  651|     11|                aim->mNumAnimMeshes = (unsigned int)targets.size();
  652|     11|                aim->mAnimMeshes = new aiAnimMesh *[aim->mNumAnimMeshes];
  653|     11|                std::fill(aim->mAnimMeshes, aim->mAnimMeshes + aim->mNumAnimMeshes, nullptr);
  654|     33|                for (size_t i = 0; i < targets.size(); i++) {
  ------------------
  |  Branch (654:36): [True: 22, False: 11]
  ------------------
  655|     22|                    bool needPositions = targets[i].position.size() > 0;
  656|     22|                    bool needNormals = (targets[i].normal.size() > 0) && aim->HasNormals();
  ------------------
  |  Branch (656:40): [True: 0, False: 22]
  |  Branch (656:74): [True: 0, False: 0]
  ------------------
  657|     22|                    bool needTangents = (targets[i].tangent.size() > 0) && aim->HasTangentsAndBitangents();
  ------------------
  |  Branch (657:41): [True: 0, False: 22]
  |  Branch (657:76): [True: 0, False: 0]
  ------------------
  658|       |                    // GLTF morph does not support colors and texCoords
  659|     22|                    aim->mAnimMeshes[i] = aiCreateAnimMesh(aim,
  660|     22|                            needPositions, needNormals, needTangents, false, false);
  661|     22|                    aiAnimMesh &aiAnimMesh = *(aim->mAnimMeshes[i]);
  662|     22|                    Mesh::Primitive::Target &target = targets[i];
  663|       |
  664|     22|                    if (needPositions) {
  ------------------
  |  Branch (664:25): [True: 0, False: 22]
  ------------------
  665|      0|                        if (target.position[0]->count != numAllVertices) {
  ------------------
  |  Branch (665:29): [True: 0, False: 0]
  ------------------
  666|      0|                            ASSIMP_LOG_WARN("Positions of target ", i, " in mesh \"", mesh.name, "\" does not match the vertex count");
  667|      0|                        } else {
  668|      0|                            aiVector3D *positionDiff = nullptr;
  669|      0|                            target.position[0]->ExtractData(positionDiff, vertexRemappingTable);
  670|      0|                            for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) {
  ------------------
  |  Branch (670:61): [True: 0, False: 0]
  ------------------
  671|      0|                                aiAnimMesh.mVertices[vertexId] += positionDiff[vertexId];
  672|      0|                            }
  673|      0|                            delete[] positionDiff;
  674|      0|                        }
  675|      0|                    }
  676|     22|                    if (needNormals) {
  ------------------
  |  Branch (676:25): [True: 0, False: 22]
  ------------------
  677|      0|                        if (target.normal[0]->count != numAllVertices) {
  ------------------
  |  Branch (677:29): [True: 0, False: 0]
  ------------------
  678|      0|                            ASSIMP_LOG_WARN("Normals of target ", i, " in mesh \"", mesh.name, "\" does not match the vertex count");
  679|      0|                        } else {
  680|      0|                            aiVector3D *normalDiff = nullptr;
  681|      0|                            target.normal[0]->ExtractData(normalDiff, vertexRemappingTable);
  682|      0|                            for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) {
  ------------------
  |  Branch (682:61): [True: 0, False: 0]
  ------------------
  683|      0|                                aiAnimMesh.mNormals[vertexId] += normalDiff[vertexId];
  684|      0|                            }
  685|      0|                            delete[] normalDiff;
  686|      0|                        }
  687|      0|                    }
  688|     22|                    if (needTangents) {
  ------------------
  |  Branch (688:25): [True: 0, False: 22]
  ------------------
  689|      0|                        if (!aiAnimMesh.HasNormals()) {
  ------------------
  |  Branch (689:29): [True: 0, False: 0]
  ------------------
  690|       |                            // prevent nullptr access to aiAnimMesh.mNormals below when no normals are available
  691|      0|                            ASSIMP_LOG_WARN("Bitangents of target ", i, " in mesh \"", mesh.name, "\" can't be computed, because mesh has no normals.");
  692|      0|                        } else if (target.tangent[0]->count != numAllVertices) {
  ------------------
  |  Branch (692:36): [True: 0, False: 0]
  ------------------
  693|      0|                            ASSIMP_LOG_WARN("Tangents of target ", i, " in mesh \"", mesh.name, "\" does not match the vertex count");
  694|      0|                        } else {
  695|      0|                            Tangent *tangent = nullptr;
  696|      0|                            attr.tangent[0]->ExtractData(tangent, vertexRemappingTable);
  697|       |
  698|      0|                            aiVector3D *tangentDiff = nullptr;
  699|      0|                            target.tangent[0]->ExtractData(tangentDiff, vertexRemappingTable);
  700|       |
  701|      0|                            for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; ++vertexId) {
  ------------------
  |  Branch (701:61): [True: 0, False: 0]
  ------------------
  702|      0|                                tangent[vertexId].xyz += tangentDiff[vertexId];
  703|      0|                                aiAnimMesh.mTangents[vertexId] = tangent[vertexId].xyz;
  704|      0|                                aiAnimMesh.mBitangents[vertexId] = (aiAnimMesh.mNormals[vertexId] ^ tangent[vertexId].xyz) * tangent[vertexId].w;
  705|      0|                            }
  706|      0|                            delete[] tangent;
  707|      0|                            delete[] tangentDiff;
  708|      0|                        }
  709|      0|                    }
  710|     22|                    if (mesh.weights.size() > i) {
  ------------------
  |  Branch (710:25): [True: 4, False: 18]
  ------------------
  711|      4|                        aiAnimMesh.mWeight = mesh.weights[i];
  712|      4|                    }
  713|     22|                    if (mesh.targetNames.size() > i) {
  ------------------
  |  Branch (713:25): [True: 0, False: 22]
  ------------------
  714|      0|                        aiAnimMesh.mName = mesh.targetNames[i];
  715|      0|                    }
  716|     22|                }
  717|     11|            }
  718|       |
  719|  1.89k|            aiFace *faces = nullptr;
  720|  1.89k|            aiFace *facePtr = nullptr;
  721|  1.89k|            size_t nFaces = 0;
  722|       |
  723|  1.89k|            if (useIndexBuffer) {
  ------------------
  |  Branch (723:17): [True: 1.25k, False: 641]
  ------------------
  724|  1.25k|                size_t count = indexBuffer.size();
  725|       |
  726|  1.25k|                switch (prim.mode) {
  ------------------
  |  Branch (726:25): [True: 1.24k, False: 3]
  ------------------
  727|     33|                case PrimitiveMode_POINTS: {
  ------------------
  |  Branch (727:17): [True: 33, False: 1.21k]
  ------------------
  728|     33|                    nFaces = count;
  729|     33|                    facePtr = faces = new aiFace[nFaces];
  730|    982|                    for (unsigned int i = 0; i < count; ++i) {
  ------------------
  |  Branch (730:46): [True: 949, False: 33]
  ------------------
  731|    949|                        SetFaceAndAdvance1(facePtr, aim->mNumVertices, indexBuffer[i]);
  732|    949|                    }
  733|     33|                    break;
  734|      0|                }
  735|       |
  736|     60|                case PrimitiveMode_LINES: {
  ------------------
  |  Branch (736:17): [True: 60, False: 1.19k]
  ------------------
  737|     60|                    nFaces = count / 2;
  738|     60|                    if (nFaces * 2 != count) {
  ------------------
  |  Branch (738:25): [True: 5, False: 55]
  ------------------
  739|      5|                        ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped.");
  740|      5|                        count = nFaces * 2;
  741|      5|                    }
  742|     60|                    facePtr = faces = new aiFace[nFaces];
  743|  1.10k|                    for (unsigned int i = 0; i < count; i += 2) {
  ------------------
  |  Branch (743:46): [True: 1.04k, False: 60]
  ------------------
  744|  1.04k|                        SetFaceAndAdvance2(facePtr, aim->mNumVertices, indexBuffer[i], indexBuffer[i + 1]);
  745|  1.04k|                    }
  746|     60|                    break;
  747|      0|                }
  748|       |
  749|     41|                case PrimitiveMode_LINE_LOOP:
  ------------------
  |  Branch (749:17): [True: 41, False: 1.21k]
  ------------------
  750|    106|                case PrimitiveMode_LINE_STRIP: {
  ------------------
  |  Branch (750:17): [True: 65, False: 1.18k]
  ------------------
  751|    106|                    nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0);
  ------------------
  |  Branch (751:39): [True: 65, False: 41]
  ------------------
  752|    106|                    facePtr = faces = new aiFace[nFaces];
  753|    106|                    SetFaceAndAdvance2(facePtr, aim->mNumVertices, indexBuffer[0], indexBuffer[1]);
  754|  3.46k|                    for (unsigned int i = 2; i < count; ++i) {
  ------------------
  |  Branch (754:46): [True: 3.36k, False: 106]
  ------------------
  755|  3.36k|                        SetFaceAndAdvance2(facePtr, aim->mNumVertices, indexBuffer[i - 1], indexBuffer[i]);
  756|  3.36k|                    }
  757|    106|                    if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop
  ------------------
  |  Branch (757:25): [True: 41, False: 65]
  ------------------
  758|     41|                        SetFaceAndAdvance2(facePtr, aim->mNumVertices, indexBuffer[static_cast<int>(count) - 1], faces[0].mIndices[0]);
  759|     41|                    }
  760|    106|                    break;
  761|     41|                }
  762|       |
  763|    736|                case PrimitiveMode_TRIANGLES: {
  ------------------
  |  Branch (763:17): [True: 736, False: 515]
  ------------------
  764|    736|                    nFaces = count / 3;
  765|    736|                    if (nFaces * 3 != count) {
  ------------------
  |  Branch (765:25): [True: 74, False: 662]
  ------------------
  766|     74|                        ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped.");
  767|     74|                        count = nFaces * 3;
  768|     74|                    }
  769|       |                    // copycd:: than > 0
  770|    736|                    if (nFaces > 0) {
  ------------------
  |  Branch (770:25): [True: 731, False: 5]
  ------------------
  771|    731|                        facePtr = faces = new aiFace[nFaces];
  772|  4.52k|                        for (unsigned int i = 0; i < count; i += 3) {
  ------------------
  |  Branch (772:50): [True: 3.79k, False: 731]
  ------------------
  773|  3.79k|                            SetFaceAndAdvance3(facePtr, aim->mNumVertices, indexBuffer[i], indexBuffer[i + 1], indexBuffer[i + 2]);
  774|  3.79k|                        }
  775|    731|                    }
  776|    736|                    break;
  777|     41|                }
  778|    172|                case PrimitiveMode_TRIANGLE_STRIP: {
  ------------------
  |  Branch (778:17): [True: 172, False: 1.07k]
  ------------------
  779|    172|                    nFaces = count - 2;
  780|    172|                    facePtr = faces = new aiFace[nFaces];
  781|  5.64k|                    for (unsigned int i = 0; i < nFaces; ++i) {
  ------------------
  |  Branch (781:46): [True: 5.47k, False: 172]
  ------------------
  782|       |                        // The ordering is to ensure that the triangles are all drawn with the same orientation
  783|  5.47k|                        if ((i + 1) % 2 == 0) {
  ------------------
  |  Branch (783:29): [True: 2.73k, False: 2.73k]
  ------------------
  784|       |                            // For even n, vertices n + 1, n, and n + 2 define triangle n
  785|  2.73k|                            SetFaceAndAdvance3(facePtr, aim->mNumVertices, indexBuffer[i + 1], indexBuffer[i], indexBuffer[i + 2]);
  786|  2.73k|                        } else {
  787|       |                            // For odd n, vertices n, n+1, and n+2 define triangle n
  788|  2.73k|                            SetFaceAndAdvance3(facePtr, aim->mNumVertices, indexBuffer[i], indexBuffer[i + 1], indexBuffer[i + 2]);
  789|  2.73k|                        }
  790|  5.47k|                    }
  791|    172|                    break;
  792|     41|                }
  793|    141|                case PrimitiveMode_TRIANGLE_FAN:
  ------------------
  |  Branch (793:17): [True: 141, False: 1.11k]
  ------------------
  794|    141|                    nFaces = count - 2;
  795|    141|                    facePtr = faces = new aiFace[nFaces];
  796|    141|                    SetFaceAndAdvance3(facePtr, aim->mNumVertices, indexBuffer[0], indexBuffer[1], indexBuffer[2]);
  797|  4.27k|                    for (unsigned int i = 1; i < nFaces; ++i) {
  ------------------
  |  Branch (797:46): [True: 4.13k, False: 141]
  ------------------
  798|  4.13k|                        SetFaceAndAdvance3(facePtr, aim->mNumVertices, indexBuffer[0], indexBuffer[i + 1], indexBuffer[i + 2]);
  799|  4.13k|                    }
  800|    141|                    break;
  801|  1.25k|                }
  802|  1.25k|            } else { // no indices provided so directly generate from counts
  803|       |
  804|       |                // use the already determined count as it includes checks
  805|    641|                unsigned int count = aim->mNumVertices;
  806|       |
  807|    641|                switch (prim.mode) {
  ------------------
  |  Branch (807:25): [True: 613, False: 28]
  ------------------
  808|     17|                case PrimitiveMode_POINTS: {
  ------------------
  |  Branch (808:17): [True: 17, False: 624]
  ------------------
  809|     17|                    nFaces = count;
  810|     17|                    facePtr = faces = new aiFace[nFaces];
  811|    345|                    for (unsigned int i = 0; i < count; ++i) {
  ------------------
  |  Branch (811:46): [True: 328, False: 17]
  ------------------
  812|    328|                        SetFaceAndAdvance1(facePtr, aim->mNumVertices, i);
  813|    328|                    }
  814|     17|                    break;
  815|      0|                }
  816|       |
  817|     11|                case PrimitiveMode_LINES: {
  ------------------
  |  Branch (817:17): [True: 11, False: 630]
  ------------------
  818|     11|                    nFaces = count / 2;
  819|     11|                    if (nFaces * 2 != count) {
  ------------------
  |  Branch (819:25): [True: 2, False: 9]
  ------------------
  820|      2|                        ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped.");
  821|      2|                        count = (unsigned int)nFaces * 2;
  822|      2|                    }
  823|     11|                    facePtr = faces = new aiFace[nFaces];
  824|    125|                    for (unsigned int i = 0; i < count; i += 2) {
  ------------------
  |  Branch (824:46): [True: 114, False: 11]
  ------------------
  825|    114|                        SetFaceAndAdvance2(facePtr, aim->mNumVertices, i, i + 1);
  826|    114|                    }
  827|     11|                    break;
  828|      0|                }
  829|       |
  830|     76|                case PrimitiveMode_LINE_LOOP:
  ------------------
  |  Branch (830:17): [True: 76, False: 565]
  ------------------
  831|     85|                case PrimitiveMode_LINE_STRIP: {
  ------------------
  |  Branch (831:17): [True: 9, False: 632]
  ------------------
  832|     85|                    nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0);
  ------------------
  |  Branch (832:39): [True: 9, False: 76]
  ------------------
  833|     85|                    facePtr = faces = new aiFace[nFaces];
  834|     85|                    SetFaceAndAdvance2(facePtr, aim->mNumVertices, 0, 1);
  835|  4.68k|                    for (unsigned int i = 2; i < count; ++i) {
  ------------------
  |  Branch (835:46): [True: 4.59k, False: 85]
  ------------------
  836|  4.59k|                        SetFaceAndAdvance2(facePtr, aim->mNumVertices, i - 1, i);
  837|  4.59k|                    }
  838|     85|                    if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop
  ------------------
  |  Branch (838:25): [True: 76, False: 9]
  ------------------
  839|     76|                        SetFaceAndAdvance2(facePtr, aim->mNumVertices, count - 1, 0);
  840|     76|                    }
  841|     85|                    break;
  842|     76|                }
  843|       |
  844|    256|                case PrimitiveMode_TRIANGLES: {
  ------------------
  |  Branch (844:17): [True: 256, False: 385]
  ------------------
  845|    256|                    nFaces = count / 3;
  846|    256|                    if (nFaces * 3 != count) {
  ------------------
  |  Branch (846:25): [True: 74, False: 182]
  ------------------
  847|     74|                        ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped.");
  848|     74|                        count = (unsigned int)nFaces * 3;
  849|     74|                    }
  850|    256|                    facePtr = faces = new aiFace[nFaces];
  851|  1.55k|                    for (unsigned int i = 0; i < count; i += 3) {
  ------------------
  |  Branch (851:46): [True: 1.29k, False: 256]
  ------------------
  852|  1.29k|                        SetFaceAndAdvance3(facePtr, aim->mNumVertices, i, i + 1, i + 2);
  853|  1.29k|                    }
  854|    256|                    break;
  855|     76|                }
  856|    180|                case PrimitiveMode_TRIANGLE_STRIP: {
  ------------------
  |  Branch (856:17): [True: 180, False: 461]
  ------------------
  857|    180|                    nFaces = count - 2;
  858|    180|                    facePtr = faces = new aiFace[nFaces];
  859|  9.03k|                    for (unsigned int i = 0; i < nFaces; ++i) {
  ------------------
  |  Branch (859:46): [True: 8.85k, False: 180]
  ------------------
  860|       |                        // The ordering is to ensure that the triangles are all drawn with the same orientation
  861|  8.85k|                        if ((i + 1) % 2 == 0) {
  ------------------
  |  Branch (861:29): [True: 4.42k, False: 4.42k]
  ------------------
  862|       |                            // For even n, vertices n + 1, n, and n + 2 define triangle n
  863|  4.42k|                            SetFaceAndAdvance3(facePtr, aim->mNumVertices, i + 1, i, i + 2);
  864|  4.42k|                        } else {
  865|       |                            // For odd n, vertices n, n+1, and n+2 define triangle n
  866|  4.42k|                            SetFaceAndAdvance3(facePtr, aim->mNumVertices, i, i + 1, i + 2);
  867|  4.42k|                        }
  868|  8.85k|                    }
  869|    180|                    break;
  870|     76|                }
  871|     64|                case PrimitiveMode_TRIANGLE_FAN:
  ------------------
  |  Branch (871:17): [True: 64, False: 577]
  ------------------
  872|     64|                    nFaces = count - 2;
  873|     64|                    facePtr = faces = new aiFace[nFaces];
  874|     64|                    SetFaceAndAdvance3(facePtr, aim->mNumVertices, 0, 1, 2);
  875|  1.39k|                    for (unsigned int i = 1; i < nFaces; ++i) {
  ------------------
  |  Branch (875:46): [True: 1.32k, False: 64]
  ------------------
  876|  1.32k|                        SetFaceAndAdvance3(facePtr, aim->mNumVertices, 0, i + 1, i + 2);
  877|  1.32k|                    }
  878|     64|                    break;
  879|    641|                }
  880|    641|            }
  881|       |
  882|  1.86k|            if (faces) {
  ------------------
  |  Branch (882:17): [True: 1.85k, False: 13]
  ------------------
  883|  1.85k|                aim->mFaces = faces;
  884|  1.85k|                const unsigned int actualNumFaces = static_cast<unsigned int>(facePtr - faces);
  885|  1.85k|                if (actualNumFaces < nFaces) {
  ------------------
  |  Branch (885:21): [True: 713, False: 1.14k]
  ------------------
  886|    713|                    ASSIMP_LOG_WARN("Some faces had out-of-range indices. Those faces were dropped.");
  887|    713|                }
  888|  1.85k|                if (actualNumFaces == 0) {
  ------------------
  |  Branch (888:21): [True: 263, False: 1.59k]
  ------------------
  889|    263|                    throw DeadlyImportError("Mesh \"", aim->mName.C_Str(), "\" has no faces");
  890|    263|                }
  891|  1.59k|                aim->mNumFaces = actualNumFaces;
  892|  1.59k|                ai_assert(CheckValidFacesIndices(faces, actualNumFaces, aim->mNumVertices));
  893|  1.59k|            }
  894|       |
  895|  1.60k|            if (prim.material) {
  ------------------
  |  Branch (895:17): [True: 1.18k, False: 420]
  ------------------
  896|  1.18k|                aim->mMaterialIndex = prim.material.GetIndex();
  897|  1.18k|            } else {
  898|    420|                aim->mMaterialIndex = mScene->mNumMaterials - 1;
  899|    420|            }
  900|  1.60k|        }
  901|  2.07k|    }
  902|       |
  903|  2.00k|    CopyVector(meshes, mScene->mMeshes, mScene->mNumMeshes);
  904|  2.00k|}
_ZN6Assimp13glTF2Importer13ImportCamerasERN5glTF25AssetE:
  906|  2.00k|void glTF2Importer::ImportCameras(glTF2::Asset &r) {
  907|  2.00k|    if (!r.cameras.Size()) {
  ------------------
  |  Branch (907:9): [True: 1.97k, False: 35]
  ------------------
  908|  1.97k|        return;
  909|  1.97k|    }
  910|       |
  911|     35|    const unsigned int numCameras = r.cameras.Size();
  912|     35|    ASSIMP_LOG_DEBUG("Importing ", numCameras, " cameras");
  913|     35|    mScene->mNumCameras = numCameras;
  914|     35|    mScene->mCameras = new aiCamera *[numCameras];
  915|     35|    std::fill(mScene->mCameras, mScene->mCameras + numCameras, nullptr);
  916|       |
  917|     85|    for (size_t i = 0; i < numCameras; ++i) {
  ------------------
  |  Branch (917:24): [True: 50, False: 35]
  ------------------
  918|     50|        Camera &cam = r.cameras[i];
  919|       |
  920|     50|        aiCamera *aicam = mScene->mCameras[i] = new aiCamera();
  921|       |
  922|       |        // cameras point in -Z by default, rest is specified in node transform
  923|     50|        aicam->mLookAt = aiVector3D(0.f, 0.f, -1.f);
  924|       |
  925|     50|        if (cam.type == Camera::Perspective) {
  ------------------
  |  Branch (925:13): [True: 37, False: 13]
  ------------------
  926|     37|            aicam->mAspect = cam.cameraProperties.perspective.aspectRatio;
  927|     37|            aicam->mHorizontalFOV = 2.0f * std::atan(std::tan(cam.cameraProperties.perspective.yfov * 0.5f) * ((aicam->mAspect == 0.f) ? 1.f : aicam->mAspect));
  ------------------
  |  Branch (927:112): [True: 19, False: 18]
  ------------------
  928|     37|            aicam->mClipPlaneFar = cam.cameraProperties.perspective.zfar;
  929|     37|            aicam->mClipPlaneNear = cam.cameraProperties.perspective.znear;
  930|     37|        } else {
  931|     13|            aicam->mClipPlaneFar = cam.cameraProperties.ortographic.zfar;
  932|     13|            aicam->mClipPlaneNear = cam.cameraProperties.ortographic.znear;
  933|     13|            aicam->mHorizontalFOV = 0.0;
  934|     13|            aicam->mOrthographicWidth = cam.cameraProperties.ortographic.xmag;
  935|     13|            aicam->mAspect = 1.0f;
  936|     13|            if (0.f != cam.cameraProperties.ortographic.ymag) {
  ------------------
  |  Branch (936:17): [True: 11, False: 2]
  ------------------
  937|     11|                aicam->mAspect = cam.cameraProperties.ortographic.xmag / cam.cameraProperties.ortographic.ymag;
  938|     11|            }
  939|     13|        }
  940|     50|    }
  941|     35|}
_ZN6Assimp13glTF2Importer12ImportLightsERN5glTF25AssetE:
  943|  2.00k|void glTF2Importer::ImportLights(glTF2::Asset &r) {
  944|  2.00k|    if (!r.lights.Size()) {
  ------------------
  |  Branch (944:9): [True: 2.00k, False: 0]
  ------------------
  945|  2.00k|        return;
  946|  2.00k|    }
  947|       |
  948|      0|    const unsigned int numLights = r.lights.Size();
  949|      0|    ASSIMP_LOG_DEBUG("Importing ", numLights, " lights");
  950|      0|    mScene->mNumLights = numLights;
  951|      0|    mScene->mLights = new aiLight *[numLights];
  952|      0|    std::fill(mScene->mLights, mScene->mLights + numLights, nullptr);
  953|       |
  954|      0|    for (size_t i = 0; i < numLights; ++i) {
  ------------------
  |  Branch (954:24): [True: 0, False: 0]
  ------------------
  955|      0|        Light &light = r.lights[i];
  956|       |
  957|      0|        aiLight *ail = mScene->mLights[i] = new aiLight();
  958|       |
  959|      0|        switch (light.type) {
  ------------------
  |  Branch (959:17): [True: 0, False: 0]
  ------------------
  960|      0|        case Light::Directional:
  ------------------
  |  Branch (960:9): [True: 0, False: 0]
  ------------------
  961|      0|            ail->mType = aiLightSource_DIRECTIONAL;
  962|      0|            break;
  963|      0|        case Light::Point:
  ------------------
  |  Branch (963:9): [True: 0, False: 0]
  ------------------
  964|      0|            ail->mType = aiLightSource_POINT;
  965|      0|            break;
  966|      0|        case Light::Spot:
  ------------------
  |  Branch (966:9): [True: 0, False: 0]
  ------------------
  967|      0|            ail->mType = aiLightSource_SPOT;
  968|      0|            break;
  969|      0|        }
  970|       |
  971|      0|        if (ail->mType != aiLightSource_POINT) {
  ------------------
  |  Branch (971:13): [True: 0, False: 0]
  ------------------
  972|      0|            ail->mDirection = aiVector3D(0.0f, 0.0f, -1.0f);
  973|      0|            ail->mUp = aiVector3D(0.0f, 1.0f, 0.0f);
  974|      0|        }
  975|       |
  976|      0|        vec3 colorWithIntensity = { light.color[0] * light.intensity, light.color[1] * light.intensity, light.color[2] * light.intensity };
  977|      0|        CopyValue(colorWithIntensity, ail->mColorAmbient);
  978|      0|        CopyValue(colorWithIntensity, ail->mColorDiffuse);
  979|      0|        CopyValue(colorWithIntensity, ail->mColorSpecular);
  980|       |
  981|      0|        if (ail->mType == aiLightSource_DIRECTIONAL) {
  ------------------
  |  Branch (981:13): [True: 0, False: 0]
  ------------------
  982|      0|            ail->mAttenuationConstant = 1.0;
  983|      0|            ail->mAttenuationLinear = 0.0;
  984|      0|            ail->mAttenuationQuadratic = 0.0;
  985|      0|        } else {
  986|       |            // in PBR attenuation is calculated using inverse square law which can be expressed
  987|       |            // using assimps equation: 1/(att0 + att1 * d + att2 * d*d) with the following parameters
  988|       |            // this is correct equation for the case when range (see
  989|       |            // https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual)
  990|       |            // is not present. When range is not present it is assumed that it is infinite and so numerator is 1.
  991|       |            // When range is present then numerator might be any value in range [0,1] and then assimps equation
  992|       |            // will not suffice. In this case range is added into metadata in ImportNode function
  993|       |            // and its up to implementation to read it when it wants to
  994|      0|            ail->mAttenuationConstant = 0.0;
  995|      0|            ail->mAttenuationLinear = 0.0;
  996|      0|            ail->mAttenuationQuadratic = 1.0;
  997|      0|        }
  998|       |
  999|      0|        if (ail->mType == aiLightSource_SPOT) {
  ------------------
  |  Branch (999:13): [True: 0, False: 0]
  ------------------
 1000|      0|            ail->mAngleInnerCone = light.innerConeAngle;
 1001|      0|            ail->mAngleOuterCone = light.outerConeAngle;
 1002|      0|        }
 1003|      0|    }
 1004|      0|}
_Z15ParseExtensionsP10aiMetadataRKN5glTF215CustomExtensionE:
 1111|  15.6k|void ParseExtensions(aiMetadata *metadata, const CustomExtension &extension) {
 1112|  15.6k|    if (extension.mStringValue.isPresent) {
  ------------------
  |  Branch (1112:9): [True: 3.86k, False: 11.7k]
  ------------------
 1113|  3.86k|        metadata->Add(extension.name, aiString(extension.mStringValue.value));
 1114|  11.7k|    } else if (extension.mDoubleValue.isPresent) {
  ------------------
  |  Branch (1114:16): [True: 112, False: 11.6k]
  ------------------
 1115|    112|        metadata->Add(extension.name, extension.mDoubleValue.value);
 1116|  11.6k|    } else if (extension.mUint64Value.isPresent) {
  ------------------
  |  Branch (1116:16): [True: 7.75k, False: 3.87k]
  ------------------
 1117|  7.75k|        metadata->Add(extension.name, extension.mUint64Value.value);
 1118|  7.75k|    } else if (extension.mInt64Value.isPresent) {
  ------------------
  |  Branch (1118:16): [True: 10, False: 3.86k]
  ------------------
 1119|     10|        metadata->Add(extension.name, static_cast<int32_t>(extension.mInt64Value.value));
 1120|  3.86k|    } else if (extension.mBoolValue.isPresent) {
  ------------------
  |  Branch (1120:16): [True: 3.84k, False: 25]
  ------------------
 1121|  3.84k|        metadata->Add(extension.name, extension.mBoolValue.value);
 1122|  3.84k|    } else if (extension.mValues.isPresent) {
  ------------------
  |  Branch (1122:16): [True: 25, False: 0]
  ------------------
 1123|     25|        aiMetadata val;
 1124|    170|        for (auto const &subExtension : extension.mValues.value) {
  ------------------
  |  Branch (1124:39): [True: 170, False: 25]
  ------------------
 1125|    170|            ParseExtensions(&val, subExtension);
 1126|    170|        }
 1127|     25|        metadata->Add(extension.name, val);
 1128|     25|    }
 1129|  15.6k|}
_Z11ParseExtrasP10aiMetadataRKN5glTF26ExtrasE:
 1131|  3.87k|void ParseExtras(aiMetadata* metadata, const Extras& extras) {
 1132|  15.4k|    for (auto const &value : extras.mValues) {
  ------------------
  |  Branch (1132:28): [True: 15.4k, False: 3.87k]
  ------------------
 1133|  15.4k|        ParseExtensions(metadata, value);
 1134|  15.4k|    }
 1135|  3.87k|}
_ZN6Assimp13glTF2Importer10ImportNodeERN5glTF25AssetERN10glTFCommon3RefINS1_4NodeEEE:
 1137|  7.34k|aiNode *glTF2Importer::ImportNode(glTF2::Asset &r, glTF2::Ref<glTF2::Node> &ptr) {
 1138|  7.34k|    Node &node = *ptr;
 1139|       |
 1140|  7.34k|    aiNode *ainode = new aiNode(GetNodeName(node));
 1141|       |
 1142|  7.34k|    try {
 1143|  7.34k|        if (!node.children.empty()) {
  ------------------
  |  Branch (1143:13): [True: 3.50k, False: 3.84k]
  ------------------
 1144|  3.50k|            ainode->mNumChildren = unsigned(node.children.size());
 1145|  3.50k|            ainode->mChildren = new aiNode *[ainode->mNumChildren];
 1146|  3.50k|            std::fill(ainode->mChildren, ainode->mChildren + ainode->mNumChildren, nullptr);
 1147|       |
 1148|  8.80k|            for (unsigned int i = 0; i < ainode->mNumChildren; ++i) {
  ------------------
  |  Branch (1148:38): [True: 5.30k, False: 3.50k]
  ------------------
 1149|  5.30k|                aiNode *child = ImportNode(r, node.children[i]);
 1150|  5.30k|                child->mParent = ainode;
 1151|  5.30k|                ainode->mChildren[i] = child;
 1152|  5.30k|            }
 1153|  3.50k|        }
 1154|       |
 1155|  7.34k|        if (node.customExtensions || node.extras.HasExtras()) {
  ------------------
  |  Branch (1155:13): [True: 36, False: 7.31k]
  |  Branch (1155:38): [True: 3.87k, False: 3.43k]
  ------------------
 1156|  3.87k|            ainode->mMetaData = new aiMetadata;
 1157|  3.87k|            if (node.customExtensions) {
  ------------------
  |  Branch (1157:17): [True: 0, False: 3.87k]
  ------------------
 1158|      0|                ParseExtensions(ainode->mMetaData, node.customExtensions);
 1159|      0|            }
 1160|  3.87k|            if (node.extras.HasExtras()) {
  ------------------
  |  Branch (1160:17): [True: 3.87k, False: 0]
  ------------------
 1161|  3.87k|                ParseExtras(ainode->mMetaData, node.extras);
 1162|  3.87k|            }
 1163|  3.87k|        }
 1164|       |
 1165|  7.34k|        GetNodeTransform(ainode->mTransformation, node);
 1166|       |
 1167|  7.34k|        if (!node.meshes.empty()) {
  ------------------
  |  Branch (1167:13): [True: 1.82k, False: 5.52k]
  ------------------
 1168|       |            // GLTF files contain at most 1 mesh per node.
 1169|  1.82k|            if (node.meshes.size() > 1) {
  ------------------
  |  Branch (1169:17): [True: 0, False: 1.82k]
  ------------------
 1170|      0|                throw DeadlyImportError("GLTF: Invalid input, found ", node.meshes.size(),
 1171|      0|                        " meshes in ", getContextForErrorMessages(node.id, node.name),
 1172|      0|                        ", but only 1 mesh per node allowed.");
 1173|      0|            }
 1174|  1.82k|            int mesh_idx = node.meshes[0].GetIndex();
 1175|  1.82k|            int count = meshOffsets[mesh_idx + 1] - meshOffsets[mesh_idx];
 1176|       |
 1177|  1.82k|            ainode->mNumMeshes = count;
 1178|  1.82k|            ainode->mMeshes = new unsigned int[count];
 1179|       |
 1180|  1.82k|            if (node.skin) {
  ------------------
  |  Branch (1180:17): [True: 421, False: 1.40k]
  ------------------
 1181|    762|                for (int primitiveNo = 0; primitiveNo < count; ++primitiveNo) {
  ------------------
  |  Branch (1181:43): [True: 341, False: 421]
  ------------------
 1182|    341|                    unsigned int aiMeshIdx = meshOffsets[mesh_idx] + primitiveNo;
 1183|    341|                    aiMesh *mesh = mScene->mMeshes[aiMeshIdx];
 1184|    341|                    unsigned int numBones = static_cast<unsigned int>(node.skin->jointNames.size());
 1185|    341|                    std::vector<unsigned int> *vertexRemappingTablePtr = mVertexRemappingTables[aiMeshIdx].empty() ? nullptr : &mVertexRemappingTables[aiMeshIdx];
  ------------------
  |  Branch (1185:74): [True: 65, False: 276]
  ------------------
 1186|       |
 1187|    341|                    std::vector<std::vector<aiVertexWeight>> weighting(numBones);
 1188|    341|                    BuildVertexWeightMapping(node.meshes[0]->primitives[primitiveNo], weighting, vertexRemappingTablePtr);
 1189|       |
 1190|    341|                    mesh->mNumBones = static_cast<unsigned int>(numBones);
 1191|    341|                    mesh->mBones = new aiBone *[mesh->mNumBones];
 1192|    341|                    std::fill(mesh->mBones, mesh->mBones + mesh->mNumBones, nullptr);
 1193|       |
 1194|       |                    // GLTF and Assimp choose to store bone weights differently.
 1195|       |                    // GLTF has each vertex specify which bones influence the vertex.
 1196|       |                    // Assimp has each bone specify which vertices it has influence over.
 1197|       |                    // To convert this data, we first read over the vertex data and pull
 1198|       |                    // out the bone-to-vertex mapping.  Then, when creating the aiBones,
 1199|       |                    // we copy the bone-to-vertex mapping into the bone.  This is unfortunate
 1200|       |                    // both because it's somewhat slow and because, for many applications,
 1201|       |                    // we then need to reconvert the data back into the vertex-to-bone
 1202|       |                    // mapping which makes things doubly-slow.
 1203|       |
 1204|    341|                    mat4 *pbindMatrices = nullptr;
 1205|    341|                    node.skin->inverseBindMatrices->ExtractData(pbindMatrices, nullptr);
 1206|       |
 1207|  2.19k|                    for (uint32_t i = 0; i < numBones; ++i) {
  ------------------
  |  Branch (1207:42): [True: 1.85k, False: 341]
  ------------------
 1208|  1.85k|                        const std::vector<aiVertexWeight> &weights = weighting[i];
 1209|  1.85k|                        aiBone *bone = new aiBone();
 1210|       |
 1211|  1.85k|                        Ref<Node> joint = node.skin->jointNames[i];
 1212|  1.85k|                        if (!joint->name.empty()) {
  ------------------
  |  Branch (1212:29): [True: 1.85k, False: 0]
  ------------------
 1213|  1.85k|                            bone->mName = joint->name;
 1214|  1.85k|                        } else {
 1215|       |                            // Assimp expects each bone to have a unique name.
 1216|      0|                            static const std::string kDefaultName = "bone_";
 1217|      0|                            char postfix[10] = { 0 };
 1218|      0|                            ASSIMP_itoa10(postfix, i);
 1219|      0|                            bone->mName = (kDefaultName + postfix);
 1220|      0|                        }
 1221|  1.85k|                        GetNodeTransform(bone->mOffsetMatrix, *joint);
 1222|  1.85k|                        CopyValue(pbindMatrices[i], bone->mOffsetMatrix);
 1223|  1.85k|                        bone->mNumWeights = static_cast<uint32_t>(weights.size());
 1224|       |
 1225|  1.85k|                        if (bone->mNumWeights > 0) {
  ------------------
  |  Branch (1225:29): [True: 1.00k, False: 847]
  ------------------
 1226|  1.00k|                            bone->mWeights = new aiVertexWeight[bone->mNumWeights];
 1227|  1.00k|                            memcpy(bone->mWeights, weights.data(), bone->mNumWeights * sizeof(aiVertexWeight));
 1228|  1.00k|                        } else {
 1229|       |                            // Assimp expects all bones to have at least 1 weight.
 1230|    847|                            bone->mWeights = new aiVertexWeight[1];
 1231|    847|                            bone->mNumWeights = 1;
 1232|    847|                            bone->mWeights->mVertexId = 0;
 1233|    847|                            bone->mWeights->mWeight = 0.f;
 1234|    847|                        }
 1235|  1.85k|                        mesh->mBones[i] = bone;
 1236|  1.85k|                    }
 1237|       |
 1238|    341|                    if (pbindMatrices) {
  ------------------
  |  Branch (1238:25): [True: 294, False: 47]
  ------------------
 1239|    294|                        delete[] pbindMatrices;
 1240|    294|                    }
 1241|    341|                }
 1242|    421|            }
 1243|       |
 1244|  1.82k|            int k = 0;
 1245|  3.46k|            for (unsigned int j = meshOffsets[mesh_idx]; j < meshOffsets[mesh_idx + 1]; ++j, ++k) {
  ------------------
  |  Branch (1245:58): [True: 1.64k, False: 1.82k]
  ------------------
 1246|  1.64k|                ainode->mMeshes[k] = j;
 1247|  1.64k|            }
 1248|  1.82k|        }
 1249|       |
 1250|  7.34k|        if (node.camera) {
  ------------------
  |  Branch (1250:13): [True: 62, False: 7.28k]
  ------------------
 1251|     62|            mScene->mCameras[node.camera.GetIndex()]->mName = ainode->mName;
 1252|     62|        }
 1253|       |
 1254|  7.34k|        if (node.light) {
  ------------------
  |  Branch (1254:13): [True: 0, False: 7.34k]
  ------------------
 1255|      0|            mScene->mLights[node.light.GetIndex()]->mName = ainode->mName;
 1256|       |
 1257|       |            // range is optional - see https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual
 1258|       |            // it is added to meta data of parent node, because there is no other place to put it
 1259|      0|            if (node.light->range.isPresent) {
  ------------------
  |  Branch (1259:17): [True: 0, False: 0]
  ------------------
 1260|      0|                if (!ainode->mMetaData) {
  ------------------
  |  Branch (1260:21): [True: 0, False: 0]
  ------------------
 1261|      0|                    ainode->mMetaData = aiMetadata::Alloc(1);
 1262|      0|                    ainode->mMetaData->Set(0, "PBR_LightRange", node.light->range.value);
 1263|      0|                } else {
 1264|      0|                    ainode->mMetaData->Add("PBR_LightRange", node.light->range.value);
 1265|      0|                }
 1266|      0|            }
 1267|      0|        }
 1268|       |
 1269|  7.34k|        return ainode;
 1270|  7.34k|    } catch (...) {
 1271|     83|        delete ainode;
 1272|     83|        throw;
 1273|     83|    }
 1274|  7.34k|}
_ZN6Assimp13glTF2Importer11ImportNodesERN5glTF25AssetE:
 1276|  2.00k|void glTF2Importer::ImportNodes(glTF2::Asset &r) {
 1277|  2.00k|    if (!r.scene) {
  ------------------
  |  Branch (1277:9): [True: 251, False: 1.75k]
  ------------------
 1278|    251|        throw DeadlyImportError("GLTF: No scene");
 1279|    251|    }
 1280|  2.00k|    ASSIMP_LOG_DEBUG("Importing nodes");
 1281|       |
 1282|  1.75k|    std::vector<Ref<Node>> rootNodes = r.scene->nodes;
 1283|       |
 1284|       |    // The root nodes
 1285|  1.75k|    unsigned int numRootNodes = unsigned(rootNodes.size());
 1286|  1.75k|    if (numRootNodes == 1) { // a single root node: use it
  ------------------
  |  Branch (1286:9): [True: 1.52k, False: 237]
  ------------------
 1287|  1.52k|        mScene->mRootNode = ImportNode(r, rootNodes[0]);
 1288|  1.52k|    } else if (numRootNodes > 1) { // more than one root node: create a fake root
  ------------------
  |  Branch (1288:16): [True: 111, False: 126]
  ------------------
 1289|    111|        aiNode *root = mScene->mRootNode = new aiNode("ROOT");
 1290|       |
 1291|    111|        root->mChildren = new aiNode *[numRootNodes];
 1292|    111|        std::fill(root->mChildren, root->mChildren + numRootNodes, nullptr);
 1293|       |
 1294|    637|        for (unsigned int i = 0; i < numRootNodes; ++i) {
  ------------------
  |  Branch (1294:34): [True: 526, False: 111]
  ------------------
 1295|    526|            aiNode *node = ImportNode(r, rootNodes[i]);
 1296|    526|            node->mParent = root;
 1297|    526|            root->mChildren[root->mNumChildren++] = node;
 1298|    526|        }
 1299|    126|    } else {
 1300|    126|        mScene->mRootNode = new aiNode("ROOT");
 1301|    126|    }
 1302|  1.75k|}
_Z14CreateNodeAnimRN5glTF25AssetERNS_4NodeER17AnimationSamplers:
 1331|    120|aiNodeAnim *CreateNodeAnim(glTF2::Asset &, Node &node, AnimationSamplers &samplers) {
 1332|    120|    aiNodeAnim *anim = new aiNodeAnim();
 1333|       |
 1334|    120|    try {
 1335|    120|        anim->mNodeName = GetNodeName(node);
 1336|       |
 1337|    120|        static const float kMillisecondsFromSeconds = 1000.f;
 1338|       |
 1339|    120|        if (samplers.translation && samplers.translation->input && samplers.translation->output) {
  ------------------
  |  Branch (1339:13): [True: 46, False: 74]
  |  Branch (1339:37): [True: 46, False: 0]
  |  Branch (1339:68): [True: 46, False: 0]
  ------------------
 1340|     46|            float *times = nullptr;
 1341|     46|            samplers.translation->input->ExtractData(times);
 1342|     46|            vec4f *tmp_values = nullptr;
 1343|     46|            size_t numItems = samplers.translation->output->ExtractData(tmp_values);
 1344|     46|            aiVector3D *values = new aiVector3D[numItems];
 1345|  1.01k|            for (size_t i = 0; i < numItems; ++i) {
  ------------------
  |  Branch (1345:32): [True: 964, False: 46]
  ------------------
 1346|    964|                values[i].x = tmp_values[i].x;
 1347|    964|                values[i].y = tmp_values[i].y;
 1348|    964|                values[i].z = tmp_values[i].z;
 1349|    964|            }
 1350|     46|            delete[] tmp_values;
 1351|       |
 1352|     46|            const bool isCubic = (samplers.translation->interpolation == Interpolation_CUBICSPLINE);
 1353|     46|            const aiAnimInterpolation interpType = MapInterpolation(samplers.translation->interpolation);
 1354|     46|            const unsigned int numLogicalKeys = static_cast<unsigned int>(samplers.translation->input->count);
 1355|       |
 1356|     46|            if (isCubic) {
  ------------------
  |  Branch (1356:17): [True: 0, False: 46]
  ------------------
 1357|       |                // Store as triplets: in-tangent, value, out-tangent per logical key
 1358|      0|                anim->mNumPositionKeys = numLogicalKeys * 3;
 1359|      0|                anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys];
 1360|      0|                for (unsigned int i = 0; i < numLogicalKeys; ++i) {
  ------------------
  |  Branch (1360:42): [True: 0, False: 0]
  ------------------
 1361|      0|                    unsigned int srcBase = i * 3;
 1362|      0|                    unsigned int dstBase = i * 3;
 1363|      0|                    for (unsigned int t = 0; t < 3; ++t) {
  ------------------
  |  Branch (1363:46): [True: 0, False: 0]
  ------------------
 1364|      0|                        anim->mPositionKeys[dstBase + t].mTime = times[i] * kMillisecondsFromSeconds;
 1365|      0|                        anim->mPositionKeys[dstBase + t].mValue = values[srcBase + t];
 1366|      0|                        anim->mPositionKeys[dstBase + t].mInterpolation = interpType;
 1367|      0|                    }
 1368|      0|                }
 1369|     46|            } else {
 1370|     46|                anim->mNumPositionKeys = numLogicalKeys;
 1371|     46|                anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys];
 1372|    529|                for (unsigned int i = 0; i < anim->mNumPositionKeys; ++i) {
  ------------------
  |  Branch (1372:42): [True: 483, False: 46]
  ------------------
 1373|    483|                    anim->mPositionKeys[i].mTime = times[i] * kMillisecondsFromSeconds;
 1374|    483|                    anim->mPositionKeys[i].mValue = values[i];
 1375|    483|                    anim->mPositionKeys[i].mInterpolation = interpType;
 1376|    483|                }
 1377|     46|            }
 1378|     46|            delete[] times;
 1379|     46|            delete[] values;
 1380|     74|        } else if (node.translation.isPresent) {
  ------------------
  |  Branch (1380:20): [True: 16, False: 58]
  ------------------
 1381|     16|            anim->mNumPositionKeys = 1;
 1382|     16|            anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys];
 1383|     16|            anim->mPositionKeys->mTime = 0.f;
 1384|     16|            anim->mPositionKeys->mValue.x = node.translation.value[0];
 1385|     16|            anim->mPositionKeys->mValue.y = node.translation.value[1];
 1386|     16|            anim->mPositionKeys->mValue.z = node.translation.value[2];
 1387|     16|        }
 1388|       |
 1389|    120|        if (samplers.rotation && samplers.rotation->input && samplers.rotation->output) {
  ------------------
  |  Branch (1389:13): [True: 74, False: 46]
  |  Branch (1389:34): [True: 74, False: 0]
  |  Branch (1389:62): [True: 74, False: 0]
  ------------------
 1390|     74|            float *times = nullptr;
 1391|     74|            samplers.rotation->input->ExtractData(times);
 1392|     74|            aiQuaternion *values = nullptr;
 1393|     74|            samplers.rotation->output->ExtractData(values);
 1394|     74|            const bool isCubic = (samplers.rotation->interpolation == Interpolation_CUBICSPLINE);
 1395|     74|            const aiAnimInterpolation interpType = MapInterpolation(samplers.rotation->interpolation);
 1396|     74|            const unsigned int numLogicalKeys = static_cast<unsigned int>(samplers.rotation->input->count);
 1397|       |
 1398|     74|            if (isCubic) {
  ------------------
  |  Branch (1398:17): [True: 0, False: 74]
  ------------------
 1399|      0|                anim->mNumRotationKeys = numLogicalKeys * 3;
 1400|      0|                anim->mRotationKeys = new aiQuatKey[anim->mNumRotationKeys];
 1401|      0|                for (unsigned int i = 0; i < numLogicalKeys; ++i) {
  ------------------
  |  Branch (1401:42): [True: 0, False: 0]
  ------------------
 1402|      0|                    unsigned int srcBase = i * 3;
 1403|      0|                    unsigned int dstBase = i * 3;
 1404|      0|                    for (unsigned int t = 0; t < 3; ++t) {
  ------------------
  |  Branch (1404:46): [True: 0, False: 0]
  ------------------
 1405|      0|                        anim->mRotationKeys[dstBase + t].mTime = times[i] * kMillisecondsFromSeconds;
 1406|      0|                        anim->mRotationKeys[dstBase + t].mValue.x = values[srcBase + t].w;
 1407|      0|                        anim->mRotationKeys[dstBase + t].mValue.y = values[srcBase + t].x;
 1408|      0|                        anim->mRotationKeys[dstBase + t].mValue.z = values[srcBase + t].y;
 1409|      0|                        anim->mRotationKeys[dstBase + t].mValue.w = values[srcBase + t].z;
 1410|      0|                        anim->mRotationKeys[dstBase + t].mInterpolation = interpType;
 1411|      0|                    }
 1412|      0|                }
 1413|     74|            } else {
 1414|     74|                anim->mNumRotationKeys = numLogicalKeys;
 1415|     74|                anim->mRotationKeys = new aiQuatKey[anim->mNumRotationKeys];
 1416|    909|                for (unsigned int i = 0; i < anim->mNumRotationKeys; ++i) {
  ------------------
  |  Branch (1416:42): [True: 835, False: 74]
  ------------------
 1417|    835|                    anim->mRotationKeys[i].mTime = times[i] * kMillisecondsFromSeconds;
 1418|    835|                    anim->mRotationKeys[i].mValue.x = values[i].w;
 1419|    835|                    anim->mRotationKeys[i].mValue.y = values[i].x;
 1420|    835|                    anim->mRotationKeys[i].mValue.z = values[i].y;
 1421|    835|                    anim->mRotationKeys[i].mValue.w = values[i].z;
 1422|    835|                    anim->mRotationKeys[i].mInterpolation = interpType;
 1423|    835|                }
 1424|     74|            }
 1425|     74|            delete[] times;
 1426|     74|            delete[] values;
 1427|     74|        } else if (node.rotation.isPresent) {
  ------------------
  |  Branch (1427:20): [True: 16, False: 30]
  ------------------
 1428|     16|            anim->mNumRotationKeys = 1;
 1429|     16|            anim->mRotationKeys = new aiQuatKey[anim->mNumRotationKeys];
 1430|     16|            anim->mRotationKeys->mTime = 0.f;
 1431|     16|            anim->mRotationKeys->mValue.x = node.rotation.value[0];
 1432|     16|            anim->mRotationKeys->mValue.y = node.rotation.value[1];
 1433|     16|            anim->mRotationKeys->mValue.z = node.rotation.value[2];
 1434|     16|            anim->mRotationKeys->mValue.w = node.rotation.value[3];
 1435|     16|        }
 1436|       |
 1437|    120|        if (samplers.scale && samplers.scale->input && samplers.scale->output) {
  ------------------
  |  Branch (1437:13): [True: 0, False: 120]
  |  Branch (1437:31): [True: 0, False: 0]
  |  Branch (1437:56): [True: 0, False: 0]
  ------------------
 1438|      0|            float *times = nullptr;
 1439|      0|            samplers.scale->input->ExtractData(times);
 1440|      0|            aiVector3D *values = nullptr;
 1441|      0|            samplers.scale->output->ExtractData(values);
 1442|      0|            const bool isCubic = (samplers.scale->interpolation == Interpolation_CUBICSPLINE);
 1443|      0|            const aiAnimInterpolation interpType = MapInterpolation(samplers.scale->interpolation);
 1444|      0|            const unsigned int numLogicalKeys = static_cast<unsigned int>(samplers.scale->input->count);
 1445|       |
 1446|      0|            if (isCubic) {
  ------------------
  |  Branch (1446:17): [True: 0, False: 0]
  ------------------
 1447|      0|                anim->mNumScalingKeys = numLogicalKeys * 3;
 1448|      0|                anim->mScalingKeys = new aiVectorKey[anim->mNumScalingKeys];
 1449|      0|                for (unsigned int i = 0; i < numLogicalKeys; ++i) {
  ------------------
  |  Branch (1449:42): [True: 0, False: 0]
  ------------------
 1450|      0|                    unsigned int srcBase = i * 3;
 1451|      0|                    unsigned int dstBase = i * 3;
 1452|      0|                    for (unsigned int t = 0; t < 3; ++t) {
  ------------------
  |  Branch (1452:46): [True: 0, False: 0]
  ------------------
 1453|      0|                        anim->mScalingKeys[dstBase + t].mTime = times[i] * kMillisecondsFromSeconds;
 1454|      0|                        anim->mScalingKeys[dstBase + t].mValue = values[srcBase + t];
 1455|      0|                        anim->mScalingKeys[dstBase + t].mInterpolation = interpType;
 1456|      0|                    }
 1457|      0|                }
 1458|      0|            } else {
 1459|      0|                anim->mNumScalingKeys = numLogicalKeys;
 1460|      0|                anim->mScalingKeys = new aiVectorKey[anim->mNumScalingKeys];
 1461|      0|                for (unsigned int i = 0; i < anim->mNumScalingKeys; ++i) {
  ------------------
  |  Branch (1461:42): [True: 0, False: 0]
  ------------------
 1462|      0|                    anim->mScalingKeys[i].mTime = times[i] * kMillisecondsFromSeconds;
 1463|      0|                    anim->mScalingKeys[i].mValue = values[i];
 1464|      0|                    anim->mScalingKeys[i].mInterpolation = interpType;
 1465|      0|                }
 1466|      0|            }
 1467|      0|            delete[] times;
 1468|      0|            delete[] values;
 1469|    120|        } else if (node.scale.isPresent) {
  ------------------
  |  Branch (1469:20): [True: 0, False: 120]
  ------------------
 1470|      0|            anim->mNumScalingKeys = 1;
 1471|      0|            anim->mScalingKeys = new aiVectorKey[anim->mNumScalingKeys];
 1472|      0|            anim->mScalingKeys->mTime = 0.f;
 1473|      0|            anim->mScalingKeys->mValue.x = node.scale.value[0];
 1474|      0|            anim->mScalingKeys->mValue.y = node.scale.value[1];
 1475|      0|            anim->mScalingKeys->mValue.z = node.scale.value[2];
 1476|      0|        }
 1477|       |
 1478|    120|        return anim;
 1479|    120|    } catch (...) {
 1480|     13|        delete anim;
 1481|     13|        throw;
 1482|     13|    }
 1483|    120|}
_Z14GatherSamplersRN5glTF29AnimationE:
 1530|    257|std::unordered_map<unsigned int, AnimationSamplers> GatherSamplers(Animation &anim) {
 1531|    257|    std::unordered_map<unsigned int, AnimationSamplers> samplers;
 1532|    562|    for (unsigned int c = 0; c < anim.channels.size(); ++c) {
  ------------------
  |  Branch (1532:30): [True: 305, False: 257]
  ------------------
 1533|    305|        Animation::Channel &channel = anim.channels[c];
 1534|    305|        if (channel.sampler < 0 || channel.sampler >= static_cast<int>(anim.samplers.size())) {
  ------------------
  |  Branch (1534:13): [True: 135, False: 170]
  |  Branch (1534:36): [True: 38, False: 132]
  ------------------
 1535|    173|            continue;
 1536|    173|        }
 1537|       |
 1538|    132|        auto &animsampler = anim.samplers[channel.sampler];
 1539|       |
 1540|    132|        if (!animsampler.input) {
  ------------------
  |  Branch (1540:13): [True: 5, False: 127]
  ------------------
 1541|      5|            ASSIMP_LOG_WARN("Animation ", anim.name, ": Missing sampler input. Skipping.");
 1542|      5|            continue;
 1543|      5|        }
 1544|       |
 1545|    127|        if (!animsampler.output) {
  ------------------
  |  Branch (1545:13): [True: 1, False: 126]
  ------------------
 1546|      1|            ASSIMP_LOG_WARN("Animation ", anim.name, ": Missing sampler output. Skipping.");
 1547|      1|            continue;
 1548|      1|        }
 1549|       |
 1550|    126|        if (animsampler.input->count > animsampler.output->count) {
  ------------------
  |  Branch (1550:13): [True: 6, False: 120]
  ------------------
 1551|      6|            ASSIMP_LOG_WARN("Animation ", anim.name, ": Number of keyframes in sampler input ", animsampler.input->count,
 1552|      6|                            " exceeds number of keyframes in sampler output ", animsampler.output->count);
 1553|      6|            continue;
 1554|      6|        }
 1555|       |
 1556|    120|        const unsigned int node_index = channel.target.node.GetIndex();
 1557|       |
 1558|    120|        AnimationSamplers &sampler = samplers[node_index];
 1559|    120|        if (channel.target.path == AnimationPath_TRANSLATION) {
  ------------------
  |  Branch (1559:13): [True: 46, False: 74]
  ------------------
 1560|     46|            sampler.translation = &anim.samplers[channel.sampler];
 1561|     74|        } else if (channel.target.path == AnimationPath_ROTATION) {
  ------------------
  |  Branch (1561:20): [True: 74, False: 0]
  ------------------
 1562|     74|            sampler.rotation = &anim.samplers[channel.sampler];
 1563|     74|        } else if (channel.target.path == AnimationPath_SCALE) {
  ------------------
  |  Branch (1563:20): [True: 0, False: 0]
  ------------------
 1564|      0|            sampler.scale = &anim.samplers[channel.sampler];
 1565|      0|        } else if (channel.target.path == AnimationPath_WEIGHTS) {
  ------------------
  |  Branch (1565:20): [True: 0, False: 0]
  ------------------
 1566|      0|            sampler.weight = &anim.samplers[channel.sampler];
 1567|      0|        }
 1568|    120|    }
 1569|       |
 1570|    257|    return samplers;
 1571|    257|}
_ZN6Assimp13glTF2Importer16ImportAnimationsERN5glTF25AssetE:
 1573|  1.71k|void glTF2Importer::ImportAnimations(glTF2::Asset &r) {
 1574|  1.71k|    if (!r.scene) return;
  ------------------
  |  Branch (1574:9): [True: 0, False: 1.71k]
  ------------------
 1575|       |
 1576|  1.71k|    const unsigned numAnimations = r.animations.Size();
 1577|  1.71k|    ASSIMP_LOG_DEBUG("Importing ", numAnimations, " animations");
 1578|  1.71k|    mScene->mNumAnimations = numAnimations;
 1579|  1.71k|    if (mScene->mNumAnimations == 0) {
  ------------------
  |  Branch (1579:9): [True: 1.51k, False: 198]
  ------------------
 1580|  1.51k|        return;
 1581|  1.51k|    }
 1582|       |
 1583|    198|    mScene->mAnimations = new aiAnimation *[numAnimations];
 1584|    198|    std::fill(mScene->mAnimations, mScene->mAnimations + numAnimations, nullptr);
 1585|       |
 1586|    455|    for (unsigned int i = 0; i < numAnimations; ++i) {
  ------------------
  |  Branch (1586:30): [True: 257, False: 198]
  ------------------
 1587|    257|        aiAnimation *ai_anim = mScene->mAnimations[i] = new aiAnimation();
 1588|       |
 1589|    257|        Animation &anim = r.animations[i];
 1590|       |
 1591|    257|        ai_anim->mName = anim.name;
 1592|    257|        ai_anim->mDuration = 0;
 1593|    257|        ai_anim->mTicksPerSecond = 0;
 1594|       |
 1595|    257|        std::unordered_map<unsigned int, AnimationSamplers> samplers = GatherSamplers(anim);
 1596|       |
 1597|    257|        uint32_t numChannels = 0u;
 1598|    257|        uint32_t numMorphMeshChannels = 0u;
 1599|       |
 1600|    257|        for (auto &iter : samplers) {
  ------------------
  |  Branch (1600:25): [True: 120, False: 257]
  ------------------
 1601|    120|            if ((nullptr != iter.second.rotation) || (nullptr != iter.second.scale) || (nullptr != iter.second.translation)) {
  ------------------
  |  Branch (1601:17): [True: 74, False: 46]
  |  Branch (1601:54): [True: 0, False: 46]
  |  Branch (1601:88): [True: 46, False: 0]
  ------------------
 1602|    120|                ++numChannels;
 1603|    120|            }
 1604|    120|            if (nullptr != iter.second.weight) {
  ------------------
  |  Branch (1604:17): [True: 0, False: 120]
  ------------------
 1605|      0|                ++numMorphMeshChannels;
 1606|      0|            }
 1607|    120|        }
 1608|       |
 1609|    257|        ai_anim->mNumChannels = numChannels;
 1610|    257|        if (ai_anim->mNumChannels > 0) {
  ------------------
  |  Branch (1610:13): [True: 120, False: 137]
  ------------------
 1611|    120|            ai_anim->mChannels = new aiNodeAnim *[ai_anim->mNumChannels];
 1612|    120|            std::fill(ai_anim->mChannels, ai_anim->mChannels + ai_anim->mNumChannels, nullptr);
 1613|    120|            int j = 0;
 1614|    120|            for (auto &iter : samplers) {
  ------------------
  |  Branch (1614:29): [True: 120, False: 120]
  ------------------
 1615|    120|                if ((nullptr != iter.second.rotation) || (nullptr != iter.second.scale) || (nullptr != iter.second.translation)) {
  ------------------
  |  Branch (1615:21): [True: 74, False: 46]
  |  Branch (1615:58): [True: 0, False: 46]
  |  Branch (1615:92): [True: 46, False: 0]
  ------------------
 1616|    120|                    ai_anim->mChannels[j] = CreateNodeAnim(r, r.nodes[iter.first], iter.second);
 1617|    120|                    ++j;
 1618|    120|                }
 1619|    120|            }
 1620|    120|        }
 1621|       |
 1622|    257|        ai_anim->mNumMorphMeshChannels = numMorphMeshChannels;
 1623|    257|        if (ai_anim->mNumMorphMeshChannels > 0) {
  ------------------
  |  Branch (1623:13): [True: 0, False: 257]
  ------------------
 1624|      0|            ai_anim->mMorphMeshChannels = new aiMeshMorphAnim *[ai_anim->mNumMorphMeshChannels];
 1625|      0|            std::fill(ai_anim->mMorphMeshChannels, ai_anim->mMorphMeshChannels + ai_anim->mNumMorphMeshChannels, nullptr);
 1626|      0|            int j = 0;
 1627|      0|            for (auto &iter : samplers) {
  ------------------
  |  Branch (1627:29): [True: 0, False: 0]
  ------------------
 1628|      0|                if (nullptr != iter.second.weight) {
  ------------------
  |  Branch (1628:21): [True: 0, False: 0]
  ------------------
 1629|      0|                    ai_anim->mMorphMeshChannels[j] = CreateMeshMorphAnim(r, r.nodes[iter.first], iter.second);
 1630|      0|                    ++j;
 1631|      0|                }
 1632|      0|            }
 1633|      0|        }
 1634|       |
 1635|       |        // Use the latest key-frame for the duration of the animation
 1636|    257|        double maxDuration = 0;
 1637|    257|        unsigned int maxNumberOfKeys = 0;
 1638|    364|        for (unsigned int j = 0; j < ai_anim->mNumChannels; ++j) {
  ------------------
  |  Branch (1638:34): [True: 107, False: 257]
  ------------------
 1639|    107|            auto chan = ai_anim->mChannels[j];
 1640|    107|            if (chan->mNumPositionKeys) {
  ------------------
  |  Branch (1640:17): [True: 48, False: 59]
  ------------------
 1641|     48|                auto lastPosKey = chan->mPositionKeys[chan->mNumPositionKeys - 1];
 1642|     48|                if (lastPosKey.mTime > maxDuration) {
  ------------------
  |  Branch (1642:21): [True: 28, False: 20]
  ------------------
 1643|     28|                    maxDuration = lastPosKey.mTime;
 1644|     28|                }
 1645|     48|                maxNumberOfKeys = std::max(maxNumberOfKeys, chan->mNumPositionKeys);
 1646|     48|            }
 1647|    107|            if (chan->mNumRotationKeys) {
  ------------------
  |  Branch (1647:17): [True: 81, False: 26]
  ------------------
 1648|     81|                auto lastRotKey = chan->mRotationKeys[chan->mNumRotationKeys - 1];
 1649|     81|                if (lastRotKey.mTime > maxDuration) {
  ------------------
  |  Branch (1649:21): [True: 56, False: 25]
  ------------------
 1650|     56|                    maxDuration = lastRotKey.mTime;
 1651|     56|                }
 1652|     81|                maxNumberOfKeys = std::max(maxNumberOfKeys, chan->mNumRotationKeys);
 1653|     81|            }
 1654|    107|            if (chan->mNumScalingKeys) {
  ------------------
  |  Branch (1654:17): [True: 0, False: 107]
  ------------------
 1655|      0|                auto lastScaleKey = chan->mScalingKeys[chan->mNumScalingKeys - 1];
 1656|      0|                if (lastScaleKey.mTime > maxDuration) {
  ------------------
  |  Branch (1656:21): [True: 0, False: 0]
  ------------------
 1657|      0|                    maxDuration = lastScaleKey.mTime;
 1658|      0|                }
 1659|      0|                maxNumberOfKeys = std::max(maxNumberOfKeys, chan->mNumScalingKeys);
 1660|      0|            }
 1661|    107|        }
 1662|       |
 1663|    257|        for (unsigned int j = 0; j < ai_anim->mNumMorphMeshChannels; ++j) {
  ------------------
  |  Branch (1663:34): [True: 0, False: 257]
  ------------------
 1664|      0|            const auto *const chan = ai_anim->mMorphMeshChannels[j];
 1665|       |
 1666|      0|            if (0u != chan->mNumKeys) {
  ------------------
  |  Branch (1666:17): [True: 0, False: 0]
  ------------------
 1667|      0|                const auto &lastKey = chan->mKeys[chan->mNumKeys - 1u];
 1668|      0|                if (lastKey.mTime > maxDuration) {
  ------------------
  |  Branch (1668:21): [True: 0, False: 0]
  ------------------
 1669|      0|                    maxDuration = lastKey.mTime;
 1670|      0|                }
 1671|      0|                maxNumberOfKeys = std::max(maxNumberOfKeys, chan->mNumKeys);
 1672|      0|            }
 1673|      0|        }
 1674|       |
 1675|    257|        ai_anim->mDuration = maxDuration;
 1676|    257|        ai_anim->mTicksPerSecond = 1000.0;
 1677|    257|    }
 1678|    198|}
_ZN6Assimp13glTF2Importer22ImportEmbeddedTexturesERN5glTF25AssetE:
 1691|  2.35k|void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) {
 1692|  2.35k|    mEmbeddedTexIdxs.resize(r.images.Size(), -1);
 1693|  2.35k|    const unsigned int numEmbeddedTexs = countEmbeddedTextures(r);
 1694|  2.35k|    if (numEmbeddedTexs == 0) {
  ------------------
  |  Branch (1694:9): [True: 2.24k, False: 111]
  ------------------
 1695|  2.24k|        return;
 1696|  2.24k|    }
 1697|       |
 1698|  2.35k|    ASSIMP_LOG_DEBUG("Importing ", numEmbeddedTexs, " embedded textures");
 1699|       |
 1700|    111|    mScene->mTextures = new aiTexture *[numEmbeddedTexs];
 1701|    111|    std::fill(mScene->mTextures, mScene->mTextures + numEmbeddedTexs, nullptr);
 1702|       |
 1703|       |    // Add the embedded textures
 1704|    222|    for (size_t i = 0; i < r.images.Size(); ++i) {
  ------------------
  |  Branch (1704:24): [True: 111, False: 111]
  ------------------
 1705|    111|        Image &img = r.images[i];
 1706|    111|        if (!img.HasData()) {
  ------------------
  |  Branch (1706:13): [True: 0, False: 111]
  ------------------
 1707|      0|            continue;
 1708|      0|        }
 1709|       |
 1710|    111|        int idx = mScene->mNumTextures++;
 1711|    111|        mEmbeddedTexIdxs[i] = idx;
 1712|       |
 1713|    111|        aiTexture *tex = mScene->mTextures[idx] = new aiTexture();
 1714|       |
 1715|    111|        size_t length = img.GetDataLength();
 1716|    111|        void *data = img.StealData();
 1717|       |
 1718|    111|        tex->mFilename = img.name;
 1719|    111|        tex->mWidth = static_cast<unsigned int>(length);
 1720|    111|        tex->mHeight = 0;
 1721|    111|        tex->pcData = reinterpret_cast<aiTexel *>(data);
 1722|       |
 1723|    111|        if (!img.mimeType.empty()) {
  ------------------
  |  Branch (1723:13): [True: 111, False: 0]
  ------------------
 1724|    111|            const char *ext = strchr(img.mimeType.c_str(), '/') + 1;
 1725|    111|            if (ext) {
  ------------------
  |  Branch (1725:17): [True: 111, False: 0]
  ------------------
 1726|    111|                if (strncmp(ext, "jpeg", 4) == 0) {
  ------------------
  |  Branch (1726:21): [True: 0, False: 111]
  ------------------
 1727|      0|                    ext = "jpg";
 1728|    111|                } else if (strcmp(ext, "ktx2") == 0) { // basisu: ktx remains
  ------------------
  |  Branch (1728:28): [True: 0, False: 111]
  ------------------
 1729|      0|                    ext = "kx2";
 1730|    111|                } else if (strcmp(ext, "basis") == 0) { // basisu
  ------------------
  |  Branch (1730:28): [True: 0, False: 111]
  ------------------
 1731|      0|                    ext = "bu";
 1732|      0|                } // webp requires no transformation
 1733|       |
 1734|    111|                size_t len = strlen(ext);
 1735|    111|                if (len > 3) len = 3;
  ------------------
  |  Branch (1735:21): [True: 1, False: 110]
  ------------------
 1736|    111|                tex->achFormatHint[3] = '\0';
 1737|    111|                memcpy(tex->achFormatHint, ext, len);
 1738|    111|            }
 1739|    111|        }
 1740|    111|    }
 1741|    111|}
_ZN6Assimp13glTF2Importer20ImportCommonMetadataERN5glTF25AssetE:
 1743|  1.69k|void glTF2Importer::ImportCommonMetadata(glTF2::Asset &a) {
 1744|  1.69k|    ASSIMP_LOG_DEBUG("Importing metadata");
 1745|  1.69k|    ai_assert(mScene->mMetaData == nullptr);
 1746|  1.69k|    const bool hasVersion = !a.asset.version.empty();
 1747|  1.69k|    const bool hasGenerator = !a.asset.generator.empty();
 1748|  1.69k|    const bool hasCopyright = !a.asset.copyright.empty();
 1749|  1.69k|    const bool hasSceneMetadata = a.scene->customExtensions;
 1750|  1.69k|    const bool hasSceneExtras = a.scene->extras.HasExtras();
 1751|  1.69k|    if (hasVersion || hasGenerator || hasCopyright || hasSceneMetadata || hasSceneExtras) {
  ------------------
  |  Branch (1751:9): [True: 1.69k, False: 0]
  |  Branch (1751:23): [True: 0, False: 0]
  |  Branch (1751:39): [True: 0, False: 0]
  |  Branch (1751:55): [True: 0, False: 0]
  |  Branch (1751:75): [True: 0, False: 0]
  ------------------
 1752|  1.69k|        mScene->mMetaData = new aiMetadata;
 1753|  1.69k|        if (hasVersion) {
  ------------------
  |  Branch (1753:13): [True: 1.69k, False: 0]
  ------------------
 1754|  1.69k|            mScene->mMetaData->Add(AI_METADATA_SOURCE_FORMAT_VERSION, aiString(a.asset.version));
 1755|  1.69k|        }
 1756|  1.69k|        if (hasGenerator) {
  ------------------
  |  Branch (1756:13): [True: 845, False: 853]
  ------------------
 1757|    845|            mScene->mMetaData->Add(AI_METADATA_SOURCE_GENERATOR, aiString(a.asset.generator));
 1758|    845|        }
 1759|  1.69k|        if (hasCopyright) {
  ------------------
  |  Branch (1759:13): [True: 78, False: 1.62k]
  ------------------
 1760|     78|            mScene->mMetaData->Add(AI_METADATA_SOURCE_COPYRIGHT, aiString(a.asset.copyright));
 1761|     78|        }
 1762|  1.69k|        if (hasSceneMetadata) {
  ------------------
  |  Branch (1762:13): [True: 0, False: 1.69k]
  ------------------
 1763|      0|            ParseExtensions(mScene->mMetaData, a.scene->customExtensions);
 1764|      0|        }
 1765|  1.69k|        if (hasSceneExtras) {
  ------------------
  |  Branch (1765:13): [True: 0, False: 1.69k]
  ------------------
 1766|      0|            ParseExtras(mScene->mMetaData, a.scene->extras);
 1767|      0|        }
 1768|  1.69k|    }
 1769|  1.69k|}
_ZN6Assimp13glTF2Importer14InternReadFileERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP7aiScenePNS_8IOSystemE:
 1771|  3.53k|void glTF2Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
 1772|  3.53k|    ASSIMP_LOG_DEBUG("Reading GLTF2 file");
 1773|       |
 1774|       |    // clean all member arrays
 1775|  3.53k|    meshOffsets.clear();
 1776|  3.53k|    mVertexRemappingTables.clear();
 1777|  3.53k|    mEmbeddedTexIdxs.clear();
 1778|       |
 1779|  3.53k|    this->mScene = pScene;
 1780|       |
 1781|       |    // read the asset file
 1782|  3.53k|    glTF2::Asset asset(pIOHandler, static_cast<rapidjson::IRemoteSchemaDocumentProvider *>(mSchemaDocumentProvider));
 1783|  3.53k|    asset.Load(pFile,
 1784|  3.53k|               CheckMagicToken(
 1785|  3.53k|                   pIOHandler, pFile, AI_GLB_MAGIC_NUMBER, 1, 0,
  ------------------
  |  |  147|  3.53k|#define AI_GLB_MAGIC_NUMBER "glTF"
  ------------------
 1786|  3.53k|                   static_cast<unsigned int>(strlen(AI_GLB_MAGIC_NUMBER))));
  ------------------
  |  |  147|  3.53k|#define AI_GLB_MAGIC_NUMBER "glTF"
  ------------------
 1787|  3.53k|    if (asset.scene) {
  ------------------
  |  Branch (1787:9): [True: 2.10k, False: 1.43k]
  ------------------
 1788|  2.10k|        pScene->mName = asset.scene->name;
 1789|  2.10k|    }
 1790|       |
 1791|       |    // Copy the data out
 1792|  3.53k|    ImportEmbeddedTextures(asset);
 1793|  3.53k|    ImportMaterials(asset);
 1794|       |
 1795|  3.53k|    ImportMeshes(asset);
 1796|       |
 1797|  3.53k|    ImportCameras(asset);
 1798|  3.53k|    ImportLights(asset);
 1799|       |
 1800|  3.53k|    ImportNodes(asset);
 1801|       |
 1802|  3.53k|    ImportAnimations(asset);
 1803|       |
 1804|  3.53k|    ImportCommonMetadata(asset);
 1805|       |
 1806|  3.53k|    if (pScene->mNumMeshes == 0) {
  ------------------
  |  Branch (1806:9): [True: 381, False: 3.14k]
  ------------------
 1807|       |        pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
 1808|    381|    }
 1809|  3.53k|}
_ZN6Assimp13glTF2Importer15SetupPropertiesEPKNS_8ImporterE:
 1811|  3.53k|void glTF2Importer::SetupProperties(const Importer *pImp) {
 1812|       |    mSchemaDocumentProvider = static_cast<rapidjson::IRemoteSchemaDocumentProvider *>(pImp->GetPropertyPointer(AI_CONFIG_IMPORT_SCHEMA_DOCUMENT_PROVIDER));
 1813|  3.53k|}
glTF2Importer.cpp:_ZL14ImportMaterialRNSt3__16vectorIiNS_9allocatorIiEEEERN5glTF25AssetERNS5_8MaterialE:
  245|  4.58k|static aiMaterial *ImportMaterial(std::vector<int> &embeddedTexIdxs, Asset &r, Material &mat) {
  246|  4.58k|    aiMaterial *aimat = new aiMaterial();
  247|       |
  248|  4.58k|    try {
  249|  4.58k|        if (!mat.name.empty()) {
  ------------------
  |  Branch (249:13): [True: 2.18k, False: 2.40k]
  ------------------
  250|  2.18k|            aiString str(mat.name);
  251|       |
  252|  2.18k|            aimat->AddProperty(&str, AI_MATKEY_NAME);
  253|  2.18k|        }
  254|       |
  255|       |        // Set Assimp DIFFUSE and BASE COLOR to the pbrMetallicRoughness base color and texture for backwards compatibility
  256|       |        // Technically should not load any pbrMetallicRoughness if extensionsRequired contains KHR_materials_pbrSpecularGlossiness
  257|  4.58k|        SetMaterialColorProperty(r, mat.pbrMetallicRoughness.baseColorFactor, aimat, AI_MATKEY_COLOR_DIFFUSE);
  258|  4.58k|        SetMaterialColorProperty(r, mat.pbrMetallicRoughness.baseColorFactor, aimat, AI_MATKEY_BASE_COLOR);
  259|       |
  260|  4.58k|        SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, aiTextureType_DIFFUSE);
  261|  4.58k|        SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, aiTextureType_BASE_COLOR);
  262|       |
  263|       |        // Keep AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE for backwards compatibility
  264|  4.58k|        SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.metallicRoughnessTexture, aimat, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE);
  265|  4.58k|        SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.metallicRoughnessTexture, aimat, aiTextureType_METALNESS);
  266|  4.58k|        SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.metallicRoughnessTexture, aimat, aiTextureType_DIFFUSE_ROUGHNESS);
  267|       |
  268|  4.58k|        aimat->AddProperty(&mat.pbrMetallicRoughness.metallicFactor, 1, AI_MATKEY_METALLIC_FACTOR);
  269|  4.58k|        aimat->AddProperty(&mat.pbrMetallicRoughness.roughnessFactor, 1, AI_MATKEY_ROUGHNESS_FACTOR);
  270|       |
  271|  4.58k|        float roughnessAsShininess = 1 - mat.pbrMetallicRoughness.roughnessFactor;
  272|  4.58k|        roughnessAsShininess *= roughnessAsShininess * 1000;
  273|  4.58k|        aimat->AddProperty(&roughnessAsShininess, 1, AI_MATKEY_SHININESS);
  274|       |
  275|  4.58k|        SetMaterialTextureProperty(embeddedTexIdxs, r, mat.normalTexture, aimat, aiTextureType_NORMALS);
  276|  4.58k|        SetMaterialTextureProperty(embeddedTexIdxs, r, mat.occlusionTexture, aimat, aiTextureType_LIGHTMAP);
  277|  4.58k|        SetMaterialTextureProperty(embeddedTexIdxs, r, mat.emissiveTexture, aimat, aiTextureType_EMISSIVE);
  278|  4.58k|        SetMaterialColorProperty(r, mat.emissiveFactor, aimat, AI_MATKEY_COLOR_EMISSIVE);
  279|       |
  280|  4.58k|        aimat->AddProperty(&mat.doubleSided, 1, AI_MATKEY_TWOSIDED);
  281|  4.58k|        aimat->AddProperty(&mat.pbrMetallicRoughness.baseColorFactor[3], 1, AI_MATKEY_OPACITY);
  282|       |
  283|  4.58k|        aiString alphaMode(mat.alphaMode);
  284|  4.58k|        aimat->AddProperty(&alphaMode, AI_MATKEY_GLTF_ALPHAMODE);
  285|  4.58k|        aimat->AddProperty(&mat.alphaCutoff, 1, AI_MATKEY_GLTF_ALPHACUTOFF);
  286|       |
  287|       |        // KHR_materials_specular
  288|  4.58k|        if (mat.materialSpecular.isPresent) {
  ------------------
  |  Branch (288:13): [True: 0, False: 4.58k]
  ------------------
  289|      0|            MaterialSpecular &specular = mat.materialSpecular.value;
  290|       |            // Default values of zero disables Specular
  291|      0|            if (std::memcmp(specular.specularColorFactor, defaultSpecularColorFactor, sizeof(vec3)) != 0 || specular.specularFactor != 0.0f) {
  ------------------
  |  Branch (291:17): [True: 0, False: 0]
  |  Branch (291:109): [True: 0, False: 0]
  ------------------
  292|      0|                SetMaterialColorProperty(r, specular.specularColorFactor, aimat, AI_MATKEY_COLOR_SPECULAR);
  293|      0|                aimat->AddProperty(&specular.specularFactor, 1, AI_MATKEY_SPECULAR_FACTOR);
  294|      0|                SetMaterialTextureProperty(embeddedTexIdxs, r, specular.specularTexture, aimat, aiTextureType_SPECULAR, 0);
  295|      0|                SetMaterialTextureProperty(embeddedTexIdxs, r, specular.specularColorTexture, aimat, aiTextureType_SPECULAR, 1);
  296|      0|            }
  297|      0|        }
  298|       |        // pbrSpecularGlossiness
  299|  4.58k|        else if (mat.pbrSpecularGlossiness.isPresent) {
  ------------------
  |  Branch (299:18): [True: 0, False: 4.58k]
  ------------------
  300|      0|            PbrSpecularGlossiness &pbrSG = mat.pbrSpecularGlossiness.value;
  301|       |
  302|      0|            SetMaterialColorProperty(r, pbrSG.diffuseFactor, aimat, AI_MATKEY_COLOR_DIFFUSE);
  303|      0|            SetMaterialColorProperty(r, pbrSG.specularFactor, aimat, AI_MATKEY_COLOR_SPECULAR);
  304|       |
  305|      0|            float glossinessAsShininess = pbrSG.glossinessFactor * 1000.0f;
  306|      0|            aimat->AddProperty(&glossinessAsShininess, 1, AI_MATKEY_SHININESS);
  307|      0|            aimat->AddProperty(&pbrSG.glossinessFactor, 1, AI_MATKEY_GLOSSINESS_FACTOR);
  308|       |
  309|      0|            SetMaterialTextureProperty(embeddedTexIdxs, r, pbrSG.diffuseTexture, aimat, aiTextureType_DIFFUSE);
  310|       |
  311|      0|            SetMaterialTextureProperty(embeddedTexIdxs, r, pbrSG.specularGlossinessTexture, aimat, aiTextureType_SPECULAR);
  312|      0|        }
  313|       |
  314|       |        // glTFv2 is either PBR or Unlit
  315|  4.58k|        aiShadingMode shadingMode = aiShadingMode_PBR_BRDF;
  316|  4.58k|        if (mat.unlit) {
  ------------------
  |  Branch (316:13): [True: 0, False: 4.58k]
  ------------------
  317|      0|            aimat->AddProperty(&mat.unlit, 1, "$mat.gltf.unlit", 0, 0); // TODO: Remove this property, it is kept for backwards compatibility with assimp 5.0.1
  318|      0|            shadingMode = aiShadingMode_Unlit;
  319|      0|        }
  320|       |
  321|  4.58k|        aimat->AddProperty(&shadingMode, 1, AI_MATKEY_SHADING_MODEL);
  322|       |
  323|       |        // KHR_materials_sheen
  324|  4.58k|        if (mat.materialSheen.isPresent) {
  ------------------
  |  Branch (324:13): [True: 0, False: 4.58k]
  ------------------
  325|      0|            MaterialSheen &sheen = mat.materialSheen.value;
  326|       |            // Default value {0,0,0} disables Sheen
  327|      0|            if (std::memcmp(sheen.sheenColorFactor, defaultSheenFactor, sizeof(glTFCommon::vec3)) != 0) {
  ------------------
  |  Branch (327:17): [True: 0, False: 0]
  ------------------
  328|      0|                SetMaterialColorProperty(r, sheen.sheenColorFactor, aimat, AI_MATKEY_SHEEN_COLOR_FACTOR);
  329|      0|                aimat->AddProperty(&sheen.sheenRoughnessFactor, 1, AI_MATKEY_SHEEN_ROUGHNESS_FACTOR);
  330|      0|                SetMaterialTextureProperty(embeddedTexIdxs, r, sheen.sheenColorTexture, aimat, AI_MATKEY_SHEEN_COLOR_TEXTURE);
  331|      0|                SetMaterialTextureProperty(embeddedTexIdxs, r, sheen.sheenRoughnessTexture, aimat, AI_MATKEY_SHEEN_ROUGHNESS_TEXTURE);
  332|      0|            }
  333|      0|        }
  334|       |
  335|       |        // KHR_materials_clearcoat
  336|  4.58k|        if (mat.materialClearcoat.isPresent) {
  ------------------
  |  Branch (336:13): [True: 0, False: 4.58k]
  ------------------
  337|      0|            MaterialClearcoat &clearcoat = mat.materialClearcoat.value;
  338|       |            // Default value 0.0 disables clearcoat
  339|      0|            if (clearcoat.clearcoatFactor != 0.0f) {
  ------------------
  |  Branch (339:17): [True: 0, False: 0]
  ------------------
  340|      0|                aimat->AddProperty(&clearcoat.clearcoatFactor, 1, AI_MATKEY_CLEARCOAT_FACTOR);
  341|      0|                aimat->AddProperty(&clearcoat.clearcoatRoughnessFactor, 1, AI_MATKEY_CLEARCOAT_ROUGHNESS_FACTOR);
  342|      0|                SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatTexture, aimat, AI_MATKEY_CLEARCOAT_TEXTURE);
  343|      0|                SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatRoughnessTexture, aimat, AI_MATKEY_CLEARCOAT_ROUGHNESS_TEXTURE);
  344|      0|                SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatNormalTexture, aimat, AI_MATKEY_CLEARCOAT_NORMAL_TEXTURE);
  345|      0|            }
  346|      0|        }
  347|       |
  348|       |        // KHR_materials_transmission
  349|  4.58k|        if (mat.materialTransmission.isPresent) {
  ------------------
  |  Branch (349:13): [True: 0, False: 4.58k]
  ------------------
  350|      0|            MaterialTransmission &transmission = mat.materialTransmission.value;
  351|       |
  352|      0|            aimat->AddProperty(&transmission.transmissionFactor, 1, AI_MATKEY_TRANSMISSION_FACTOR);
  353|      0|            SetMaterialTextureProperty(embeddedTexIdxs, r, transmission.transmissionTexture, aimat, AI_MATKEY_TRANSMISSION_TEXTURE);
  354|      0|        }
  355|       |
  356|       |        // KHR_materials_volume
  357|  4.58k|        if (mat.materialVolume.isPresent) {
  ------------------
  |  Branch (357:13): [True: 0, False: 4.58k]
  ------------------
  358|      0|            MaterialVolume &volume = mat.materialVolume.value;
  359|       |
  360|      0|            aimat->AddProperty(&volume.thicknessFactor, 1, AI_MATKEY_VOLUME_THICKNESS_FACTOR);
  361|      0|            SetMaterialTextureProperty(embeddedTexIdxs, r, volume.thicknessTexture, aimat, AI_MATKEY_VOLUME_THICKNESS_TEXTURE);
  362|      0|            aimat->AddProperty(&volume.attenuationDistance, 1, AI_MATKEY_VOLUME_ATTENUATION_DISTANCE);
  363|      0|            SetMaterialColorProperty(r, volume.attenuationColor, aimat, AI_MATKEY_VOLUME_ATTENUATION_COLOR);
  364|      0|        }
  365|       |
  366|       |        // KHR_materials_ior
  367|  4.58k|        if (mat.materialIOR.isPresent) {
  ------------------
  |  Branch (367:13): [True: 0, False: 4.58k]
  ------------------
  368|      0|            MaterialIOR &ior = mat.materialIOR.value;
  369|       |
  370|      0|            aimat->AddProperty(&ior.ior, 1, AI_MATKEY_REFRACTI);
  371|      0|        }
  372|       |
  373|       |        // KHR_materials_emissive_strength
  374|  4.58k|        if (mat.materialEmissiveStrength.isPresent) {
  ------------------
  |  Branch (374:13): [True: 0, False: 4.58k]
  ------------------
  375|      0|            const MaterialEmissiveStrength &emissiveStrength = mat.materialEmissiveStrength.value;
  376|       |
  377|      0|            aimat->AddProperty(&emissiveStrength.emissiveStrength, 1, AI_MATKEY_EMISSIVE_INTENSITY);
  378|      0|        }
  379|       |
  380|       |        // KHR_materials_anisotropy
  381|  4.58k|        if (mat.materialAnisotropy.isPresent) {
  ------------------
  |  Branch (381:13): [True: 0, False: 4.58k]
  ------------------
  382|      0|            const MaterialAnisotropy &anisotropy = mat.materialAnisotropy.value;
  383|       |
  384|      0|            aimat->AddProperty(&anisotropy.anisotropyStrength, 1, AI_MATKEY_ANISOTROPY_FACTOR);
  385|      0|            aimat->AddProperty(&anisotropy.anisotropyRotation, 1, AI_MATKEY_ANISOTROPY_ROTATION);
  386|       |
  387|      0|            SetMaterialTextureProperty(embeddedTexIdxs, r, anisotropy.anisotropyTexture, aimat, AI_MATKEY_ANISOTROPY_TEXTURE);
  388|      0|        }
  389|       |
  390|  4.58k|        return aimat;
  391|  4.58k|    } catch (...) {
  392|      0|        delete aimat;
  393|      0|        throw;
  394|      0|    }
  395|  4.58k|}
glTF2Importer.cpp:_ZL24SetMaterialColorPropertyRN5glTF25AssetERA4_fP10aiMaterialPKcjj:
  144|  9.16k|        const char *pKey, unsigned int type, unsigned int idx) {
  145|  9.16k|    aiColor4D col;
  146|  9.16k|    CopyValue(prop, col);
  147|  9.16k|    mat->AddProperty(&col, 1, pKey, type, idx);
  148|  9.16k|}
glTF2Importer.cpp:_ZL26SetMaterialTexturePropertyRNSt3__16vectorIiNS_9allocatorIiEEEERN5glTF25AssetENS5_11TextureInfoEP10aiMaterial13aiTextureTypej:
  159|  36.6k|        unsigned int texSlot = 0) {
  160|  36.6k|    if (prop.texture && prop.texture->source) {
  ------------------
  |  Branch (160:9): [True: 424, False: 36.2k]
  |  Branch (160:25): [True: 390, False: 34]
  ------------------
  161|    390|        aiString uri(prop.texture->source->uri);
  162|       |
  163|    390|        int texIdx = embeddedTexIdxs[prop.texture->source.GetIndex()];
  164|    390|        if (texIdx != -1) { // embedded
  ------------------
  |  Branch (164:13): [True: 346, False: 44]
  ------------------
  165|       |            // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture)
  166|    346|            uri.data[0] = '*';
  167|    346|            uri.length = 1 + ASSIMP_itoa10(uri.data + 1, AI_MAXLEN - 1, texIdx);
  168|    346|        }
  169|       |
  170|    390|        mat->AddProperty(&uri, AI_MATKEY_TEXTURE(texType, texSlot));
  171|    390|        const int uvIndex = static_cast<int>(prop.texCoord);
  172|    390|        mat->AddProperty(&uvIndex, 1, AI_MATKEY_UVWSRC(texType, texSlot));
  173|       |
  174|    390|        if (prop.textureTransformSupported) {
  ------------------
  |  Branch (174:13): [True: 0, False: 390]
  ------------------
  175|      0|            aiUVTransform transform;
  176|      0|            transform.mScaling.x = prop.TextureTransformExt_t.scale[0];
  177|      0|            transform.mScaling.y = prop.TextureTransformExt_t.scale[1];
  178|      0|            transform.mRotation = -prop.TextureTransformExt_t.rotation; // must be negated
  179|       |
  180|       |            // A change of coordinates is required to map glTF UV transformations into the space used by
  181|       |            // Assimp. In glTF all UV origins are at 0,1 (top left of texture) in Assimp space. In Assimp
  182|       |            // rotation occurs around the image center (0.5,0.5) where as in glTF rotation is around the
  183|       |            // texture origin. All three can be corrected for solely by a change of the translation since
  184|       |            // the transformations available are shape preserving. Note the importer already flips the V
  185|       |            // coordinate of the actual meshes during import.
  186|      0|            const ai_real rcos(cos(-transform.mRotation));
  187|      0|            const ai_real rsin(sin(-transform.mRotation));
  188|      0|            transform.mTranslation.x = (static_cast<ai_real>(0.5) * transform.mScaling.x) * (-rcos + rsin + 1) + prop.TextureTransformExt_t.offset[0];
  189|      0|            transform.mTranslation.y = ((static_cast<ai_real>(0.5) * transform.mScaling.y) * (rsin + rcos - 1)) + 1 - transform.mScaling.y - prop.TextureTransformExt_t.offset[1];
  190|       |
  191|      0|            mat->AddProperty(&transform, 1, _AI_MATKEY_UVTRANSFORM_BASE, texType, texSlot);
  192|      0|        }
  193|       |
  194|    390|        if (prop.texture->sampler) {
  ------------------
  |  Branch (194:13): [True: 320, False: 70]
  ------------------
  195|    320|            Ref<Sampler> sampler = prop.texture->sampler;
  196|       |
  197|    320|            aiString name(sampler->name);
  198|    320|            aiString id(sampler->id);
  199|       |
  200|    320|            mat->AddProperty(&name, AI_MATKEY_GLTF_MAPPINGNAME(texType, texSlot));
  201|    320|            mat->AddProperty(&id, AI_MATKEY_GLTF_MAPPINGID(texType, texSlot));
  202|       |
  203|    320|            aiTextureMapMode wrapS = ConvertWrappingMode(sampler->wrapS);
  204|    320|            aiTextureMapMode wrapT = ConvertWrappingMode(sampler->wrapT);
  205|    320|            mat->AddProperty(&wrapS, 1, AI_MATKEY_MAPPINGMODE_U(texType, texSlot));
  206|    320|            mat->AddProperty(&wrapT, 1, AI_MATKEY_MAPPINGMODE_V(texType, texSlot));
  207|       |
  208|    320|            if (sampler->magFilter != SamplerMagFilter::UNSET) {
  ------------------
  |  Branch (208:17): [True: 126, False: 194]
  ------------------
  209|    126|                mat->AddProperty(&sampler->magFilter, 1, AI_MATKEY_GLTF_MAPPINGFILTER_MAG(texType, texSlot));
  210|    126|            }
  211|       |
  212|    320|            if (sampler->minFilter != SamplerMinFilter::UNSET) {
  ------------------
  |  Branch (212:17): [True: 114, False: 206]
  ------------------
  213|    114|                mat->AddProperty(&sampler->minFilter, 1, AI_MATKEY_GLTF_MAPPINGFILTER_MIN(texType, texSlot));
  214|    114|            }
  215|    320|        } else {
  216|       |            // Use glTFv2 default sampler
  217|     70|            const aiTextureMapMode default_wrap = aiTextureMapMode_Wrap;
  218|     70|            mat->AddProperty(&default_wrap, 1, AI_MATKEY_MAPPINGMODE_U(texType, texSlot));
  219|       |            mat->AddProperty(&default_wrap, 1, AI_MATKEY_MAPPINGMODE_V(texType, texSlot));
  220|     70|        }
  221|    390|    }
  222|  36.6k|}
glTF2Importer.cpp:_ZL19ConvertWrappingModeN5glTF211SamplerWrapE:
  127|    640|static aiTextureMapMode ConvertWrappingMode(SamplerWrap gltfWrapMode) {
  128|    640|    switch (gltfWrapMode) {
  129|      0|        case SamplerWrap::Mirrored_Repeat:
  ------------------
  |  Branch (129:9): [True: 0, False: 640]
  ------------------
  130|      0|            return aiTextureMapMode_Mirror;
  131|       |
  132|      0|        case SamplerWrap::Clamp_To_Edge:
  ------------------
  |  Branch (132:9): [True: 0, False: 640]
  ------------------
  133|      0|            return aiTextureMapMode_Clamp;
  134|       |
  135|      0|        case SamplerWrap::UNSET:
  ------------------
  |  Branch (135:9): [True: 0, False: 640]
  ------------------
  136|    622|        case SamplerWrap::Repeat:
  ------------------
  |  Branch (136:9): [True: 622, False: 18]
  ------------------
  137|    640|        default:
  ------------------
  |  Branch (137:9): [True: 18, False: 622]
  ------------------
  138|    640|            break;
  139|    640|    }
  140|    640|    return aiTextureMapMode_Wrap;
  141|    640|}
glTF2Importer.cpp:_ZL26SetMaterialTexturePropertyRNSt3__16vectorIiNS_9allocatorIiEEEERN5glTF25AssetERNS5_17NormalTextureInfoEP10aiMaterial13aiTextureTypej:
  226|  4.58k|        unsigned int texSlot = 0) {
  227|  4.58k|    SetMaterialTextureProperty(embeddedTexIdxs, r, static_cast<TextureInfo>(prop), mat, texType, texSlot);
  228|       |
  229|  4.58k|    if (prop.texture && prop.texture->source) {
  ------------------
  |  Branch (229:9): [True: 0, False: 4.58k]
  |  Branch (229:25): [True: 0, False: 0]
  ------------------
  230|       |        mat->AddProperty(&prop.scale, 1, AI_MATKEY_GLTF_TEXTURE_SCALE(texType, texSlot));
  231|      0|    }
  232|  4.58k|}
glTF2Importer.cpp:_ZL26SetMaterialTexturePropertyRNSt3__16vectorIiNS_9allocatorIiEEEERN5glTF25AssetERNS5_20OcclusionTextureInfoEP10aiMaterial13aiTextureTypej:
  236|  4.58k|        unsigned int texSlot = 0) {
  237|  4.58k|    SetMaterialTextureProperty(embeddedTexIdxs, r, static_cast<TextureInfo>(prop), mat, texType, texSlot);
  238|       |
  239|  4.58k|    if (prop.texture && prop.texture->source) {
  ------------------
  |  Branch (239:9): [True: 0, False: 4.58k]
  |  Branch (239:25): [True: 0, False: 0]
  ------------------
  240|       |        std::string textureStrengthKey = std::string(_AI_MATKEY_TEXTURE_BASE) + "." + "strength";
  241|      0|        mat->AddProperty(&prop.strength, 1, textureStrengthKey.c_str(), texType, texSlot);
  242|      0|    }
  243|  4.58k|}
glTF2Importer.cpp:_ZL24SetMaterialColorPropertyRN5glTF25AssetERA3_fP10aiMaterialPKcjj:
  151|  4.58k|        const char *pKey, unsigned int type, unsigned int idx) {
  152|  4.58k|    aiColor4D col;
  153|  4.58k|    CopyValue(prop, col);
  154|  4.58k|    mat->AddProperty(&col, 1, pKey, type, idx);
  155|  4.58k|}
glTF2Importer.cpp:_ZL18SetFaceAndAdvance1RP6aiFacejj:
  412|  1.27k|static inline void SetFaceAndAdvance1(aiFace *&face, unsigned int numVertices, unsigned int a) {
  413|  1.27k|    if (a >= numVertices) {
  ------------------
  |  Branch (413:9): [True: 633, False: 644]
  ------------------
  414|    633|        return;
  415|    633|    }
  416|    644|    face->mNumIndices = 1;
  417|    644|    face->mIndices = new unsigned int[1];
  418|    644|    face->mIndices[0] = a;
  419|    644|    ++face;
  420|    644|}
glTF2Importer.cpp:_ZL18SetFaceAndAdvance2RP6aiFacejjj:
  423|  9.42k|        unsigned int a, unsigned int b) {
  424|  9.42k|    if ((a >= numVertices) || (b >= numVertices)) {
  ------------------
  |  Branch (424:9): [True: 2.51k, False: 6.90k]
  |  Branch (424:31): [True: 509, False: 6.39k]
  ------------------
  425|  3.02k|        return;
  426|  3.02k|    }
  427|  6.39k|    face->mNumIndices = 2;
  428|  6.39k|    face->mIndices = new unsigned int[2];
  429|  6.39k|    face->mIndices[0] = a;
  430|  6.39k|    face->mIndices[1] = b;
  431|  6.39k|    ++face;
  432|  6.39k|}
glTF2Importer.cpp:_ZL18SetFaceAndAdvance3RP6aiFacejjjj:
  435|  25.0k|        unsigned int b, unsigned int c) {
  436|  25.0k|    if ((a >= numVertices) || (b >= numVertices) || (c >= numVertices)) {
  ------------------
  |  Branch (436:9): [True: 4.61k, False: 20.4k]
  |  Branch (436:31): [True: 1.97k, False: 18.5k]
  |  Branch (436:53): [True: 941, False: 17.5k]
  ------------------
  437|  7.52k|        return;
  438|  7.52k|    }
  439|  17.5k|    face->mNumIndices = 3;
  440|  17.5k|    face->mIndices = new unsigned int[3];
  441|  17.5k|    face->mIndices[0] = a;
  442|  17.5k|    face->mIndices[1] = b;
  443|  17.5k|    face->mIndices[2] = c;
  444|  17.5k|    ++face;
  445|  17.5k|}
glTF2Importer.cpp:_ZL22CheckValidFacesIndicesP6aiFacejj:
  448|  1.59k|static inline bool CheckValidFacesIndices(aiFace *faces, unsigned nFaces, unsigned nVerts) {
  449|  26.2k|    for (unsigned i = 0; i < nFaces; ++i) {
  ------------------
  |  Branch (449:26): [True: 24.6k, False: 1.59k]
  ------------------
  450|  90.7k|        for (unsigned j = 0; j < faces[i].mNumIndices; ++j) {
  ------------------
  |  Branch (450:30): [True: 66.1k, False: 24.6k]
  ------------------
  451|  66.1k|            unsigned idx = faces[i].mIndices[j];
  452|  66.1k|            if (idx >= nVerts) {
  ------------------
  |  Branch (452:17): [True: 0, False: 66.1k]
  ------------------
  453|      0|                return false;
  454|      0|            }
  455|  66.1k|        }
  456|  24.6k|    }
  457|  1.59k|    return true;
  458|  1.59k|}
glTF2Importer.cpp:_ZL11GetNodeNameRKN5glTF24NodeE:
 1107|  7.46k|static std::string GetNodeName(const Node &node) {
 1108|  7.46k|    return node.name.empty() ? node.id : node.name;
  ------------------
  |  Branch (1108:12): [True: 0, False: 7.46k]
  ------------------
 1109|  7.46k|}
glTF2Importer.cpp:_ZL16GetNodeTransformR12aiMatrix4x4tIfERKN5glTF24NodeE:
 1006|  9.16k|static void GetNodeTransform(aiMatrix4x4 &matrix, const glTF2::Node &node) {
 1007|  9.16k|    if (node.matrix.isPresent) {
  ------------------
  |  Branch (1007:9): [True: 6.26k, False: 2.90k]
  ------------------
 1008|  6.26k|        CopyValue(node.matrix.value, matrix);
 1009|  6.26k|        return;
 1010|  6.26k|    }
 1011|       |
 1012|  2.90k|    if (node.translation.isPresent) {
  ------------------
  |  Branch (1012:9): [True: 367, False: 2.53k]
  ------------------
 1013|    367|        aiVector3D trans;
 1014|    367|        CopyValue(node.translation.value, trans);
 1015|    367|        aiMatrix4x4 t;
 1016|    367|        aiMatrix4x4::Translation(trans, t);
 1017|    367|        matrix = matrix * t;
 1018|    367|    }
 1019|       |
 1020|  2.90k|    if (node.rotation.isPresent) {
  ------------------
  |  Branch (1020:9): [True: 304, False: 2.60k]
  ------------------
 1021|    304|        aiQuaternion rot;
 1022|    304|        CopyValue(node.rotation.value, rot);
 1023|    304|        matrix = matrix * aiMatrix4x4(rot.GetMatrix());
 1024|    304|    }
 1025|       |
 1026|  2.90k|    if (node.scale.isPresent) {
  ------------------
  |  Branch (1026:9): [True: 4, False: 2.90k]
  ------------------
 1027|      4|        aiVector3D scal(1.f);
 1028|      4|        CopyValue(node.scale.value, scal);
 1029|      4|        aiMatrix4x4 s;
 1030|      4|        aiMatrix4x4::Scaling(scal, s);
 1031|      4|        matrix = matrix * s;
 1032|      4|    }
 1033|  2.90k|}
glTF2Importer.cpp:_ZL24BuildVertexWeightMappingRN5glTF24Mesh9PrimitiveERNSt3__16vectorINS4_I14aiVertexWeightNS3_9allocatorIS5_EEEENS6_IS8_EEEEPNS4_IjNS6_IjEEEE:
 1035|    341|static void BuildVertexWeightMapping(Mesh::Primitive &primitive, std::vector<std::vector<aiVertexWeight>> &map, std::vector<unsigned int>* vertexRemappingTablePtr) {
 1036|       |
 1037|    341|    Mesh::Primitive::Attributes &attr = primitive.attributes;
 1038|    341|    if (attr.weight.empty() || attr.joint.empty()) {
  ------------------
  |  Branch (1038:9): [True: 11, False: 330]
  |  Branch (1038:32): [True: 16, False: 314]
  ------------------
 1039|     27|        return;
 1040|     27|    }
 1041|    314|    if (attr.weight[0]->count != attr.joint[0]->count) {
  ------------------
  |  Branch (1041:9): [True: 30, False: 284]
  ------------------
 1042|     30|        return;
 1043|     30|    }
 1044|       |
 1045|    284|    size_t num_vertices = 0;
 1046|       |
 1047|    284|    struct Weights {
 1048|    284|        float values[4];
 1049|    284|    };
 1050|    284|    Weights **weights = new Weights*[attr.weight.size()];
 1051|    935|    for (size_t w = 0; w < attr.weight.size(); ++w) {
  ------------------
  |  Branch (1051:24): [True: 651, False: 284]
  ------------------
 1052|    651|        num_vertices = attr.weight[w]->ExtractData(weights[w], vertexRemappingTablePtr);
 1053|    651|    }
 1054|       |
 1055|    284|    struct Indices8 {
 1056|    284|        uint8_t values[4];
 1057|    284|    };
 1058|    284|    struct Indices16 {
 1059|    284|        uint16_t values[4];
 1060|    284|    };
 1061|    284|    Indices8 **indices8 = nullptr;
 1062|    284|    Indices16 **indices16 = nullptr;
 1063|    284|    if (attr.joint[0]->GetElementSize() == 4) {
  ------------------
  |  Branch (1063:9): [True: 43, False: 241]
  ------------------
 1064|     43|        indices8 = new Indices8*[attr.joint.size()];
 1065|    112|        for (size_t j = 0; j < attr.joint.size(); ++j) {
  ------------------
  |  Branch (1065:28): [True: 69, False: 43]
  ------------------
 1066|     69|            attr.joint[j]->ExtractData(indices8[j], vertexRemappingTablePtr);
 1067|     69|        }
 1068|    241|    } else {
 1069|    241|        indices16 = new Indices16 *[attr.joint.size()];
 1070|    797|        for (size_t j = 0; j < attr.joint.size(); ++j) {
  ------------------
  |  Branch (1070:28): [True: 556, False: 241]
  ------------------
 1071|    556|            attr.joint[j]->ExtractData(indices16[j], vertexRemappingTablePtr);
 1072|    556|        }
 1073|    241|    }
 1074|       |
 1075|       |    // No indices are an invalid usecase
 1076|    284|    if (nullptr == indices8 && nullptr == indices16) {
  ------------------
  |  Branch (1076:9): [True: 215, False: 69]
  |  Branch (1076:32): [True: 0, False: 215]
  ------------------
 1077|       |        // Something went completely wrong!
 1078|      0|        ai_assert(false);
 1079|      0|        return;
 1080|      0|    }
 1081|       |
 1082|    843|    for (size_t w = 0; w < attr.weight.size(); ++w) {
  ------------------
  |  Branch (1082:24): [True: 559, False: 284]
  ------------------
 1083|  3.01k|        for (size_t i = 0; i < num_vertices; ++i) {
  ------------------
  |  Branch (1083:28): [True: 2.45k, False: 559]
  ------------------
 1084|  12.2k|            for (int j = 0; j < 4; ++j) {
  ------------------
  |  Branch (1084:29): [True: 9.82k, False: 2.45k]
  ------------------
 1085|  9.82k|                const unsigned int bone = (indices8 != nullptr) ? indices8[w][i].values[j] : indices16[w][i].values[j];
  ------------------
  |  Branch (1085:43): [True: 1.13k, False: 8.68k]
  ------------------
 1086|  9.82k|                const float weight = weights[w][i].values[j];
 1087|  9.82k|                if (weight > 0 && bone < map.size()) {
  ------------------
  |  Branch (1087:21): [True: 5.63k, False: 4.18k]
  |  Branch (1087:35): [True: 3.84k, False: 1.78k]
  ------------------
 1088|  3.84k|                    map[bone].reserve(8);
 1089|  3.84k|                    map[bone].emplace_back(static_cast<unsigned int>(i), weight);
 1090|  3.84k|                }
 1091|  9.82k|            }
 1092|  2.45k|        }
 1093|    559|    }
 1094|       |
 1095|    843|    for (size_t w = 0; w < attr.weight.size(); ++w) {
  ------------------
  |  Branch (1095:24): [True: 559, False: 284]
  ------------------
 1096|    559|        delete[] weights[w];
 1097|    559|        if(indices8)
  ------------------
  |  Branch (1097:12): [True: 42, False: 517]
  ------------------
 1098|     42|            delete[] indices8[w];
 1099|    559|        if (indices16)
  ------------------
  |  Branch (1099:13): [True: 517, False: 42]
  ------------------
 1100|    517|            delete[] indices16[w];
 1101|    559|    }
 1102|    284|    delete[] weights;
 1103|    284|    delete[] indices8;
 1104|    284|    delete[] indices16;
 1105|    284|}
glTF2Importer.cpp:_ZL16MapInterpolationN5glTF213InterpolationE:
 1323|    107|static aiAnimInterpolation MapInterpolation(Interpolation interp) {
 1324|    107|    switch (interp) {
 1325|      0|        case Interpolation_STEP: return aiAnimInterpolation_Step;
  ------------------
  |  Branch (1325:9): [True: 0, False: 107]
  ------------------
 1326|      0|        case Interpolation_CUBICSPLINE: return aiAnimInterpolation_Cubic_Spline;
  ------------------
  |  Branch (1326:9): [True: 0, False: 107]
  ------------------
 1327|    107|        default: return aiAnimInterpolation_Linear;
  ------------------
  |  Branch (1327:9): [True: 107, False: 0]
  ------------------
 1328|    107|    }
 1329|    107|}
glTF2Importer.cpp:_ZL21countEmbeddedTexturesRN5glTF25AssetE:
 1680|  2.35k|static unsigned int countEmbeddedTextures(glTF2::Asset &r) {
 1681|  2.35k|    unsigned int numEmbeddedTexs = 0;
 1682|  2.48k|    for (size_t i = 0; i < r.images.Size(); ++i) {
  ------------------
  |  Branch (1682:24): [True: 130, False: 2.35k]
  ------------------
 1683|    130|        if (r.images[i].HasData()) {
  ------------------
  |  Branch (1683:13): [True: 111, False: 19]
  ------------------
 1684|    111|            numEmbeddedTexs += 1;
 1685|    111|        }
 1686|    130|    }
 1687|       |
 1688|  2.35k|    return numEmbeddedTexs;
 1689|  2.35k|}
_Z22GetVertexColorsForTypeIhEP9aiColor4tIfEN10glTFCommon3RefIN5glTF28AccessorEEEPNSt3__16vectorIjNS8_9allocatorIjEEEE:
  462|     11|aiColor4D *GetVertexColorsForType(Ref<Accessor> input, std::vector<unsigned int> *vertexRemappingTable) {
  463|     11|    constexpr float max = std::numeric_limits<T>::max();
  464|     11|    aiColor4t<T> *colors;
  465|     11|    size_t count = input->ExtractData(colors, vertexRemappingTable);
  466|     11|    auto output = new aiColor4D[count];
  467|     51|    for (size_t i = 0; i < count; i++) {
  ------------------
  |  Branch (467:24): [True: 40, False: 11]
  ------------------
  468|     40|        output[i] = aiColor4D(
  469|     40|                colors[i].r / max, colors[i].g / max,
  470|     40|                colors[i].b / max, colors[i].a / max);
  471|     40|    }
  472|     11|    delete[] colors;
  473|     11|    return output;
  474|     11|}
_Z22GetVertexColorsForTypeItEP9aiColor4tIfEN10glTFCommon3RefIN5glTF28AccessorEEEPNSt3__16vectorIjNS8_9allocatorIjEEEE:
  462|     14|aiColor4D *GetVertexColorsForType(Ref<Accessor> input, std::vector<unsigned int> *vertexRemappingTable) {
  463|     14|    constexpr float max = std::numeric_limits<T>::max();
  464|     14|    aiColor4t<T> *colors;
  465|     14|    size_t count = input->ExtractData(colors, vertexRemappingTable);
  466|     14|    auto output = new aiColor4D[count];
  467|     56|    for (size_t i = 0; i < count; i++) {
  ------------------
  |  Branch (467:24): [True: 42, False: 14]
  ------------------
  468|     42|        output[i] = aiColor4D(
  469|     42|                colors[i].r / max, colors[i].g / max,
  470|     42|                colors[i].b / max, colors[i].a / max);
  471|     42|    }
  472|     14|    delete[] colors;
  473|     14|    return output;
  474|     14|}
_ZN17AnimationSamplersC2Ev:
 1306|    120|            translation(nullptr),
 1307|    120|            rotation(nullptr),
 1308|    120|            scale(nullptr),
 1309|    120|            weight(nullptr) {
 1310|       |        // empty
 1311|    120|    }

_ZN6Assimp13glTF2ImporterD2Ev:
   62|  5.13k|    ~glTF2Importer() override = default;

_ZN10glTFCommon4Util12ParseDataURIEPKcmRNS0_7DataURIE:
   47|  1.75k|bool ParseDataURI(const char *const_uri, size_t uriLen, DataURI &out) {
   48|  1.75k|    if (nullptr == const_uri) {
  ------------------
  |  Branch (48:9): [True: 0, False: 1.75k]
  ------------------
   49|      0|        return false;
   50|      0|    }
   51|       |
   52|  1.75k|    if (const_uri[0] != 0x10) { // we already parsed this uri?
  ------------------
  |  Branch (52:9): [True: 1.75k, False: 0]
  ------------------
   53|  1.75k|        if (strncmp(const_uri, "data:", 5) != 0) // not a data uri?
  ------------------
  |  Branch (53:13): [True: 503, False: 1.25k]
  ------------------
   54|    503|            return false;
   55|  1.75k|    }
   56|       |
   57|       |    // set defaults
   58|  1.25k|    out.mediaType = "text/plain";
   59|  1.25k|    out.charset = "US-ASCII";
   60|  1.25k|    out.base64 = false;
   61|       |
   62|  1.25k|    char *uri = const_cast<char *>(const_uri);
   63|  1.25k|    if (uri[0] != 0x10) {
  ------------------
  |  Branch (63:9): [True: 1.25k, False: 0]
  ------------------
   64|  1.25k|        uri[0] = 0x10;
   65|  1.25k|        uri[1] = uri[2] = uri[3] = uri[4] = 0;
   66|       |
   67|  1.25k|        size_t i = 5, j;
   68|  1.25k|        if (uri[i] != ';' && uri[i] != ',') { // has media type?
  ------------------
  |  Branch (68:13): [True: 1.25k, False: 2]
  |  Branch (68:30): [True: 1.24k, False: 1]
  ------------------
   69|  1.24k|            uri[1] = char(i);
   70|  57.7k|            for (;i < uriLen && uri[i] != ';' && uri[i] != ','; ++i) {
  ------------------
  |  Branch (70:19): [True: 57.7k, False: 12]
  |  Branch (70:33): [True: 56.4k, False: 1.23k]
  |  Branch (70:50): [True: 56.4k, False: 4]
  ------------------
   71|       |                // nothing to do!
   72|  56.4k|            }
   73|  1.24k|        }
   74|  7.04k|        while (i < uriLen && uri[i] == ';') {
  ------------------
  |  Branch (74:16): [True: 7.00k, False: 39]
  |  Branch (74:30): [True: 5.79k, False: 1.21k]
  ------------------
   75|  5.79k|            uri[i++] = '\0';
   76|   554k|            for (j = i; i < uriLen && uri[i] != ';' && uri[i] != ','; ++i) {
  ------------------
  |  Branch (76:25): [True: 554k, False: 27]
  |  Branch (76:39): [True: 549k, False: 4.56k]
  |  Branch (76:56): [True: 548k, False: 1.20k]
  ------------------
   77|       |                // nothing to do!
   78|   548k|            }
   79|       |
   80|  5.79k|            if (strncmp(uri + j, "charset=", 8) == 0) {
  ------------------
  |  Branch (80:17): [True: 7, False: 5.78k]
  ------------------
   81|      7|                uri[2] = char(j + 8);
   82|  5.78k|            } else if (strncmp(uri + j, "base64", 6) == 0) {
  ------------------
  |  Branch (82:24): [True: 5.15k, False: 631]
  ------------------
   83|  5.15k|                uri[3] = char(j);
   84|  5.15k|            }
   85|  5.79k|        }
   86|  1.25k|        if (i < uriLen) {
  ------------------
  |  Branch (86:13): [True: 1.21k, False: 39]
  ------------------
   87|  1.21k|            uri[i++] = '\0';
   88|  1.21k|            uri[4] = char(i);
   89|  1.21k|        } else {
   90|     39|            uri[1] = uri[2] = uri[3] = 0;
   91|     39|            uri[4] = 5;
   92|     39|        }
   93|  1.25k|    }
   94|       |
   95|  1.25k|    if (uri[1] != 0) {
  ------------------
  |  Branch (95:9): [True: 1.21k, False: 42]
  ------------------
   96|  1.21k|        out.mediaType = uri + uri[1];
   97|  1.21k|    }
   98|  1.25k|    if (uri[2] != 0) {
  ------------------
  |  Branch (98:9): [True: 3, False: 1.24k]
  ------------------
   99|      3|        out.charset = uri + uri[2];
  100|      3|    }
  101|  1.25k|    if (uri[3] != 0) {
  ------------------
  |  Branch (101:9): [True: 1.18k, False: 68]
  ------------------
  102|  1.18k|        out.base64 = true;
  103|  1.18k|    }
  104|  1.25k|    out.data = uri + uri[4];
  105|  1.25k|    out.dataLength = (uri + uriLen) - out.data;
  106|       |
  107|  1.25k|    return true;
  108|  1.75k|}

_ZN10glTFCommon10ReadHelperIbE4ReadERN9rapidjson12GenericValueINS2_4UTF8IcEENS2_19MemoryPoolAllocatorINS2_12CrtAllocatorEEEEERb:
  289|  2.63k|    static bool Read(Value &val, bool &out) {
  290|  2.63k|        return val.IsBool() ? out = val.GetBool(), true : false;
  ------------------
  |  Branch (290:16): [True: 2.63k, False: 8]
  ------------------
  291|  2.63k|    }
_ZN10glTFCommon10ReadHelperIfE4ReadERN9rapidjson12GenericValueINS2_4UTF8IcEENS2_19MemoryPoolAllocatorINS2_12CrtAllocatorEEEEERf:
  296|  4.90k|    static bool Read(Value &val, float &out) {
  297|  4.90k|        return val.IsNumber() ? out = static_cast<float>(val.GetDouble()), true : false;
  ------------------
  |  Branch (297:16): [True: 4.90k, False: 2]
  ------------------
  298|  4.90k|    }
_ZN10glTFCommon10ReadHelperIPKcE4ReadERN9rapidjson12GenericValueINS4_4UTF8IcEENS4_19MemoryPoolAllocatorINS4_12CrtAllocatorEEEEERS2_:
  315|  14.4k|    static bool Read(Value &val, const char *&out) {
  316|  14.4k|        return val.IsString() ? (out = val.GetString(), true) : false;
  ------------------
  |  Branch (316:16): [True: 14.4k, False: 25]
  ------------------
  317|  14.4k|    }
_ZN10glTFCommon10ReadHelperINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE4ReadERN9rapidjson12GenericValueINS9_4UTF8IcEENS9_19MemoryPoolAllocatorINS9_12CrtAllocatorEEEEERS7_:
  322|  29.7k|    static bool Read(Value &val, std::string &out) {
  323|  29.7k|        return val.IsString() ? (out = std::string(val.GetString(), val.GetStringLength()), true) : false;
  ------------------
  |  Branch (323:16): [True: 29.7k, False: 60]
  ------------------
  324|  29.7k|    }
_ZN10glTFCommon10ReadHelperImE4ReadERN9rapidjson12GenericValueINS2_4UTF8IcEENS2_19MemoryPoolAllocatorINS2_12CrtAllocatorEEEEERm:
  336|  22.8k|    static bool Read(Value &val, uint64_t &out) {
  337|  22.8k|        return val.IsUint64() ? out = val.GetUint64(), true : false;
  ------------------
  |  Branch (337:16): [True: 22.7k, False: 98]
  ------------------
  338|  22.8k|    }
_ZN10glTFCommon9CopyValueERA3_KfR9aiColor4tIfE:
  138|  4.58k|inline void CopyValue(const glTFCommon::vec3 &v, aiColor4D &out) {
  139|  4.58k|    out.r = v[0];
  140|  4.58k|    out.g = v[1];
  141|  4.58k|    out.b = v[2];
  142|  4.58k|    out.a = 1.0;
  143|  4.58k|}
_ZN10glTFCommon9CopyValueERA4_KfR9aiColor4tIfE:
  145|  9.19k|inline void CopyValue(const glTFCommon::vec4 &v, aiColor4D &out) {
  146|  9.19k|    out.r = v[0];
  147|  9.19k|    out.g = v[1];
  148|  9.19k|    out.b = v[2];
  149|  9.19k|    out.a = v[3];
  150|  9.19k|}
_ZN10glTFCommon9CopyValueERA3_KfR10aiVector3tIfE:
  164|    389|inline void CopyValue(const glTFCommon::vec3 &v, aiVector3D &out) {
  165|    389|    out.x = v[0];
  166|    389|    out.y = v[1];
  167|    389|    out.z = v[2];
  168|    389|}
_ZN10glTFCommon9CopyValueERA4_KfR13aiQuaterniontIfE:
  170|    309|inline void CopyValue(const glTFCommon::vec4 &v, aiQuaternion &out) {
  171|    309|    out.x = v[0];
  172|    309|    out.y = v[1];
  173|    309|    out.z = v[2];
  174|    309|    out.w = v[3];
  175|    309|}
_ZN10glTFCommon9CopyValueERA16_KfR12aiMatrix4x4tIfE:
  177|  8.21k|inline void CopyValue(const glTFCommon::mat4 &v, aiMatrix4x4 &o) {
  178|  8.21k|    o.a1 = v[0];
  179|  8.21k|    o.b1 = v[1];
  180|  8.21k|    o.c1 = v[2];
  181|  8.21k|    o.d1 = v[3];
  182|  8.21k|    o.a2 = v[4];
  183|  8.21k|    o.b2 = v[5];
  184|  8.21k|    o.c2 = v[6];
  185|  8.21k|    o.d2 = v[7];
  186|  8.21k|    o.a3 = v[8];
  187|  8.21k|    o.b3 = v[9];
  188|  8.21k|    o.c3 = v[10];
  189|  8.21k|    o.d3 = v[11];
  190|  8.21k|    o.a4 = v[12];
  191|  8.21k|    o.b4 = v[13];
  192|  8.21k|    o.c4 = v[14];
  193|  8.21k|    o.d4 = v[15];
  194|  8.21k|}
_ZN10glTFCommon10FindMemberERN9rapidjson12GenericValueINS0_4UTF8IcEENS0_19MemoryPoolAllocatorINS0_12CrtAllocatorEEEEEPKc:
  386|  19.6k|inline Value *FindMember(Value &val, const char *id) {
  387|  19.6k|    if (!val.IsObject()) {
  ------------------
  |  Branch (387:9): [True: 0, False: 19.6k]
  ------------------
  388|      0|        return nullptr;
  389|      0|    }
  390|  19.6k|    Value::MemberIterator it = val.FindMember(id);
  391|  19.6k|    return (it != val.MemberEnd()) ? &it->value : nullptr;
  ------------------
  |  Branch (391:12): [True: 3.53k, False: 16.0k]
  ------------------
  392|  19.6k|}
_ZN10glTFCommon19FindStringInContextERN9rapidjson12GenericValueINS0_4UTF8IcEENS0_19MemoryPoolAllocatorINS0_12CrtAllocatorEEEEEPKcSA_SA_:
  405|  13.9k|inline Value *FindStringInContext(Value &val, const char *memberId, const char *context, const char *extraContext = nullptr) {
  406|  13.9k|    if (!val.IsObject()) {
  ------------------
  |  Branch (406:9): [True: 54, False: 13.9k]
  ------------------
  407|     54|        return nullptr;
  408|     54|    }
  409|  13.9k|    Value::MemberIterator it = val.FindMember(memberId);
  410|  13.9k|    if (it == val.MemberEnd()) {
  ------------------
  |  Branch (410:9): [True: 4.14k, False: 9.75k]
  ------------------
  411|  4.14k|        return nullptr;
  412|  4.14k|    }
  413|  9.75k|    if (!it->value.IsString()) {
  ------------------
  |  Branch (413:9): [True: 159, False: 9.59k]
  ------------------
  414|    159|        throwUnexpectedTypeError("string", memberId, context, extraContext);
  415|    159|    }
  416|  9.75k|    return &it->value;
  417|  13.9k|}
_ZN10glTFCommon17FindUIntInContextERN9rapidjson12GenericValueINS0_4UTF8IcEENS0_19MemoryPoolAllocatorINS0_12CrtAllocatorEEEEEPKcSA_SA_:
  433|  95.0k|inline Value *FindUIntInContext(Value &val, const char *memberId, const char *context, const char *extraContext = nullptr) {
  434|  95.0k|    if (!val.IsObject()) {
  ------------------
  |  Branch (434:9): [True: 385, False: 94.6k]
  ------------------
  435|    385|        return nullptr;
  436|    385|    }
  437|  94.6k|    Value::MemberIterator it = val.FindMember(memberId);
  438|  94.6k|    if (it == val.MemberEnd()) {
  ------------------
  |  Branch (438:9): [True: 46.9k, False: 47.6k]
  ------------------
  439|  46.9k|        return nullptr;
  440|  46.9k|    }
  441|  47.6k|    if (!it->value.IsUint()) {
  ------------------
  |  Branch (441:9): [True: 33, False: 47.6k]
  ------------------
  442|     33|        throwUnexpectedTypeError("uint", memberId, context, extraContext);
  443|     33|    }
  444|  47.6k|    return &it->value;
  445|  94.6k|}
_ZN10glTFCommon18FindArrayInContextERN9rapidjson12GenericValueINS0_4UTF8IcEENS0_19MemoryPoolAllocatorINS0_12CrtAllocatorEEEEEPKcSA_SA_:
  447|   111k|inline Value *FindArrayInContext(Value &val, const char *memberId, const char *context, const char *extraContext = nullptr) {
  448|   111k|    if (!val.IsObject()) {
  ------------------
  |  Branch (448:9): [True: 80, False: 111k]
  ------------------
  449|     80|        return nullptr;
  450|     80|    }
  451|   111k|    Value::MemberIterator it = val.FindMember(memberId);
  452|   111k|    if (it == val.MemberEnd()) {
  ------------------
  |  Branch (452:9): [True: 59.5k, False: 51.5k]
  ------------------
  453|  59.5k|        return nullptr;
  454|  59.5k|    }
  455|  51.5k|    if (!it->value.IsArray()) {
  ------------------
  |  Branch (455:9): [True: 38, False: 51.4k]
  ------------------
  456|     38|        throwUnexpectedTypeError("array", memberId, context, extraContext);
  457|     38|    }
  458|  51.5k|    return &it->value;
  459|   111k|}
_ZN10glTFCommon19FindObjectInContextERN9rapidjson12GenericValueINS0_4UTF8IcEENS0_19MemoryPoolAllocatorINS0_12CrtAllocatorEEEEEPKcSA_SA_:
  461|   169k|inline Value *FindObjectInContext(Value &val, const char * memberId, const char *context, const char *extraContext = nullptr) {
  462|   169k|    if (!val.IsObject()) {
  ------------------
  |  Branch (462:9): [True: 277, False: 169k]
  ------------------
  463|    277|        return nullptr;
  464|    277|    }
  465|   169k|    Value::MemberIterator it = val.FindMember(memberId);
  466|   169k|    if (it == val.MemberEnd()) {
  ------------------
  |  Branch (466:9): [True: 146k, False: 22.6k]
  ------------------
  467|   146k|        return nullptr;
  468|   146k|    }
  469|  22.6k|    if (!it->value.IsObject()) {
  ------------------
  |  Branch (469:9): [True: 25, False: 22.6k]
  ------------------
  470|     25|        ASSIMP_LOG_ERROR("Member \"", memberId, "\" was not of type \"", context, "\" when reading ", extraContext);
  471|     25|        return nullptr;
  472|     25|   }
  473|  22.6k|    return &it->value;
  474|  22.6k|}
_ZN10glTFCommon22FindExtensionInContextERN9rapidjson12GenericValueINS0_4UTF8IcEENS0_19MemoryPoolAllocatorINS0_12CrtAllocatorEEEEEPKcSA_SA_:
  476|      3|inline Value *FindExtensionInContext(Value &val, const char *extensionId, const char *context, const char *extraContext = nullptr) {
  477|      3|    if (Value *extensionList = FindObjectInContext(val, "extensions", context, extraContext)) {
  ------------------
  |  Branch (477:16): [True: 1, False: 2]
  ------------------
  478|      1|        if (Value *extension = FindObjectInContext(*extensionList, extensionId, context, extraContext)) {
  ------------------
  |  Branch (478:20): [True: 0, False: 1]
  ------------------
  479|      0|            return extension;
  480|      0|        }
  481|      1|    }
  482|      3|    return nullptr;
  483|      3|}
_ZN10glTFCommon10FindStringERN9rapidjson15GenericDocumentINS0_4UTF8IcEENS0_19MemoryPoolAllocatorINS0_12CrtAllocatorEEES5_EEPKc:
  487|  1.15k|inline Value *FindString(Document &doc, const char *memberId) {
  488|  1.15k|    return FindStringInContext(doc, memberId, "the document");
  489|  1.15k|}
_ZN10glTFCommon8FindUIntERN9rapidjson15GenericDocumentINS0_4UTF8IcEENS0_19MemoryPoolAllocatorINS0_12CrtAllocatorEEES5_EEPKc:
  495|  3.45k|inline Value *FindUInt(Document &doc, const char *memberId) {
  496|  3.45k|    return FindUIntInContext(doc, memberId, "the document");
  497|  3.45k|}
_ZN10glTFCommon9FindArrayERN9rapidjson15GenericDocumentINS0_4UTF8IcEENS0_19MemoryPoolAllocatorINS0_12CrtAllocatorEEES5_EEPKc:
  499|  16.4k|inline Value *FindArray(Document &val, const char *memberId) {
  500|  16.4k|    return FindArrayInContext(val, memberId, "the document");
  501|  16.4k|}
_ZN10glTFCommon10FindObjectERN9rapidjson15GenericDocumentINS0_4UTF8IcEENS0_19MemoryPoolAllocatorINS0_12CrtAllocatorEEES5_EEPKc:
  503|  19.1k|inline Value *FindObject(Document &doc, const char *memberId) {
  504|  19.1k|    return FindObjectInContext(doc, memberId, "the document");
  505|  19.1k|}
_ZN10glTFCommon10FindStringERN9rapidjson12GenericValueINS0_4UTF8IcEENS0_19MemoryPoolAllocatorINS0_12CrtAllocatorEEEEEPKc:
  511|  6.11k|inline Value *FindString(Value &val, const char *id) {
  512|  6.11k|    Value::MemberIterator it = val.FindMember(id);
  513|  6.11k|    return (it != val.MemberEnd() && it->value.IsString()) ? &it->value : nullptr;
  ------------------
  |  Branch (513:13): [True: 3.79k, False: 2.32k]
  |  Branch (513:38): [True: 3.64k, False: 144]
  ------------------
  514|  6.11k|}
_ZN10glTFCommon10FindObjectERN9rapidjson12GenericValueINS0_4UTF8IcEENS0_19MemoryPoolAllocatorINS0_12CrtAllocatorEEEEEPKc:
  516|  21.1k|inline Value *FindObject(Value &val, const char *id) {
  517|  21.1k|    Value::MemberIterator it = val.FindMember(id);
  518|  21.1k|    return (it != val.MemberEnd() && it->value.IsObject()) ? &it->value : nullptr;
  ------------------
  |  Branch (518:13): [True: 5.75k, False: 15.3k]
  |  Branch (518:38): [True: 5.25k, False: 502]
  ------------------
  519|  21.1k|}
_ZN10glTFCommon9FindArrayERN9rapidjson12GenericValueINS0_4UTF8IcEENS0_19MemoryPoolAllocatorINS0_12CrtAllocatorEEEEEPKc:
  521|  5.86k|inline Value *FindArray(Value &val, const char *id) {
  522|  5.86k|    Value::MemberIterator it = val.FindMember(id);
  523|  5.86k|    return (it != val.MemberEnd() && it->value.IsArray()) ? &it->value : nullptr;
  ------------------
  |  Branch (523:13): [True: 3.53k, False: 2.32k]
  |  Branch (523:38): [True: 3.52k, False: 16]
  ------------------
  524|  5.86k|}
_ZN10glTFCommon10FindNumberERN9rapidjson12GenericValueINS0_4UTF8IcEENS0_19MemoryPoolAllocatorINS0_12CrtAllocatorEEEEEPKc:
  526|    194|inline Value *FindNumber(Value &val, const char *id) {
  527|    194|    Value::MemberIterator it = val.FindMember(id);
  528|    194|    return (it != val.MemberEnd() && it->value.IsNumber()) ? &it->value : nullptr;
  ------------------
  |  Branch (528:13): [True: 142, False: 52]
  |  Branch (528:38): [True: 138, False: 4]
  ------------------
  529|    194|}
_ZN10glTFCommon24throwUnexpectedTypeErrorILi7EEEvRAT__KcPS1_S4_S4_:
  395|    159|inline void throwUnexpectedTypeError(const char (&expectedTypeName)[N], const char *memberId, const char *context, const char *extraContext) {
  396|    159|    std::string fullContext = context;
  397|    159|    if (extraContext && (strlen(extraContext) > 0)) {
  ------------------
  |  Branch (397:9): [True: 3, False: 156]
  |  Branch (397:25): [True: 0, False: 3]
  ------------------
  398|      0|        fullContext = fullContext + " (" + extraContext + ")";
  399|      0|    }
  400|    159|    throw DeadlyImportError("Member \"", memberId, "\" was not of type \"", expectedTypeName, "\" when reading ", fullContext);
  401|    159|}
_ZN10glTFCommon24throwUnexpectedTypeErrorILi5EEEvRAT__KcPS1_S4_S4_:
  395|     33|inline void throwUnexpectedTypeError(const char (&expectedTypeName)[N], const char *memberId, const char *context, const char *extraContext) {
  396|     33|    std::string fullContext = context;
  397|     33|    if (extraContext && (strlen(extraContext) > 0)) {
  ------------------
  |  Branch (397:9): [True: 29, False: 4]
  |  Branch (397:25): [True: 18, False: 11]
  ------------------
  398|     18|        fullContext = fullContext + " (" + extraContext + ")";
  399|     18|    }
  400|     33|    throw DeadlyImportError("Member \"", memberId, "\" was not of type \"", expectedTypeName, "\" when reading ", fullContext);
  401|     33|}
_ZN10glTFCommon24throwUnexpectedTypeErrorILi6EEEvRAT__KcPS1_S4_S4_:
  395|     38|inline void throwUnexpectedTypeError(const char (&expectedTypeName)[N], const char *memberId, const char *context, const char *extraContext) {
  396|     38|    std::string fullContext = context;
  397|     38|    if (extraContext && (strlen(extraContext) > 0)) {
  ------------------
  |  Branch (397:9): [True: 14, False: 24]
  |  Branch (397:25): [True: 5, False: 9]
  ------------------
  398|      5|        fullContext = fullContext + " (" + extraContext + ")";
  399|      5|    }
  400|     38|    throw DeadlyImportError("Member \"", memberId, "\" was not of type \"", expectedTypeName, "\" when reading ", fullContext);
  401|     38|}
_ZN10glTFCommon10ReadHelperINS_8NullableINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEEE4ReadERN9rapidjson12GenericValueINSB_4UTF8IcEENSB_19MemoryPoolAllocatorINSB_12CrtAllocatorEEEEERS9_:
  329|  4.81k|    static bool Read(Value &val, Nullable<T> &out) {
  330|  4.81k|        return out.isPresent = ReadHelper<T>::Read(val, out.value);
  331|  4.81k|    }
_ZNK10glTFCommon3RefIN5glTF26BufferEEcvbEv:
  269|  17.7k|    operator bool() const { return vector != nullptr && index < vector->size(); }
  ------------------
  |  Branch (269:36): [True: 14.3k, False: 3.45k]
  |  Branch (269:57): [True: 14.3k, False: 0]
  ------------------
_ZN10glTFCommon10ReadHelperIjE4ReadERN9rapidjson12GenericValueINS2_4UTF8IcEENS2_19MemoryPoolAllocatorINS2_12CrtAllocatorEEEEERj:
  282|  4.45k|    static bool Read(Value &val, T &out) {
  283|  4.45k|        return val.IsInt() ? out = static_cast<T>(val.GetInt()), true : false;
  ------------------
  |  Branch (283:16): [True: 4.42k, False: 31]
  ------------------
  284|  4.45k|    }
_ZN10glTFCommon3RefIN5glTF26BufferEEptEv:
  271|  34.0k|    T *operator->() { return (*vector)[index]; }
_ZN10glTFCommon3RefIN5glTF210BufferViewEEptEv:
  271|   138k|    T *operator->() { return (*vector)[index]; }
_ZN10glTFCommon10ReadHelperIN5glTF213ComponentTypeEE4ReadERN9rapidjson12GenericValueINS4_4UTF8IcEENS4_19MemoryPoolAllocatorINS4_12CrtAllocatorEEEEERS2_:
  282|  11.6k|    static bool Read(Value &val, T &out) {
  283|  11.6k|        return val.IsInt() ? out = static_cast<T>(val.GetInt()), true : false;
  ------------------
  |  Branch (283:16): [True: 11.6k, False: 22]
  ------------------
  284|  11.6k|    }
_ZNK10glTFCommon3RefIN5glTF210BufferViewEEcvbEv:
  269|  68.7k|    operator bool() const { return vector != nullptr && index < vector->size(); }
  ------------------
  |  Branch (269:36): [True: 63.8k, False: 4.88k]
  |  Branch (269:57): [True: 63.8k, False: 0]
  ------------------
_ZN10glTFCommon10ReadHelperIN5glTF216SamplerMagFilterEE4ReadERN9rapidjson12GenericValueINS4_4UTF8IcEENS4_19MemoryPoolAllocatorINS4_12CrtAllocatorEEEEERS2_:
  282|     76|    static bool Read(Value &val, T &out) {
  283|     76|        return val.IsInt() ? out = static_cast<T>(val.GetInt()), true : false;
  ------------------
  |  Branch (283:16): [True: 75, False: 1]
  ------------------
  284|     76|    }
_ZN10glTFCommon10ReadHelperIN5glTF216SamplerMinFilterEE4ReadERN9rapidjson12GenericValueINS4_4UTF8IcEENS4_19MemoryPoolAllocatorINS4_12CrtAllocatorEEEEERS2_:
  282|     72|    static bool Read(Value &val, T &out) {
  283|     72|        return val.IsInt() ? out = static_cast<T>(val.GetInt()), true : false;
  ------------------
  |  Branch (283:16): [True: 68, False: 4]
  ------------------
  284|     72|    }
_ZN10glTFCommon10ReadHelperIN5glTF211SamplerWrapEE4ReadERN9rapidjson12GenericValueINS4_4UTF8IcEENS4_19MemoryPoolAllocatorINS4_12CrtAllocatorEEEEERS2_:
  282|    156|    static bool Read(Value &val, T &out) {
  283|    156|        return val.IsInt() ? out = static_cast<T>(val.GetInt()), true : false;
  ------------------
  |  Branch (283:16): [True: 153, False: 3]
  ------------------
  284|    156|    }
_ZN10glTFCommon10ReadHelperIA4_fE4ReadERN9rapidjson12GenericValueINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEEEERS1_:
  303|  3.18k|    static bool Read(Value &val, float (&out)[N]) {
  304|  3.18k|        if (!val.IsArray() || val.Size() != N) return false;
  ------------------
  |  Branch (304:13): [True: 4, False: 3.17k]
  |  Branch (304:31): [True: 23, False: 3.15k]
  ------------------
  305|  15.7k|        for (unsigned int i = 0; i < N; ++i) {
  ------------------
  |  Branch (305:34): [True: 12.6k, False: 3.15k]
  ------------------
  306|  12.6k|            if (val[i].IsNumber())
  ------------------
  |  Branch (306:17): [True: 12.6k, False: 1]
  ------------------
  307|  12.6k|                out[i] = static_cast<float>(val[i].GetDouble());
  308|  12.6k|        }
  309|  3.15k|        return true;
  310|  3.18k|    }
_ZN10glTFCommon10ReadHelperIA3_fE4ReadERN9rapidjson12GenericValueINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEEEERS1_:
  303|  3.59k|    static bool Read(Value &val, float (&out)[N]) {
  304|  3.59k|        if (!val.IsArray() || val.Size() != N) return false;
  ------------------
  |  Branch (304:13): [True: 10, False: 3.58k]
  |  Branch (304:31): [True: 130, False: 3.45k]
  ------------------
  305|  13.8k|        for (unsigned int i = 0; i < N; ++i) {
  ------------------
  |  Branch (305:34): [True: 10.3k, False: 3.45k]
  ------------------
  306|  10.3k|            if (val[i].IsNumber())
  ------------------
  |  Branch (306:17): [True: 10.3k, False: 2]
  ------------------
  307|  10.3k|                out[i] = static_cast<float>(val[i].GetDouble());
  308|  10.3k|        }
  309|  3.45k|        return true;
  310|  3.59k|    }
_ZN10glTFCommon10ReadHelperIN5glTF213PrimitiveModeEE4ReadERN9rapidjson12GenericValueINS4_4UTF8IcEENS4_19MemoryPoolAllocatorINS4_12CrtAllocatorEEEEERS2_:
  282|  3.15k|    static bool Read(Value &val, T &out) {
  283|  3.15k|        return val.IsInt() ? out = static_cast<T>(val.GetInt()), true : false;
  ------------------
  |  Branch (283:16): [True: 3.14k, False: 9]
  ------------------
  284|  3.15k|    }
_ZNK10glTFCommon3RefIN5glTF24NodeEEcvbEv:
  269|  17.2k|    operator bool() const { return vector != nullptr && index < vector->size(); }
  ------------------
  |  Branch (269:36): [True: 17.2k, False: 0]
  |  Branch (269:57): [True: 17.2k, False: 0]
  ------------------
_ZN10glTFCommon10ReadHelperINS_8NullableIA16_fEEE4ReadERN9rapidjson12GenericValueINS5_4UTF8IcEENS5_19MemoryPoolAllocatorINS5_12CrtAllocatorEEEEERS3_:
  329|  10.0k|    static bool Read(Value &val, Nullable<T> &out) {
  330|  10.0k|        return out.isPresent = ReadHelper<T>::Read(val, out.value);
  331|  10.0k|    }
_ZN10glTFCommon10ReadHelperIA16_fE4ReadERN9rapidjson12GenericValueINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEEEERS1_:
  303|  10.0k|    static bool Read(Value &val, float (&out)[N]) {
  304|  10.0k|        if (!val.IsArray() || val.Size() != N) return false;
  ------------------
  |  Branch (304:13): [True: 0, False: 10.0k]
  |  Branch (304:31): [True: 334, False: 9.68k]
  ------------------
  305|   164k|        for (unsigned int i = 0; i < N; ++i) {
  ------------------
  |  Branch (305:34): [True: 154k, False: 9.68k]
  ------------------
  306|   154k|            if (val[i].IsNumber())
  ------------------
  |  Branch (306:17): [True: 154k, False: 28]
  ------------------
  307|   154k|                out[i] = static_cast<float>(val[i].GetDouble());
  308|   154k|        }
  309|  9.68k|        return true;
  310|  10.0k|    }
_ZN10glTFCommon10ReadHelperINS_8NullableIA3_fEEE4ReadERN9rapidjson12GenericValueINS5_4UTF8IcEENS5_19MemoryPoolAllocatorINS5_12CrtAllocatorEEEEERS3_:
  329|  1.58k|    static bool Read(Value &val, Nullable<T> &out) {
  330|  1.58k|        return out.isPresent = ReadHelper<T>::Read(val, out.value);
  331|  1.58k|    }
_ZN10glTFCommon10ReadHelperINS_8NullableIA4_fEEE4ReadERN9rapidjson12GenericValueINS5_4UTF8IcEENS5_19MemoryPoolAllocatorINS5_12CrtAllocatorEEEEERS3_:
  329|    719|    static bool Read(Value &val, Nullable<T> &out) {
  330|    719|        return out.isPresent = ReadHelper<T>::Read(val, out.value);
  331|    719|    }
_ZNK10glTFCommon3RefIN5glTF24MeshEEcvbEv:
  269|  5.70k|    operator bool() const { return vector != nullptr && index < vector->size(); }
  ------------------
  |  Branch (269:36): [True: 5.70k, False: 0]
  |  Branch (269:57): [True: 5.70k, False: 0]
  ------------------
_ZNK10glTFCommon3RefIN5glTF26CameraEEcvbEv:
  269|  7.36k|    operator bool() const { return vector != nullptr && index < vector->size(); }
  ------------------
  |  Branch (269:36): [True: 160, False: 7.20k]
  |  Branch (269:57): [True: 160, False: 0]
  ------------------
_ZN10glTFCommon3RefIN5glTF26CameraEEptEv:
  271|     98|    T *operator->() { return (*vector)[index]; }
_ZNK10glTFCommon3RefIN5glTF25LightEEcvbEv:
  269|  7.26k|    operator bool() const { return vector != nullptr && index < vector->size(); }
  ------------------
  |  Branch (269:36): [True: 0, False: 7.26k]
  |  Branch (269:57): [True: 0, False: 0]
  ------------------
_ZN10glTFCommon3RefIN5glTF25SceneEEptEv:
  271|  9.50k|    T *operator->() { return (*vector)[index]; }
_ZN10glTFCommon3RefIN4glTF6BufferEEC2Ev:
  261|  7.18k|            vector(nullptr),
  262|  7.18k|            index(0) {}
_ZN10glTFCommon3RefIN4glTF10BufferViewEEptEv:
  271|      2|    T *operator->() { return (*vector)[index]; }
_ZNK10glTFCommon3RefIN4glTF10BufferViewEEcvbEv:
  269|     28|    operator bool() const { return vector != nullptr && index < vector->size(); }
  ------------------
  |  Branch (269:36): [True: 2, False: 26]
  |  Branch (269:57): [True: 2, False: 0]
  ------------------
_ZNK10glTFCommon3RefIN4glTF7TextureEEcvbEv:
  269|     32|    operator bool() const { return vector != nullptr && index < vector->size(); }
  ------------------
  |  Branch (269:36): [True: 0, False: 32]
  |  Branch (269:57): [True: 0, False: 0]
  ------------------
_ZN10glTFCommon3RefIN4glTF5SceneEEC2Ev:
  261|  6.73k|            vector(nullptr),
  262|  6.73k|            index(0) {}
_ZN10glTFCommon3RefIN4glTF6BufferEEC2ERNSt3__16vectorIPS2_NS4_9allocatorIS6_EEEEj:
  264|  2.24k|            vector(&vec),
  265|  2.24k|            index(idx) {}
glTFImporter.cpp:_ZN10glTFCommonL10ReadMemberINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEEbRN9rapidjson12GenericValueINS8_4UTF8IcEENS8_19MemoryPoolAllocatorINS8_12CrtAllocatorEEEEEPKcRT_:
  369|  11.8k|inline static bool ReadMember(Value &obj, const char *id, T &out) {
  370|  11.8k|    if (!obj.IsObject()) {
  ------------------
  |  Branch (370:9): [True: 0, False: 11.8k]
  ------------------
  371|      0|        return false;
  372|      0|    }
  373|  11.8k|    Value::MemberIterator it = obj.FindMember(id);
  374|  11.8k|    if (it != obj.MemberEnd()) {
  ------------------
  |  Branch (374:9): [True: 4.43k, False: 7.39k]
  ------------------
  375|  4.43k|        return ReadHelper<T>::Read(it->value, out);
  376|  4.43k|    }
  377|  7.39k|    return false;
  378|  11.8k|}
glTFImporter.cpp:_ZN10glTFCommonL15MemberOrDefaultIbEET_RN9rapidjson12GenericValueINS2_4UTF8IcEENS2_19MemoryPoolAllocatorINS2_12CrtAllocatorEEEEEPKcS1_:
  381|  3.30k|inline static T MemberOrDefault(Value &obj, const char *id, T defaultValue) {
  382|  3.30k|    T out;
  383|  3.30k|    return ReadMember(obj, id, out) ? out : defaultValue;
  ------------------
  |  Branch (383:12): [True: 243, False: 3.06k]
  ------------------
  384|  3.30k|}
glTFImporter.cpp:_ZN10glTFCommonL10ReadMemberIbEEbRN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEEPKcRT_:
  369|  3.30k|inline static bool ReadMember(Value &obj, const char *id, T &out) {
  370|  3.30k|    if (!obj.IsObject()) {
  ------------------
  |  Branch (370:9): [True: 0, False: 3.30k]
  ------------------
  371|      0|        return false;
  372|      0|    }
  373|  3.30k|    Value::MemberIterator it = obj.FindMember(id);
  374|  3.30k|    if (it != obj.MemberEnd()) {
  ------------------
  |  Branch (374:9): [True: 249, False: 3.05k]
  ------------------
  375|    249|        return ReadHelper<T>::Read(it->value, out);
  376|    249|    }
  377|  3.05k|    return false;
  378|  3.30k|}
_ZN10glTFCommon3RefIN4glTF5SceneEEC2ERNSt3__16vectorIPS2_NS4_9allocatorIS6_EEEEj:
  264|     92|            vector(&vec),
  265|     92|            index(idx) {}
_ZN10glTFCommon3RefIN4glTF4NodeEEC2ERNSt3__16vectorIPS2_NS4_9allocatorIS6_EEEEj:
  264|  1.49k|            vector(&vec),
  265|  1.49k|            index(idx) {}
_ZN10glTFCommon8NullableIA16_fEC2Ev:
  246|  20.5k|            isPresent(false) {}
_ZN10glTFCommon8NullableIA3_fEC2Ev:
  246|  33.8k|            isPresent(false) {}
_ZN10glTFCommon8NullableIA4_fEC2Ev:
  246|  16.9k|            isPresent(false) {}
_ZN10glTFCommon3RefIN4glTF6CameraEEC2Ev:
  261|  1.56k|            vector(nullptr),
  262|  1.56k|            index(0) {}
_ZN10glTFCommon3RefIN4glTF5LightEEC2Ev:
  261|  1.56k|            vector(nullptr),
  262|  1.56k|            index(0) {}
_ZN10glTFCommon3RefIN4glTF4SkinEEC2Ev:
  261|  1.56k|            vector(nullptr),
  262|  1.56k|            index(0) {}
_ZN10glTFCommon3RefIN4glTF4NodeEEC2Ev:
  261|  1.56k|            vector(nullptr),
  262|  1.56k|            index(0) {}
glTFImporter.cpp:_ZN10glTFCommonL9ReadValueINS_8NullableIA16_fEEEEbRN9rapidjson12GenericValueINS4_4UTF8IcEENS4_19MemoryPoolAllocatorINS4_12CrtAllocatorEEEEERT_:
  364|    376|inline static bool ReadValue(Value &val, T &out) {
  365|    376|    return ReadHelper<T>::Read(val, out);
  366|    376|}
glTFImporter.cpp:_ZN10glTFCommonL10ReadMemberINS_8NullableIA3_fEEEEbRN9rapidjson12GenericValueINS4_4UTF8IcEENS4_19MemoryPoolAllocatorINS4_12CrtAllocatorEEEEEPKcRT_:
  369|  2.09k|inline static bool ReadMember(Value &obj, const char *id, T &out) {
  370|  2.09k|    if (!obj.IsObject()) {
  ------------------
  |  Branch (370:9): [True: 0, False: 2.09k]
  ------------------
  371|      0|        return false;
  372|      0|    }
  373|  2.09k|    Value::MemberIterator it = obj.FindMember(id);
  374|  2.09k|    if (it != obj.MemberEnd()) {
  ------------------
  |  Branch (374:9): [True: 846, False: 1.24k]
  ------------------
  375|    846|        return ReadHelper<T>::Read(it->value, out);
  376|    846|    }
  377|  1.24k|    return false;
  378|  2.09k|}
glTFImporter.cpp:_ZN10glTFCommonL10ReadMemberINS_8NullableIA4_fEEEEbRN9rapidjson12GenericValueINS4_4UTF8IcEENS4_19MemoryPoolAllocatorINS4_12CrtAllocatorEEEEEPKcRT_:
  369|  1.04k|inline static bool ReadMember(Value &obj, const char *id, T &out) {
  370|  1.04k|    if (!obj.IsObject()) {
  ------------------
  |  Branch (370:9): [True: 0, False: 1.04k]
  ------------------
  371|      0|        return false;
  372|      0|    }
  373|  1.04k|    Value::MemberIterator it = obj.FindMember(id);
  374|  1.04k|    if (it != obj.MemberEnd()) {
  ------------------
  |  Branch (374:9): [True: 142, False: 904]
  ------------------
  375|    142|        return ReadHelper<T>::Read(it->value, out);
  376|    142|    }
  377|    904|    return false;
  378|  1.04k|}
_ZN10glTFCommon3RefIN4glTF4MeshEEC2ERNSt3__16vectorIPS2_NS4_9allocatorIS6_EEEEj:
  264|    798|            vector(&vec),
  265|    798|            index(idx) {}
_ZN10glTFCommon3RefIN4glTF8AccessorEEC2Ev:
  261|  1.68k|            vector(nullptr),
  262|  1.68k|            index(0) {}
_ZN10glTFCommon3RefIN4glTF8MaterialEEC2Ev:
  261|    866|            vector(nullptr),
  262|    866|            index(0) {}
glTFImporter.cpp:_ZN10glTFCommonL15MemberOrDefaultIN4glTF13PrimitiveModeEEET_RN9rapidjson12GenericValueINS4_4UTF8IcEENS4_19MemoryPoolAllocatorINS4_12CrtAllocatorEEEEEPKcS3_:
  381|    846|inline static T MemberOrDefault(Value &obj, const char *id, T defaultValue) {
  382|    846|    T out;
  383|    846|    return ReadMember(obj, id, out) ? out : defaultValue;
  ------------------
  |  Branch (383:12): [True: 796, False: 50]
  ------------------
  384|    846|}
glTFImporter.cpp:_ZN10glTFCommonL10ReadMemberIN4glTF13PrimitiveModeEEEbRN9rapidjson12GenericValueINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEEEEPKcRT_:
  369|    846|inline static bool ReadMember(Value &obj, const char *id, T &out) {
  370|    846|    if (!obj.IsObject()) {
  ------------------
  |  Branch (370:9): [True: 0, False: 846]
  ------------------
  371|      0|        return false;
  372|      0|    }
  373|    846|    Value::MemberIterator it = obj.FindMember(id);
  374|    846|    if (it != obj.MemberEnd()) {
  ------------------
  |  Branch (374:9): [True: 810, False: 36]
  ------------------
  375|    810|        return ReadHelper<T>::Read(it->value, out);
  376|    810|    }
  377|     36|    return false;
  378|    846|}
_ZN10glTFCommon10ReadHelperIN4glTF13PrimitiveModeEE4ReadERN9rapidjson12GenericValueINS4_4UTF8IcEENS4_19MemoryPoolAllocatorINS4_12CrtAllocatorEEEEERS2_:
  282|    810|    static bool Read(Value &val, T &out) {
  283|    810|        return val.IsInt() ? out = static_cast<T>(val.GetInt()), true : false;
  ------------------
  |  Branch (283:16): [True: 796, False: 14]
  ------------------
  284|    810|    }
_ZN10glTFCommon3RefIN4glTF8AccessorEEC2ERNSt3__16vectorIPS2_NS4_9allocatorIS6_EEEEj:
  264|    852|            vector(&vec),
  265|    852|            index(idx) {}
_ZN10glTFCommon3RefIN4glTF10BufferViewEEC2Ev:
  261|    840|            vector(nullptr),
  262|    840|            index(0) {}
glTFImporter.cpp:_ZN10glTFCommonL15MemberOrDefaultIPKcEET_RN9rapidjson12GenericValueINS4_4UTF8IcEENS4_19MemoryPoolAllocatorINS4_12CrtAllocatorEEEEES2_S3_:
  381|  1.25k|inline static T MemberOrDefault(Value &obj, const char *id, T defaultValue) {
  382|  1.25k|    T out;
  383|  1.25k|    return ReadMember(obj, id, out) ? out : defaultValue;
  ------------------
  |  Branch (383:12): [True: 1.03k, False: 226]
  ------------------
  384|  1.25k|}
_ZN10glTFCommon3RefIN4glTF10BufferViewEEC2ERNSt3__16vectorIPS2_NS4_9allocatorIS6_EEEEj:
  264|    650|            vector(&vec),
  265|    650|            index(idx) {}
glTFImporter.cpp:_ZN10glTFCommonL15MemberOrDefaultImEET_RN9rapidjson12GenericValueINS2_4UTF8IcEENS2_19MemoryPoolAllocatorINS2_12CrtAllocatorEEEEEPKcS1_:
  381|    202|inline static T MemberOrDefault(Value &obj, const char *id, T defaultValue) {
  382|    202|    T out;
  383|    202|    return ReadMember(obj, id, out) ? out : defaultValue;
  ------------------
  |  Branch (383:12): [True: 32, False: 170]
  ------------------
  384|    202|}
glTFImporter.cpp:_ZN10glTFCommonL15MemberOrDefaultIjEET_RN9rapidjson12GenericValueINS2_4UTF8IcEENS2_19MemoryPoolAllocatorINS2_12CrtAllocatorEEEEEPKcS1_:
  381|  3.05k|inline static T MemberOrDefault(Value &obj, const char *id, T defaultValue) {
  382|  3.05k|    T out;
  383|  3.05k|    return ReadMember(obj, id, out) ? out : defaultValue;
  ------------------
  |  Branch (383:12): [True: 2.60k, False: 446]
  ------------------
  384|  3.05k|}
glTFImporter.cpp:_ZN10glTFCommonL10ReadMemberIjEEbRN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEEPKcRT_:
  369|  3.05k|inline static bool ReadMember(Value &obj, const char *id, T &out) {
  370|  3.05k|    if (!obj.IsObject()) {
  ------------------
  |  Branch (370:9): [True: 0, False: 3.05k]
  ------------------
  371|      0|        return false;
  372|      0|    }
  373|  3.05k|    Value::MemberIterator it = obj.FindMember(id);
  374|  3.05k|    if (it != obj.MemberEnd()) {
  ------------------
  |  Branch (374:9): [True: 2.63k, False: 416]
  ------------------
  375|  2.63k|        return ReadHelper<T>::Read(it->value, out);
  376|  2.63k|    }
  377|    416|    return false;
  378|  3.05k|}
glTFImporter.cpp:_ZN10glTFCommonL15MemberOrDefaultIN4glTF13ComponentTypeEEET_RN9rapidjson12GenericValueINS4_4UTF8IcEENS4_19MemoryPoolAllocatorINS4_12CrtAllocatorEEEEEPKcS3_:
  381|    748|inline static T MemberOrDefault(Value &obj, const char *id, T defaultValue) {
  382|    748|    T out;
  383|    748|    return ReadMember(obj, id, out) ? out : defaultValue;
  ------------------
  |  Branch (383:12): [True: 676, False: 72]
  ------------------
  384|    748|}
_ZN10glTFCommon3RefIN4glTF8MaterialEEC2ERNSt3__16vectorIPS2_NS4_9allocatorIS6_EEEEj:
  264|     46|            vector(&vec),
  265|     46|            index(idx) {}
_ZN10glTFCommon3RefIN4glTF7TextureEEC2Ev:
  261|    448|            vector(nullptr),
  262|    448|            index(0) {}
_ZN10glTFCommon3RefIN4glTF7TextureEEC2ERNSt3__16vectorIPS2_NS4_9allocatorIS6_EEEEj:
  264|     24|            vector(&vec),
  265|     24|            index(idx) {}
_ZN10glTFCommon3RefIN4glTF7SamplerEEC2Ev:
  261|     80|            vector(nullptr),
  262|     80|            index(0) {}
_ZN10glTFCommon3RefIN4glTF5ImageEEC2Ev:
  261|     80|            vector(nullptr),
  262|     80|            index(0) {}
_ZN10glTFCommon3RefIN4glTF5ImageEEC2ERNSt3__16vectorIPS2_NS4_9allocatorIS6_EEEEj:
  264|     28|            vector(&vec),
  265|     28|            index(idx) {}
_ZN10glTFCommon3RefIN4glTF7SamplerEEC2ERNSt3__16vectorIPS2_NS4_9allocatorIS6_EEEEj:
  264|     18|            vector(&vec),
  265|     18|            index(idx) {}
glTFImporter.cpp:_ZN10glTFCommonL10ReadMemberIN4glTF16SamplerMagFilterEEEbRN9rapidjson12GenericValueINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEEEEPKcRT_:
  369|     18|inline static bool ReadMember(Value &obj, const char *id, T &out) {
  370|     18|    if (!obj.IsObject()) {
  ------------------
  |  Branch (370:9): [True: 0, False: 18]
  ------------------
  371|      0|        return false;
  372|      0|    }
  373|     18|    Value::MemberIterator it = obj.FindMember(id);
  374|     18|    if (it != obj.MemberEnd()) {
  ------------------
  |  Branch (374:9): [True: 16, False: 2]
  ------------------
  375|     16|        return ReadHelper<T>::Read(it->value, out);
  376|     16|    }
  377|      2|    return false;
  378|     18|}
_ZN10glTFCommon10ReadHelperIN4glTF16SamplerMagFilterEE4ReadERN9rapidjson12GenericValueINS4_4UTF8IcEENS4_19MemoryPoolAllocatorINS4_12CrtAllocatorEEEEERS2_:
  282|     16|    static bool Read(Value &val, T &out) {
  283|     16|        return val.IsInt() ? out = static_cast<T>(val.GetInt()), true : false;
  ------------------
  |  Branch (283:16): [True: 14, False: 2]
  ------------------
  284|     16|    }
glTFImporter.cpp:_ZN10glTFCommonL10ReadMemberIN4glTF16SamplerMinFilterEEEbRN9rapidjson12GenericValueINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEEEEPKcRT_:
  369|     18|inline static bool ReadMember(Value &obj, const char *id, T &out) {
  370|     18|    if (!obj.IsObject()) {
  ------------------
  |  Branch (370:9): [True: 0, False: 18]
  ------------------
  371|      0|        return false;
  372|      0|    }
  373|     18|    Value::MemberIterator it = obj.FindMember(id);
  374|     18|    if (it != obj.MemberEnd()) {
  ------------------
  |  Branch (374:9): [True: 14, False: 4]
  ------------------
  375|     14|        return ReadHelper<T>::Read(it->value, out);
  376|     14|    }
  377|      4|    return false;
  378|     18|}
_ZN10glTFCommon10ReadHelperIN4glTF16SamplerMinFilterEE4ReadERN9rapidjson12GenericValueINS4_4UTF8IcEENS4_19MemoryPoolAllocatorINS4_12CrtAllocatorEEEEERS2_:
  282|     14|    static bool Read(Value &val, T &out) {
  283|     14|        return val.IsInt() ? out = static_cast<T>(val.GetInt()), true : false;
  ------------------
  |  Branch (283:16): [True: 12, False: 2]
  ------------------
  284|     14|    }
glTFImporter.cpp:_ZN10glTFCommonL10ReadMemberIN4glTF11SamplerWrapEEEbRN9rapidjson12GenericValueINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEEEEPKcRT_:
  369|     36|inline static bool ReadMember(Value &obj, const char *id, T &out) {
  370|     36|    if (!obj.IsObject()) {
  ------------------
  |  Branch (370:9): [True: 0, False: 36]
  ------------------
  371|      0|        return false;
  372|      0|    }
  373|     36|    Value::MemberIterator it = obj.FindMember(id);
  374|     36|    if (it != obj.MemberEnd()) {
  ------------------
  |  Branch (374:9): [True: 30, False: 6]
  ------------------
  375|     30|        return ReadHelper<T>::Read(it->value, out);
  376|     30|    }
  377|      6|    return false;
  378|     36|}
_ZN10glTFCommon10ReadHelperIN4glTF11SamplerWrapEE4ReadERN9rapidjson12GenericValueINS4_4UTF8IcEENS4_19MemoryPoolAllocatorINS4_12CrtAllocatorEEEEERS2_:
  282|     30|    static bool Read(Value &val, T &out) {
  283|     30|        return val.IsInt() ? out = static_cast<T>(val.GetInt()), true : false;
  ------------------
  |  Branch (283:16): [True: 26, False: 4]
  ------------------
  284|     30|    }
glTFImporter.cpp:_ZN10glTFCommonL9ReadValueIA4_fEEbRN9rapidjson12GenericValueINS2_4UTF8IcEENS2_19MemoryPoolAllocatorINS2_12CrtAllocatorEEEEERT_:
  364|     56|inline static bool ReadValue(Value &val, T &out) {
  365|     56|    return ReadHelper<T>::Read(val, out);
  366|     56|}
glTFImporter.cpp:_ZN10glTFCommonL10ReadMemberIfEEbRN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEEPKcRT_:
  369|     84|inline static bool ReadMember(Value &obj, const char *id, T &out) {
  370|     84|    if (!obj.IsObject()) {
  ------------------
  |  Branch (370:9): [True: 0, False: 84]
  ------------------
  371|      0|        return false;
  372|      0|    }
  373|     84|    Value::MemberIterator it = obj.FindMember(id);
  374|     84|    if (it != obj.MemberEnd()) {
  ------------------
  |  Branch (374:9): [True: 40, False: 44]
  ------------------
  375|     40|        return ReadHelper<T>::Read(it->value, out);
  376|     40|    }
  377|     44|    return false;
  378|     84|}
glTFImporter.cpp:_ZN10glTFCommonL10ReadMemberImEEbRN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEEPKcRT_:
  369|    202|inline static bool ReadMember(Value &obj, const char *id, T &out) {
  370|    202|    if (!obj.IsObject()) {
  ------------------
  |  Branch (370:9): [True: 0, False: 202]
  ------------------
  371|      0|        return false;
  372|      0|    }
  373|    202|    Value::MemberIterator it = obj.FindMember(id);
  374|    202|    if (it != obj.MemberEnd()) {
  ------------------
  |  Branch (374:9): [True: 84, False: 118]
  ------------------
  375|     84|        return ReadHelper<T>::Read(it->value, out);
  376|     84|    }
  377|    118|    return false;
  378|    202|}
glTFImporter.cpp:_ZN10glTFCommonL10ReadMemberIN4glTF13ComponentTypeEEEbRN9rapidjson12GenericValueINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEEEEPKcRT_:
  369|    748|inline static bool ReadMember(Value &obj, const char *id, T &out) {
  370|    748|    if (!obj.IsObject()) {
  ------------------
  |  Branch (370:9): [True: 0, False: 748]
  ------------------
  371|      0|        return false;
  372|      0|    }
  373|    748|    Value::MemberIterator it = obj.FindMember(id);
  374|    748|    if (it != obj.MemberEnd()) {
  ------------------
  |  Branch (374:9): [True: 694, False: 54]
  ------------------
  375|    694|        return ReadHelper<T>::Read(it->value, out);
  376|    694|    }
  377|     54|    return false;
  378|    748|}
_ZN10glTFCommon10ReadHelperIN4glTF13ComponentTypeEE4ReadERN9rapidjson12GenericValueINS4_4UTF8IcEENS4_19MemoryPoolAllocatorINS4_12CrtAllocatorEEEEERS2_:
  282|    694|    static bool Read(Value &val, T &out) {
  283|    694|        return val.IsInt() ? out = static_cast<T>(val.GetInt()), true : false;
  ------------------
  |  Branch (283:16): [True: 676, False: 18]
  ------------------
  284|    694|    }
glTFImporter.cpp:_ZN10glTFCommonL10ReadMemberIPKcEEbRN9rapidjson12GenericValueINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEEEES2_RT_:
  369|  2.12k|inline static bool ReadMember(Value &obj, const char *id, T &out) {
  370|  2.12k|    if (!obj.IsObject()) {
  ------------------
  |  Branch (370:9): [True: 0, False: 2.12k]
  ------------------
  371|      0|        return false;
  372|      0|    }
  373|  2.12k|    Value::MemberIterator it = obj.FindMember(id);
  374|  2.12k|    if (it != obj.MemberEnd()) {
  ------------------
  |  Branch (374:9): [True: 1.87k, False: 246]
  ------------------
  375|  1.87k|        return ReadHelper<T>::Read(it->value, out);
  376|  1.87k|    }
  377|    246|    return false;
  378|  2.12k|}
_ZNK10glTFCommon3RefIN4glTF4MeshEEcvbEv:
  269|    798|    operator bool() const { return vector != nullptr && index < vector->size(); }
  ------------------
  |  Branch (269:36): [True: 798, False: 0]
  |  Branch (269:57): [True: 798, False: 0]
  ------------------
_ZNK10glTFCommon3RefIN4glTF4NodeEEcvbEv:
  269|  1.49k|    operator bool() const { return vector != nullptr && index < vector->size(); }
  ------------------
  |  Branch (269:36): [True: 1.49k, False: 0]
  |  Branch (269:57): [True: 1.49k, False: 0]
  ------------------
_ZNK10glTFCommon3RefIN4glTF6BufferEEcvbEv:
  269|      2|    operator bool() const { return vector != nullptr && index < vector->size(); }
  ------------------
  |  Branch (269:36): [True: 0, False: 2]
  |  Branch (269:57): [True: 0, False: 0]
  ------------------
_ZN10glTFCommon3RefIN4glTF6BufferEEptEv:
  271|  1.96k|    T *operator->() { return (*vector)[index]; }
_ZN10glTFCommon3RefIN4glTF8AccessorEEptEv:
  271|     40|    T *operator->() { return (*vector)[index]; }
_ZNK10glTFCommon3RefIN4glTF6CameraEEcvbEv:
  269|    141|    operator bool() const { return vector != nullptr && index < vector->size(); }
  ------------------
  |  Branch (269:36): [True: 0, False: 141]
  |  Branch (269:57): [True: 0, False: 0]
  ------------------
_ZNK10glTFCommon3RefIN4glTF8AccessorEEcvbEv:
  269|     59|    operator bool() const { return vector != nullptr && index < vector->size(); }
  ------------------
  |  Branch (269:36): [True: 28, False: 31]
  |  Branch (269:57): [True: 28, False: 0]
  ------------------
_ZNK10glTFCommon3RefIN4glTF8MaterialEEcvbEv:
  269|     31|    operator bool() const { return vector != nullptr && index < vector->size(); }
  ------------------
  |  Branch (269:36): [True: 8, False: 23]
  |  Branch (269:57): [True: 8, False: 0]
  ------------------
_ZNK10glTFCommon3RefIN4glTF5SceneEEcvbEv:
  269|    331|    operator bool() const { return vector != nullptr && index < vector->size(); }
  ------------------
  |  Branch (269:36): [True: 46, False: 285]
  |  Branch (269:57): [True: 46, False: 0]
  ------------------
_ZN10glTFCommon3RefIN4glTF5SceneEEptEv:
  271|     46|    T *operator->() { return (*vector)[index]; }
_ZNK10glTFCommon3RefIN4glTF8MaterialEE8GetIndexEv:
  267|      8|    inline unsigned int GetIndex() const { return index; }
_ZN10glTFCommon3RefIN4glTF4NodeEEdeEv:
  273|    141|    T &operator*() { return *((*vector)[index]); }
_ZNK10glTFCommon3RefIN4glTF4MeshEE8GetIndexEv:
  267|    148|    inline unsigned int GetIndex() const { return index; }
_ZNK10glTFCommon3RefIN4glTF5LightEEcvbEv:
  269|    141|    operator bool() const { return vector != nullptr && index < vector->size(); }
  ------------------
  |  Branch (269:36): [True: 0, False: 141]
  |  Branch (269:57): [True: 0, False: 0]
  ------------------
_ZNK10glTFCommon3RefIN5glTF27TextureEEcvbEv:
  269|  45.8k|    operator bool() const { return vector != nullptr && index < vector->size(); }
  ------------------
  |  Branch (269:36): [True: 424, False: 45.4k]
  |  Branch (269:57): [True: 424, False: 0]
  ------------------
_ZN10glTFCommon3RefIN5glTF27TextureEEptEv:
  271|  1.91k|    T *operator->() { return (*vector)[index]; }
_ZNK10glTFCommon3RefIN5glTF25ImageEEcvbEv:
  269|    424|    operator bool() const { return vector != nullptr && index < vector->size(); }
  ------------------
  |  Branch (269:36): [True: 390, False: 34]
  |  Branch (269:57): [True: 390, False: 0]
  ------------------
_ZN10glTFCommon3RefIN5glTF25ImageEEptEv:
  271|    390|    T *operator->() { return (*vector)[index]; }
_ZNK10glTFCommon3RefIN5glTF27SamplerEEcvbEv:
  269|    390|    operator bool() const { return vector != nullptr && index < vector->size(); }
  ------------------
  |  Branch (269:36): [True: 320, False: 70]
  |  Branch (269:57): [True: 320, False: 0]
  ------------------
_ZN10glTFCommon3RefIN5glTF27SamplerEEptEv:
  271|  2.16k|    T *operator->() { return (*vector)[index]; }
_ZN10glTFCommon3RefIN5glTF25SceneEEC2Ev:
  261|  9.60k|            vector(nullptr),
  262|  9.60k|            index(0) {}
_ZN10glTFCommon3RefIN5glTF26BufferEEC2Ev:
  261|  17.6k|            vector(nullptr),
  262|  17.6k|            index(0) {}
_ZN10glTFCommon8NullableINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEC2Ev:
  246|  82.4k|            isPresent(false) {}
_ZN10glTFCommon8NullableIdEC2Ev:
  246|  82.4k|            isPresent(false) {}
_ZN10glTFCommon8NullableImEC2Ev:
  246|  82.4k|            isPresent(false) {}
_ZN10glTFCommon8NullableIlEC2Ev:
  246|  82.4k|            isPresent(false) {}
_ZN10glTFCommon8NullableIbEC2Ev:
  246|  82.4k|            isPresent(false) {}
_ZN10glTFCommon8NullableINSt3__16vectorIN5glTF215CustomExtensionENS1_9allocatorIS4_EEEEEC2Ev:
  246|  82.4k|            isPresent(false) {}
_ZN10glTFCommon3RefIN5glTF26BufferEEC2ERNSt3__16vectorIPS2_NS4_9allocatorIS6_EEEEj:
  264|  11.0k|            vector(&vec),
  265|  11.0k|            index(idx) {}
glTF2Importer.cpp:_ZN10glTFCommonL10ReadMemberINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEEbRN9rapidjson12GenericValueINS8_4UTF8IcEENS8_19MemoryPoolAllocatorINS8_12CrtAllocatorEEEEEPKcRT_:
  369|  72.1k|inline static bool ReadMember(Value &obj, const char *id, T &out) {
  370|  72.1k|    if (!obj.IsObject()) {
  ------------------
  |  Branch (370:9): [True: 0, False: 72.1k]
  ------------------
  371|      0|        return false;
  372|      0|    }
  373|  72.1k|    Value::MemberIterator it = obj.FindMember(id);
  374|  72.1k|    if (it != obj.MemberEnd()) {
  ------------------
  |  Branch (374:9): [True: 20.5k, False: 51.5k]
  ------------------
  375|  20.5k|        return ReadHelper<T>::Read(it->value, out);
  376|  20.5k|    }
  377|  51.5k|    return false;
  378|  72.1k|}
_ZN10glTFCommon3RefIN5glTF27TextureEEC2Ev:
  261|  92.7k|            vector(nullptr),
  262|  92.7k|            index(0) {}
_ZN10glTFCommon8NullableIN5glTF221PbrSpecularGlossinessEEC2Ev:
  246|  5.45k|            isPresent(false) {}
_ZN10glTFCommon8NullableIN5glTF216MaterialSpecularEEC2Ev:
  246|  5.45k|            isPresent(false) {}
_ZN10glTFCommon8NullableIN5glTF213MaterialSheenEEC2Ev:
  246|  5.45k|            isPresent(false) {}
_ZN10glTFCommon8NullableIN5glTF217MaterialClearcoatEEC2Ev:
  246|  5.45k|            isPresent(false) {}
_ZN10glTFCommon8NullableIN5glTF220MaterialTransmissionEEC2Ev:
  246|  5.45k|            isPresent(false) {}
_ZN10glTFCommon8NullableIN5glTF214MaterialVolumeEEC2Ev:
  246|  5.45k|            isPresent(false) {}
_ZN10glTFCommon8NullableIN5glTF211MaterialIOREEC2Ev:
  246|  5.45k|            isPresent(false) {}
_ZN10glTFCommon8NullableIN5glTF224MaterialEmissiveStrengthEEC2Ev:
  246|  5.45k|            isPresent(false) {}
_ZN10glTFCommon8NullableIN5glTF218MaterialAnisotropyEEC2Ev:
  246|  5.45k|            isPresent(false) {}
_ZNK10glTFCommon3RefIN5glTF25ImageEE8GetIndexEv:
  267|    390|    inline unsigned int GetIndex() const { return index; }
glTF2Importer.cpp:_ZN10glTFCommonL9ReadValueINS_8NullableINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEEEEbRN9rapidjson12GenericValueINSA_4UTF8IcEENSA_19MemoryPoolAllocatorINSA_12CrtAllocatorEEEEERT_:
  364|  4.81k|inline static bool ReadValue(Value &val, T &out) {
  365|  4.81k|    return ReadHelper<T>::Read(val, out);
  366|  4.81k|}
_ZN10glTFCommon3RefIN5glTF25SceneEEC2ERNSt3__16vectorIPS2_NS4_9allocatorIS6_EEEEj:
  264|  2.25k|            vector(&vec),
  265|  2.25k|            index(idx) {}
_ZN10glTFCommon3RefIN5glTF24NodeEEC2ERNSt3__16vectorIPS2_NS4_9allocatorIS6_EEEEj:
  264|  17.3k|            vector(&vec),
  265|  17.3k|            index(idx) {}
_ZN10glTFCommon3RefIN5glTF26CameraEEC2Ev:
  261|  15.3k|            vector(nullptr),
  262|  15.3k|            index(0) {}
_ZN10glTFCommon3RefIN5glTF25LightEEC2Ev:
  261|  15.3k|            vector(nullptr),
  262|  15.3k|            index(0) {}
_ZN10glTFCommon3RefIN5glTF24SkinEEC2Ev:
  261|  15.3k|            vector(nullptr),
  262|  15.3k|            index(0) {}
_ZN10glTFCommon3RefIN5glTF24NodeEEC2Ev:
  261|  15.6k|            vector(nullptr),
  262|  15.6k|            index(0) {}
glTF2Importer.cpp:_ZN10glTFCommonL9ReadValueINS_8NullableIA16_fEEEEbRN9rapidjson12GenericValueINS4_4UTF8IcEENS4_19MemoryPoolAllocatorINS4_12CrtAllocatorEEEEERT_:
  364|  9.64k|inline static bool ReadValue(Value &val, T &out) {
  365|  9.64k|    return ReadHelper<T>::Read(val, out);
  366|  9.64k|}
glTF2Importer.cpp:_ZN10glTFCommonL10ReadMemberINS_8NullableIA3_fEEEEbRN9rapidjson12GenericValueINS4_4UTF8IcEENS4_19MemoryPoolAllocatorINS4_12CrtAllocatorEEEEEPKcRT_:
  369|  10.4k|inline static bool ReadMember(Value &obj, const char *id, T &out) {
  370|  10.4k|    if (!obj.IsObject()) {
  ------------------
  |  Branch (370:9): [True: 0, False: 10.4k]
  ------------------
  371|      0|        return false;
  372|      0|    }
  373|  10.4k|    Value::MemberIterator it = obj.FindMember(id);
  374|  10.4k|    if (it != obj.MemberEnd()) {
  ------------------
  |  Branch (374:9): [True: 743, False: 9.70k]
  ------------------
  375|    743|        return ReadHelper<T>::Read(it->value, out);
  376|    743|    }
  377|  9.70k|    return false;
  378|  10.4k|}
glTF2Importer.cpp:_ZN10glTFCommonL10ReadMemberINS_8NullableIA4_fEEEEbRN9rapidjson12GenericValueINS4_4UTF8IcEENS4_19MemoryPoolAllocatorINS4_12CrtAllocatorEEEEEPKcRT_:
  369|  5.22k|inline static bool ReadMember(Value &obj, const char *id, T &out) {
  370|  5.22k|    if (!obj.IsObject()) {
  ------------------
  |  Branch (370:9): [True: 0, False: 5.22k]
  ------------------
  371|      0|        return false;
  372|      0|    }
  373|  5.22k|    Value::MemberIterator it = obj.FindMember(id);
  374|  5.22k|    if (it != obj.MemberEnd()) {
  ------------------
  |  Branch (374:9): [True: 577, False: 4.64k]
  ------------------
  375|    577|        return ReadHelper<T>::Read(it->value, out);
  376|    577|    }
  377|  4.64k|    return false;
  378|  5.22k|}
_ZN10glTFCommon3RefIN5glTF24MeshEEC2ERNSt3__16vectorIPS2_NS4_9allocatorIS6_EEEEj:
  264|  5.70k|            vector(&vec),
  265|  5.70k|            index(idx) {}
_ZN10glTFCommon3RefIN5glTF28AccessorEEC2Ev:
  261|  18.3k|            vector(nullptr),
  262|  18.3k|            index(0) {}
_ZN10glTFCommon3RefIN5glTF28MaterialEEC2Ev:
  261|  4.47k|            vector(nullptr),
  262|  4.47k|            index(0) {}
glTF2Importer.cpp:_ZN10glTFCommonL15MemberOrDefaultIN5glTF213PrimitiveModeEEET_RN9rapidjson12GenericValueINS4_4UTF8IcEENS4_19MemoryPoolAllocatorINS4_12CrtAllocatorEEEEEPKcS3_:
  381|  4.44k|inline static T MemberOrDefault(Value &obj, const char *id, T defaultValue) {
  382|  4.44k|    T out;
  383|  4.44k|    return ReadMember(obj, id, out) ? out : defaultValue;
  ------------------
  |  Branch (383:12): [True: 3.14k, False: 1.29k]
  ------------------
  384|  4.44k|}
glTF2Importer.cpp:_ZN10glTFCommonL10ReadMemberIN5glTF213PrimitiveModeEEEbRN9rapidjson12GenericValueINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEEEEPKcRT_:
  369|  4.44k|inline static bool ReadMember(Value &obj, const char *id, T &out) {
  370|  4.44k|    if (!obj.IsObject()) {
  ------------------
  |  Branch (370:9): [True: 80, False: 4.36k]
  ------------------
  371|     80|        return false;
  372|     80|    }
  373|  4.36k|    Value::MemberIterator it = obj.FindMember(id);
  374|  4.36k|    if (it != obj.MemberEnd()) {
  ------------------
  |  Branch (374:9): [True: 3.15k, False: 1.20k]
  ------------------
  375|  3.15k|        return ReadHelper<T>::Read(it->value, out);
  376|  3.15k|    }
  377|  1.20k|    return false;
  378|  4.36k|}
_ZN10glTFCommon3RefIN5glTF28AccessorEEC2ERNSt3__16vectorIPS2_NS4_9allocatorIS6_EEEEj:
  264|  13.4k|            vector(&vec),
  265|  13.4k|            index(idx) {}
_ZN10glTFCommon3RefIN5glTF210BufferViewEEC2Ev:
  261|  13.5k|            vector(nullptr),
  262|  13.5k|            index(0) {}
_ZN10glTFCommon3RefIN5glTF210BufferViewEEC2ERNSt3__16vectorIPS2_NS4_9allocatorIS6_EEEEj:
  264|  8.22k|            vector(&vec),
  265|  8.22k|            index(idx) {}
glTF2Importer.cpp:_ZN10glTFCommonL15MemberOrDefaultIjEET_RN9rapidjson12GenericValueINS2_4UTF8IcEENS2_19MemoryPoolAllocatorINS2_12CrtAllocatorEEEEEPKcS1_:
  381|  7.61k|inline static T MemberOrDefault(Value &obj, const char *id, T defaultValue) {
  382|  7.61k|    T out;
  383|  7.61k|    return ReadMember(obj, id, out) ? out : defaultValue;
  ------------------
  |  Branch (383:12): [True: 1.81k, False: 5.79k]
  ------------------
  384|  7.61k|}
glTF2Importer.cpp:_ZN10glTFCommonL10ReadMemberIjEEbRN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEEPKcRT_:
  369|  7.61k|inline static bool ReadMember(Value &obj, const char *id, T &out) {
  370|  7.61k|    if (!obj.IsObject()) {
  ------------------
  |  Branch (370:9): [True: 0, False: 7.61k]
  ------------------
  371|      0|        return false;
  372|      0|    }
  373|  7.61k|    Value::MemberIterator it = obj.FindMember(id);
  374|  7.61k|    if (it != obj.MemberEnd()) {
  ------------------
  |  Branch (374:9): [True: 1.81k, False: 5.79k]
  ------------------
  375|  1.81k|        return ReadHelper<T>::Read(it->value, out);
  376|  1.81k|    }
  377|  5.79k|    return false;
  378|  7.61k|}
glTF2Importer.cpp:_ZN10glTFCommonL15MemberOrDefaultImEET_RN9rapidjson12GenericValueINS2_4UTF8IcEENS2_19MemoryPoolAllocatorINS2_12CrtAllocatorEEEEEPKcS1_:
  381|  29.5k|inline static T MemberOrDefault(Value &obj, const char *id, T defaultValue) {
  382|  29.5k|    T out;
  383|  29.5k|    return ReadMember(obj, id, out) ? out : defaultValue;
  ------------------
  |  Branch (383:12): [True: 22.7k, False: 6.86k]
  ------------------
  384|  29.5k|}
glTF2Importer.cpp:_ZN10glTFCommonL15MemberOrDefaultIN5glTF213ComponentTypeEEET_RN9rapidjson12GenericValueINS4_4UTF8IcEENS4_19MemoryPoolAllocatorINS4_12CrtAllocatorEEEEEPKcS3_:
  381|  12.8k|inline static T MemberOrDefault(Value &obj, const char *id, T defaultValue) {
  382|  12.8k|    T out;
  383|  12.8k|    return ReadMember(obj, id, out) ? out : defaultValue;
  ------------------
  |  Branch (383:12): [True: 11.6k, False: 1.22k]
  ------------------
  384|  12.8k|}
glTF2Importer.cpp:_ZN10glTFCommonL10ReadMemberIN5glTF213ComponentTypeEEEbRN9rapidjson12GenericValueINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEEEEPKcRT_:
  369|  12.8k|inline static bool ReadMember(Value &obj, const char *id, T &out) {
  370|  12.8k|    if (!obj.IsObject()) {
  ------------------
  |  Branch (370:9): [True: 0, False: 12.8k]
  ------------------
  371|      0|        return false;
  372|      0|    }
  373|  12.8k|    Value::MemberIterator it = obj.FindMember(id);
  374|  12.8k|    if (it != obj.MemberEnd()) {
  ------------------
  |  Branch (374:9): [True: 11.6k, False: 1.20k]
  ------------------
  375|  11.6k|        return ReadHelper<T>::Read(it->value, out);
  376|  11.6k|    }
  377|  1.20k|    return false;
  378|  12.8k|}
glTF2Importer.cpp:_ZN10glTFCommonL10ReadMemberIPKcEEbRN9rapidjson12GenericValueINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEEEES2_RT_:
  369|  12.9k|inline static bool ReadMember(Value &obj, const char *id, T &out) {
  370|  12.9k|    if (!obj.IsObject()) {
  ------------------
  |  Branch (370:9): [True: 0, False: 12.9k]
  ------------------
  371|      0|        return false;
  372|      0|    }
  373|  12.9k|    Value::MemberIterator it = obj.FindMember(id);
  374|  12.9k|    if (it != obj.MemberEnd()) {
  ------------------
  |  Branch (374:9): [True: 12.5k, False: 395]
  ------------------
  375|  12.5k|        return ReadHelper<T>::Read(it->value, out);
  376|  12.5k|    }
  377|    395|    return false;
  378|  12.9k|}
glTF2Importer.cpp:_ZN10glTFCommonL10ReadMemberImEEbRN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEEPKcRT_:
  369|  29.5k|inline static bool ReadMember(Value &obj, const char *id, T &out) {
  370|  29.5k|    if (!obj.IsObject()) {
  ------------------
  |  Branch (370:9): [True: 0, False: 29.5k]
  ------------------
  371|      0|        return false;
  372|      0|    }
  373|  29.5k|    Value::MemberIterator it = obj.FindMember(id);
  374|  29.5k|    if (it != obj.MemberEnd()) {
  ------------------
  |  Branch (374:9): [True: 22.7k, False: 6.81k]
  ------------------
  375|  22.7k|        return ReadHelper<T>::Read(it->value, out);
  376|  22.7k|    }
  377|  6.81k|    return false;
  378|  29.5k|}
_ZN10glTFCommon3RefIN5glTF28MaterialEEC2ERNSt3__16vectorIPS2_NS4_9allocatorIS6_EEEEj:
  264|  3.13k|            vector(&vec),
  265|  3.13k|            index(idx) {}
glTF2Importer.cpp:_ZN10glTFCommonL10ReadMemberIA4_fEEbRN9rapidjson12GenericValueINS2_4UTF8IcEENS2_19MemoryPoolAllocatorINS2_12CrtAllocatorEEEEEPKcRT_:
  369|  2.84k|inline static bool ReadMember(Value &obj, const char *id, T &out) {
  370|  2.84k|    if (!obj.IsObject()) {
  ------------------
  |  Branch (370:9): [True: 0, False: 2.84k]
  ------------------
  371|      0|        return false;
  372|      0|    }
  373|  2.84k|    Value::MemberIterator it = obj.FindMember(id);
  374|  2.84k|    if (it != obj.MemberEnd()) {
  ------------------
  |  Branch (374:9): [True: 2.40k, False: 436]
  ------------------
  375|  2.40k|        return ReadHelper<T>::Read(it->value, out);
  376|  2.40k|    }
  377|    436|    return false;
  378|  2.84k|}
_ZN10glTFCommon3RefIN5glTF27TextureEEC2ERNSt3__16vectorIPS2_NS4_9allocatorIS6_EEEEj:
  264|    254|            vector(&vec),
  265|    254|            index(idx) {}
_ZN10glTFCommon3RefIN5glTF27SamplerEEC2Ev:
  261|    203|            vector(nullptr),
  262|    203|            index(0) {}
_ZN10glTFCommon3RefIN5glTF25ImageEEC2Ev:
  261|    203|            vector(nullptr),
  262|    203|            index(0) {}
_ZN10glTFCommon3RefIN5glTF25ImageEEC2ERNSt3__16vectorIPS2_NS4_9allocatorIS6_EEEEj:
  264|    165|            vector(&vec),
  265|    165|            index(idx) {}
_ZN10glTFCommon3RefIN5glTF27SamplerEEC2ERNSt3__16vectorIPS2_NS4_9allocatorIS6_EEEEj:
  264|    144|            vector(&vec),
  265|    144|            index(idx) {}
glTF2Importer.cpp:_ZN10glTFCommonL10ReadMemberIN5glTF216SamplerMagFilterEEEbRN9rapidjson12GenericValueINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEEEEPKcRT_:
  369|    144|inline static bool ReadMember(Value &obj, const char *id, T &out) {
  370|    144|    if (!obj.IsObject()) {
  ------------------
  |  Branch (370:9): [True: 0, False: 144]
  ------------------
  371|      0|        return false;
  372|      0|    }
  373|    144|    Value::MemberIterator it = obj.FindMember(id);
  374|    144|    if (it != obj.MemberEnd()) {
  ------------------
  |  Branch (374:9): [True: 76, False: 68]
  ------------------
  375|     76|        return ReadHelper<T>::Read(it->value, out);
  376|     76|    }
  377|     68|    return false;
  378|    144|}
glTF2Importer.cpp:_ZN10glTFCommonL10ReadMemberIN5glTF216SamplerMinFilterEEEbRN9rapidjson12GenericValueINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEEEEPKcRT_:
  369|    144|inline static bool ReadMember(Value &obj, const char *id, T &out) {
  370|    144|    if (!obj.IsObject()) {
  ------------------
  |  Branch (370:9): [True: 0, False: 144]
  ------------------
  371|      0|        return false;
  372|      0|    }
  373|    144|    Value::MemberIterator it = obj.FindMember(id);
  374|    144|    if (it != obj.MemberEnd()) {
  ------------------
  |  Branch (374:9): [True: 72, False: 72]
  ------------------
  375|     72|        return ReadHelper<T>::Read(it->value, out);
  376|     72|    }
  377|     72|    return false;
  378|    144|}
glTF2Importer.cpp:_ZN10glTFCommonL10ReadMemberIN5glTF211SamplerWrapEEEbRN9rapidjson12GenericValueINS3_4UTF8IcEENS3_19MemoryPoolAllocatorINS3_12CrtAllocatorEEEEEPKcRT_:
  369|    288|inline static bool ReadMember(Value &obj, const char *id, T &out) {
  370|    288|    if (!obj.IsObject()) {
  ------------------
  |  Branch (370:9): [True: 0, False: 288]
  ------------------
  371|      0|        return false;
  372|      0|    }
  373|    288|    Value::MemberIterator it = obj.FindMember(id);
  374|    288|    if (it != obj.MemberEnd()) {
  ------------------
  |  Branch (374:9): [True: 156, False: 132]
  ------------------
  375|    156|        return ReadHelper<T>::Read(it->value, out);
  376|    156|    }
  377|    132|    return false;
  378|    288|}
glTF2Importer.cpp:_ZN10glTFCommonL10ReadMemberIfEEbRN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEEPKcRT_:
  369|  9.05k|inline static bool ReadMember(Value &obj, const char *id, T &out) {
  370|  9.05k|    if (!obj.IsObject()) {
  ------------------
  |  Branch (370:9): [True: 0, False: 9.05k]
  ------------------
  371|      0|        return false;
  372|      0|    }
  373|  9.05k|    Value::MemberIterator it = obj.FindMember(id);
  374|  9.05k|    if (it != obj.MemberEnd()) {
  ------------------
  |  Branch (374:9): [True: 4.86k, False: 4.18k]
  ------------------
  375|  4.86k|        return ReadHelper<T>::Read(it->value, out);
  376|  4.86k|    }
  377|  4.18k|    return false;
  378|  9.05k|}
glTF2Importer.cpp:_ZN10glTFCommonL10ReadMemberIA3_fEEbRN9rapidjson12GenericValueINS2_4UTF8IcEENS2_19MemoryPoolAllocatorINS2_12CrtAllocatorEEEEEPKcRT_:
  369|  3.06k|inline static bool ReadMember(Value &obj, const char *id, T &out) {
  370|  3.06k|    if (!obj.IsObject()) {
  ------------------
  |  Branch (370:9): [True: 0, False: 3.06k]
  ------------------
  371|      0|        return false;
  372|      0|    }
  373|  3.06k|    Value::MemberIterator it = obj.FindMember(id);
  374|  3.06k|    if (it != obj.MemberEnd()) {
  ------------------
  |  Branch (374:9): [True: 2.00k, False: 1.05k]
  ------------------
  375|  2.00k|        return ReadHelper<T>::Read(it->value, out);
  376|  2.00k|    }
  377|  1.05k|    return false;
  378|  3.06k|}
glTF2Importer.cpp:_ZN10glTFCommonL10ReadMemberIbEEbRN9rapidjson12GenericValueINS1_4UTF8IcEENS1_19MemoryPoolAllocatorINS1_12CrtAllocatorEEEEEPKcRT_:
  369|  3.06k|inline static bool ReadMember(Value &obj, const char *id, T &out) {
  370|  3.06k|    if (!obj.IsObject()) {
  ------------------
  |  Branch (370:9): [True: 0, False: 3.06k]
  ------------------
  371|      0|        return false;
  372|      0|    }
  373|  3.06k|    Value::MemberIterator it = obj.FindMember(id);
  374|  3.06k|    if (it != obj.MemberEnd()) {
  ------------------
  |  Branch (374:9): [True: 2.39k, False: 676]
  ------------------
  375|  2.39k|        return ReadHelper<T>::Read(it->value, out);
  376|  2.39k|    }
  377|    676|    return false;
  378|  3.06k|}
_ZN10glTFCommon3RefIN5glTF24SkinEEC2ERNSt3__16vectorIPS2_NS4_9allocatorIS6_EEEEj:
  264|  4.24k|            vector(&vec),
  265|  4.24k|            index(idx) {}
_ZN10glTFCommon3RefIN5glTF26CameraEEC2ERNSt3__16vectorIPS2_NS4_9allocatorIS6_EEEEj:
  264|     98|            vector(&vec),
  265|     98|            index(idx) {}
glTF2Importer.cpp:_ZN10glTFCommonL15MemberOrDefaultIPKcEET_RN9rapidjson12GenericValueINS4_4UTF8IcEENS4_19MemoryPoolAllocatorINS4_12CrtAllocatorEEEEES2_S3_:
  381|    104|inline static T MemberOrDefault(Value &obj, const char *id, T defaultValue) {
  382|    104|    T out;
  383|    104|    return ReadMember(obj, id, out) ? out : defaultValue;
  ------------------
  |  Branch (383:12): [True: 98, False: 6]
  ------------------
  384|    104|}
glTF2Importer.cpp:_ZN10glTFCommonL15MemberOrDefaultIfEET_RN9rapidjson12GenericValueINS2_4UTF8IcEENS2_19MemoryPoolAllocatorINS2_12CrtAllocatorEEEEEPKcS1_:
  381|    372|inline static T MemberOrDefault(Value &obj, const char *id, T defaultValue) {
  382|    372|    T out;
  383|    372|    return ReadMember(obj, id, out) ? out : defaultValue;
  ------------------
  |  Branch (383:12): [True: 264, False: 108]
  ------------------
  384|    372|}
_ZN10glTFCommon3RefIN5glTF29AnimationEEC2ERNSt3__16vectorIPS2_NS4_9allocatorIS6_EEEEj:
  264|    280|            vector(&vec),
  265|    280|            index(idx) {}
_ZN10glTFCommon3RefIN5glTF24NodeEEptEv:
  271|  3.71k|    T *operator->() { return (*vector)[index]; }
_ZN10glTFCommon3RefIN5glTF28AccessorEEptEv:
  271|  14.2k|    T *operator->() { return (*vector)[index]; }
_ZNK10glTFCommon3RefIN5glTF28MaterialEEcvbEv:
  269|  1.60k|    operator bool() const { return vector != nullptr && index < vector->size(); }
  ------------------
  |  Branch (269:36): [True: 1.18k, False: 420]
  |  Branch (269:57): [True: 1.18k, False: 0]
  ------------------
_ZNK10glTFCommon3RefIN5glTF28AccessorEEcvbEv:
  269|  8.13k|    operator bool() const { return vector != nullptr && index < vector->size(); }
  ------------------
  |  Branch (269:36): [True: 7.49k, False: 644]
  |  Branch (269:57): [True: 7.49k, False: 0]
  ------------------
_ZN10glTFCommon3RefIN5glTF24MeshEEptEv:
  271|    341|    T *operator->() { return (*vector)[index]; }
_ZNK10glTFCommon3RefIN5glTF24SkinEEcvbEv:
  269|  1.82k|    operator bool() const { return vector != nullptr && index < vector->size(); }
  ------------------
  |  Branch (269:36): [True: 435, False: 1.38k]
  |  Branch (269:57): [True: 421, False: 14]
  ------------------
_ZN10glTFCommon3RefIN5glTF24SkinEEptEv:
  271|  2.49k|    T *operator->() { return (*vector)[index]; }
_ZNK10glTFCommon3RefIN5glTF25SceneEEcvbEv:
  269|  6.07k|    operator bool() const { return vector != nullptr && index < vector->size(); }
  ------------------
  |  Branch (269:36): [True: 5.56k, False: 503]
  |  Branch (269:57): [True: 5.56k, False: 0]
  ------------------
_ZNK10glTFCommon3RefIN5glTF28MaterialEE8GetIndexEv:
  267|  1.18k|    inline unsigned int GetIndex() const { return index; }
_ZN10glTFCommon3RefIN5glTF24NodeEEdeEv:
  273|  9.20k|    T &operator*() { return *((*vector)[index]); }
_ZNK10glTFCommon3RefIN5glTF24MeshEE8GetIndexEv:
  267|  1.82k|    inline unsigned int GetIndex() const { return index; }
_ZNK10glTFCommon3RefIN5glTF26CameraEE8GetIndexEv:
  267|     62|    inline unsigned int GetIndex() const { return index; }
_ZNK10glTFCommon3RefIN5glTF24NodeEE8GetIndexEv:
  267|    120|    inline unsigned int GetIndex() const { return index; }

_ZN6Assimp6Base646DecodeEPKcmRPh:
  122|  1.18k|size_t Decode(const char *in, size_t inLength, uint8_t *&out) {
  123|  1.18k|    if (in == nullptr) {
  ------------------
  |  Branch (123:9): [True: 0, False: 1.18k]
  ------------------
  124|      0|        out = nullptr;
  125|      0|        return 0;
  126|      0|    }
  127|       |
  128|  1.18k|    if (inLength % 4 != 0) {
  ------------------
  |  Branch (128:9): [True: 32, False: 1.15k]
  ------------------
  129|     32|        throw DeadlyImportError("Invalid base64 encoded data: \"", std::string(in, std::min(size_t(32), inLength)),
  130|     32|            "\", length:", inLength);
  131|     32|    }
  132|       |
  133|  1.15k|    if (inLength < 4) {
  ------------------
  |  Branch (133:9): [True: 0, False: 1.15k]
  ------------------
  134|      0|        out = nullptr;
  135|      0|        return 0;
  136|      0|    }
  137|       |
  138|  1.15k|    int nEquals = int(in[inLength - 1] == '=') +
  139|  1.15k|                  int(in[inLength - 2] == '=');
  140|       |
  141|  1.15k|    size_t outLength = (inLength * 3) / 4 - nEquals;
  142|  1.15k|    out = new uint8_t[outLength];
  143|  1.15k|    memset(out, 0, outLength);
  144|       |
  145|  1.15k|    size_t i, j = 0;
  146|       |
  147|   182k|    for (i = 0; i + 4 < inLength; i += 4) {
  ------------------
  |  Branch (147:17): [True: 180k, False: 1.15k]
  ------------------
  148|   180k|        uint8_t b0 = DecodeChar(in[i]);
  149|   180k|        uint8_t b1 = DecodeChar(in[i + 1]);
  150|   180k|        uint8_t b2 = DecodeChar(in[i + 2]);
  151|   180k|        uint8_t b3 = DecodeChar(in[i + 3]);
  152|       |
  153|   180k|        out[j++] = (uint8_t)((b0 << 2) | (b1 >> 4));
  154|   180k|        out[j++] = (uint8_t)((b1 << 4) | (b2 >> 2));
  155|   180k|        out[j++] = (uint8_t)((b2 << 6) | b3);
  156|   180k|    }
  157|       |
  158|  1.15k|    {
  159|  1.15k|        uint8_t b0 = DecodeChar(in[i]);
  160|  1.15k|        uint8_t b1 = DecodeChar(in[i + 1]);
  161|  1.15k|        uint8_t b2 = DecodeChar(in[i + 2]);
  162|  1.15k|        uint8_t b3 = DecodeChar(in[i + 3]);
  163|       |
  164|  1.15k|        out[j++] = (uint8_t)((b0 << 2) | (b1 >> 4));
  165|  1.15k|        if (b2 < 64) out[j++] = (uint8_t)((b1 << 4) | (b2 >> 2));
  ------------------
  |  Branch (165:13): [True: 1.12k, False: 27]
  ------------------
  166|  1.15k|        if (b3 < 64) out[j++] = (uint8_t)((b2 << 6) | b3);
  ------------------
  |  Branch (166:13): [True: 735, False: 417]
  ------------------
  167|  1.15k|    }
  168|       |
  169|  1.15k|    return outLength;
  170|  1.15k|}
_ZN6Assimp6Base6410DecodeCharEc:
   66|   727k|inline uint8_t DecodeChar(char c) {
   67|   727k|    if (c & 0x80) {
  ------------------
  |  Branch (67:9): [True: 25, False: 727k]
  ------------------
   68|     25|        throw DeadlyImportError("Invalid base64 char value: ", size_t(c));
   69|     25|    }
   70|   727k|    return tableDecodeBase64[size_t(c & 0x7F)]; // TODO faster with lookup table or ifs?
   71|   727k|}

_ZN6Assimp12BaseImporterC2Ev:
   92|   246k|        : m_progress() {
   93|       |    // empty
   94|   246k|}
_ZN6Assimp12BaseImporter19UpdateImporterScaleEPNS_8ImporterE:
   96|  2.02k|void BaseImporter::UpdateImporterScale(Importer *pImp) {
   97|  2.02k|    ai_assert(pImp != nullptr);
   98|  2.02k|    ai_assert(importerScale != 0.0);
   99|  2.02k|    ai_assert(fileScale != 0.0);
  100|       |
  101|  2.02k|    double activeScale = importerScale * fileScale;
  102|       |
  103|       |    // Set active scaling
  104|  2.02k|    pImp->SetPropertyFloat(AI_CONFIG_APP_SCALE_KEY, static_cast<float>(activeScale));
  105|       |
  106|       |    ASSIMP_LOG_DEBUG("UpdateImporterScale scale set: ", activeScale);
  107|  2.02k|}
_ZN6Assimp12BaseImporter8ReadFileEPNS_8ImporterERKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEPNS_8IOSystemE:
  111|  3.86k|aiScene *BaseImporter::ReadFile(Importer *pImp, const std::string &pFile, IOSystem *pIOHandler) {
  112|       |
  113|  3.86k|    m_progress = pImp->GetProgressHandler();
  114|  3.86k|    if (nullptr == m_progress) {
  ------------------
  |  Branch (114:9): [True: 0, False: 3.86k]
  ------------------
  115|      0|        return nullptr;
  116|      0|    }
  117|       |
  118|  3.86k|    ai_assert(m_progress);
  119|       |
  120|       |    // Gather configuration properties for this run
  121|  3.86k|    SetupProperties(pImp);
  122|       |
  123|       |    // Construct a file system filter to improve our success ratio at reading external files
  124|  3.86k|    FileSystemFilter filter(pFile, pIOHandler);
  125|       |
  126|       |    // create a scene object to hold the data
  127|  3.86k|    std::unique_ptr<aiScene> sc(new aiScene());
  128|       |
  129|       |    // dispatch importing
  130|  3.86k|    try {
  131|  3.86k|        InternReadFile(pFile, sc.get(), &filter);
  132|       |
  133|       |        // Calculate import scale hook - required because pImp not available anywhere else
  134|       |        // passes scale into ScaleProcess
  135|  3.86k|        UpdateImporterScale(pImp);
  136|       |
  137|  3.86k|    } catch( const std::exception &err ) {
  138|       |        // extract error description
  139|  1.83k|        m_ErrorText = err.what();
  140|  1.83k|        ASSIMP_LOG_ERROR(err.what());
  141|  1.83k|        m_Exception = std::current_exception();
  142|  1.83k|        return nullptr;
  143|  1.83k|    }
  144|       |
  145|       |    // return what we gathered from the import.
  146|  2.02k|    return sc.release();
  147|  3.86k|}
_ZN6Assimp12BaseImporter15SetupPropertiesEPKNS_8ImporterE:
  150|    331|void BaseImporter::SetupProperties(const Importer *) {
  151|       |    // the default implementation does nothing
  152|    331|}
_ZN6Assimp12BaseImporter16GetExtensionListERNSt3__13setINS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEENS1_4lessIS8_EENS6_IS8_EEEE:
  155|  10.2k|void BaseImporter::GetExtensionList(std::set<std::string> &extensions) {
  156|  10.2k|    const aiImporterDesc *desc = GetInfo();
  157|  10.2k|    ai_assert(desc != nullptr);
  158|       |
  159|  10.2k|    const char *ext = desc->mFileExtensions;
  160|  10.2k|    ai_assert(ext != nullptr);
  161|       |
  162|  10.2k|    const char *last = ext;
  163|   112k|    do {
  164|   112k|        if (!*ext || *ext == ' ') {
  ------------------
  |  Branch (164:13): [True: 10.2k, False: 102k]
  |  Branch (164:22): [True: 15.3k, False: 87.2k]
  ------------------
  165|  25.6k|            extensions.insert(std::string(last, ext - last));
  166|  25.6k|            ai_assert(ext - last > 0);
  167|  25.6k|            last = ext;
  168|  41.0k|            while (*last == ' ') {
  ------------------
  |  Branch (168:20): [True: 15.3k, False: 25.6k]
  ------------------
  169|  15.3k|                ++last;
  170|  15.3k|            }
  171|  25.6k|        }
  172|   112k|    } while (*ext++);
  ------------------
  |  Branch (172:14): [True: 102k, False: 10.2k]
  ------------------
  173|  10.2k|}
_ZN6Assimp12BaseImporter12HasExtensionERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEERKNS1_3setIS7_NS1_4lessIS7_EENS5_IS7_EEEE:
  265|  10.2k|/*static*/ bool BaseImporter::HasExtension(const std::string &pFile, const std::set<std::string> &extensions) {
  266|  10.2k|    const std::string file = StripVersionHash(pFile);
  267|       |    // CAUTION: Do not just search for the extension!
  268|       |    // GetExtension() returns the part after the *last* dot, but some extensions
  269|       |    // have dots inside them, e.g. ogre.mesh.xml. Compare the entire end of the
  270|       |    // string.
  271|  20.5k|    for (const std::string& ext : extensions) {
  ------------------
  |  Branch (271:33): [True: 20.5k, False: 0]
  ------------------
  272|       |        // Yay for C++<20 not having std::string::ends_with()
  273|  20.5k|        const std::string dotExt = "." + ext;
  274|  20.5k|        if (dotExt.length() > file.length()) continue;
  ------------------
  |  Branch (274:13): [True: 0, False: 20.5k]
  ------------------
  275|       |        // Possible optimization: Fetch the lowercase filename!
  276|  20.5k|        if (0 == ASSIMP_stricmp(file.c_str() + file.length() - dotExt.length(), dotExt.c_str())) {
  ------------------
  |  Branch (276:13): [True: 10.2k, False: 10.2k]
  ------------------
  277|  10.2k|            return true;
  278|  10.2k|        }
  279|  20.5k|    }
  280|      0|    return false;
  281|  10.2k|}
_ZN6Assimp12BaseImporter12GetExtensionERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
  285|  6.07k|std::string BaseImporter::GetExtension(const std::string &pFile) {
  286|  6.07k|    const std::string file = StripVersionHash(pFile);
  287|  6.07k|    std::string::size_type pos = file.find_last_of('.');
  288|       |
  289|       |    // no file extension at all
  290|  6.07k|    if (pos == std::string::npos) {
  ------------------
  |  Branch (290:9): [True: 0, False: 6.07k]
  ------------------
  291|      0|        return std::string();
  292|      0|    }
  293|       |
  294|       |    // thanks to Andy Maloney for the hint
  295|  6.07k|    std::string ret = file.substr(pos + 1);
  296|  6.07k|    ret = ai_tolower(ret);
  297|       |
  298|  6.07k|    return ret;
  299|  6.07k|}
_ZN6Assimp12BaseImporter15CheckMagicTokenEPNS_8IOSystemERKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEPKvmjj:
  305|  16.3k|        const void *_magic, std::size_t num, unsigned int offset, unsigned int size) {
  306|  16.3k|    ai_assert(size <= 16);
  307|  16.3k|    ai_assert(_magic);
  308|       |
  309|  16.3k|    if (!pIOHandler) {
  ------------------
  |  Branch (309:9): [True: 0, False: 16.3k]
  ------------------
  310|      0|        return false;
  311|      0|    }
  312|  16.3k|    const char *magic = reinterpret_cast<const char *>(_magic);
  313|  16.3k|    std::unique_ptr<IOStream> pStream(pIOHandler->Open(pFile));
  314|  16.3k|    if (pStream) {
  ------------------
  |  Branch (314:9): [True: 16.3k, False: 0]
  ------------------
  315|       |
  316|       |        // skip to offset
  317|  16.3k|        pStream->Seek(offset, aiOrigin_SET);
  318|       |
  319|       |        // read 'size' characters from the file
  320|  16.3k|        union {
  321|  16.3k|            char data[16];
  322|  16.3k|            uint16_t data_u16[8];
  323|  16.3k|            uint32_t data_u32[4];
  324|  16.3k|        };
  325|  16.3k|        if (size != pStream->Read(data, 1, size)) {
  ------------------
  |  Branch (325:13): [True: 0, False: 16.3k]
  ------------------
  326|      0|            return false;
  327|      0|        }
  328|       |
  329|  27.2k|        for (unsigned int i = 0; i < num; ++i) {
  ------------------
  |  Branch (329:34): [True: 16.3k, False: 10.9k]
  ------------------
  330|       |            // also check against big endian versions of tokens with size 2,4
  331|       |            // that's just for convenience, the chance that we cause conflicts
  332|       |            // is quite low and it can save some lines and prevent nasty bugs
  333|  16.3k|            if (2 == size) {
  ------------------
  |  Branch (333:17): [True: 0, False: 16.3k]
  ------------------
  334|      0|                uint16_t magic_u16;
  335|      0|                memcpy(&magic_u16, magic, 2);
  336|      0|                if (data_u16[0] == magic_u16 || data_u16[0] == ByteSwap::Swapped(magic_u16)) {
  ------------------
  |  Branch (336:21): [True: 0, False: 0]
  |  Branch (336:49): [True: 0, False: 0]
  ------------------
  337|      0|                    return true;
  338|      0|                }
  339|  16.3k|            } else if (4 == size) {
  ------------------
  |  Branch (339:24): [True: 16.3k, False: 0]
  ------------------
  340|  16.3k|                uint32_t magic_u32;
  341|  16.3k|                memcpy(&magic_u32, magic, 4);
  342|  16.3k|                if (data_u32[0] == magic_u32 || data_u32[0] == ByteSwap::Swapped(magic_u32)) {
  ------------------
  |  Branch (342:21): [True: 5.41k, False: 10.9k]
  |  Branch (342:49): [True: 0, False: 10.9k]
  ------------------
  343|  5.41k|                    return true;
  344|  5.41k|                }
  345|  16.3k|            } else {
  346|       |                // any length ... just compare
  347|      0|                if (!memcmp(magic, data, size)) {
  ------------------
  |  Branch (347:21): [True: 0, False: 0]
  ------------------
  348|      0|                    return true;
  349|      0|                }
  350|      0|            }
  351|  10.9k|            magic += size;
  352|  10.9k|        }
  353|  16.3k|    }
  354|  10.9k|    return false;
  355|  16.3k|}
BaseImporter.cpp:_ZN12_GLOBAL__N_116StripVersionHashERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
   75|  16.3k|std::string StripVersionHash(const std::string &filename) {
   76|  16.3k|    const std::string::size_type pos = filename.find_last_of('#');
   77|       |    // Only strip if the hash is behind a possible file extension and the part
   78|       |    // behind the hash is a version string.
   79|  16.3k|    if (pos != std::string::npos && pos > filename.find_last_of('.') &&
  ------------------
  |  Branch (79:9): [True: 0, False: 16.3k]
  |  Branch (79:9): [True: 0, False: 16.3k]
  |  Branch (79:37): [True: 0, False: 0]
  ------------------
   80|      0|        IsGcsVersion(filename.substr(pos + 1))) {
  ------------------
  |  Branch (80:9): [True: 0, False: 0]
  ------------------
   81|      0|        return filename.substr(0, pos);
   82|      0|    }
   83|  16.3k|    return filename;
   84|  16.3k|}

_ZN6Assimp11BaseProcessC2Ev:
   56|   171k|          progress() {
   57|       |    // empty
   58|   171k|}
_ZN6Assimp11BaseProcess14ExecuteOnSceneEPNS_8ImporterE:
   61|  24.8k|void BaseProcess::ExecuteOnScene(Importer *pImp) {
   62|  24.8k|    ai_assert( nullptr != pImp );
   63|  24.8k|    if (pImp == nullptr) {
  ------------------
  |  Branch (63:9): [True: 0, False: 24.8k]
  ------------------
   64|      0|        return;
   65|      0|    }
   66|       |
   67|  24.8k|    ai_assert(nullptr != pImp->Pimpl()->mScene);
   68|  24.8k|    if (pImp->Pimpl()->mScene == nullptr) {
  ------------------
  |  Branch (68:9): [True: 0, False: 24.8k]
  ------------------
   69|      0|        return;
   70|      0|    }
   71|       |
   72|  24.8k|    progress = pImp->GetProgressHandler();
   73|  24.8k|    ai_assert(nullptr != progress);
   74|  24.8k|    if (progress == nullptr) {
  ------------------
  |  Branch (74:9): [True: 0, False: 24.8k]
  ------------------
   75|      0|        return;
   76|      0|    }
   77|       |
   78|  24.8k|    SetupProperties(pImp);
   79|       |
   80|       |    // catch exceptions thrown inside the PostProcess-Step
   81|  24.8k|    try {
   82|  24.8k|        Execute(pImp->Pimpl()->mScene);
   83|  24.8k|    } catch (const std::exception &err) {
   84|       |
   85|       |        // extract error description
   86|    526|        pImp->Pimpl()->mErrorString = err.what();
   87|    526|        ASSIMP_LOG_ERROR(pImp->Pimpl()->mErrorString);
   88|       |
   89|       |        // and kill the partially imported data
   90|    526|        delete pImp->Pimpl()->mScene;
   91|    526|        pImp->Pimpl()->mScene = nullptr;
   92|    526|    }
   93|  24.8k|}
_ZN6Assimp11BaseProcess15SetupPropertiesEPKNS_8ImporterE:
   96|  9.63k|void BaseProcess::SetupProperties(const Importer * /*pImp*/) {
   97|       |    // the default implementation does nothing
   98|  9.63k|}

_ZN6Assimp11BaseProcess13SetSharedDataEPNS_21SharedPostProcessInfoE:
  234|   169k|    inline void SetSharedData(SharedPostProcessInfo *sh) {
  235|   169k|        shared = sh;
  236|   169k|    }
_ZN6Assimp21SharedPostProcessInfoD2Ev:
   98|  5.13k|    ~SharedPostProcessInfo() {
   99|  5.13k|        Clean();
  100|  5.13k|    }
_ZN6Assimp11BaseProcessD2Ev:
  186|   171k|    virtual ~BaseProcess() = default;
_ZN6Assimp21SharedPostProcessInfo5CleanEv:
  103|  10.0k|    void Clean() {
  104|       |        // invoke the virtual destructor for all stored properties
  105|  10.0k|        for (PropertyMap::iterator it = pmap.begin(), end = pmap.end();
  106|  10.0k|                it != end; ++it) {
  ------------------
  |  Branch (106:17): [True: 0, False: 10.0k]
  ------------------
  107|      0|            delete (*it).second;
  108|      0|        }
  109|  10.0k|        pmap.clear();
  110|  10.0k|    }
_ZN6Assimp21SharedPostProcessInfo14RemovePropertyEPKc:
  148|  1.50k|    void RemoveProperty(const char *name) {
  149|  1.50k|        SetGenericPropertyPtr<Base>(pmap, name, nullptr );
  150|  1.50k|    }
_ZN6Assimp21SharedPostProcessInfo11AddPropertyEPKcPNS0_4BaseE:
  153|  1.50k|    void AddProperty(const char *name, Base *data) {
  154|  1.50k|        SetGenericPropertyPtr<Base>(pmap, name, data);
  155|  1.50k|    }
_ZNK6Assimp21SharedPostProcessInfo19GetPropertyInternalEPKc:
  157|    804|    Base *GetPropertyInternal(const char *name) const {
  158|    804|        return GetGenericProperty<Base *>(pmap, name, nullptr );
  159|    804|    }
_ZN6Assimp21SharedPostProcessInfo11AddPropertyINSt3__16vectorINS2_4pairINS_11SpatialSortEfEENS2_9allocatorIS6_EEEEEEvPKcPT_:
  114|  1.50k|    void AddProperty(const char *name, T *in) {
  115|  1.50k|        AddProperty(name, (Base *)new THeapData<T>(in));
  116|  1.50k|    }
_ZN6Assimp21SharedPostProcessInfo9THeapDataINSt3__16vectorINS2_4pairINS_11SpatialSortEfEENS2_9allocatorIS6_EEEEEC2EPS9_:
   73|  1.50k|                data(in) {}
_ZN6Assimp21SharedPostProcessInfo4BaseD2Ev:
   66|  1.50k|        virtual ~Base() = default;
_ZN6Assimp21SharedPostProcessInfo9THeapDataINSt3__16vectorINS2_4pairINS_11SpatialSortEfEENS2_9allocatorIS6_EEEEED2Ev:
   75|  1.50k|        ~THeapData() override {
   76|  1.50k|            delete data;
   77|  1.50k|        }
_ZNK6Assimp21SharedPostProcessInfo11GetPropertyINSt3__16vectorINS2_4pairINS_11SpatialSortEfEENS2_9allocatorIS6_EEEEEEbPKcRPT_:
  126|    804|    bool GetProperty(const char *name, T *&out) const {
  127|    804|        THeapData<T> *t = (THeapData<T> *)GetPropertyInternal(name);
  128|    804|        if (!t) {
  ------------------
  |  Branch (128:13): [True: 0, False: 804]
  ------------------
  129|      0|            out = nullptr;
  130|      0|            return false;
  131|      0|        }
  132|    804|        out = t->data;
  133|    804|        return true;
  134|    804|    }

_ZN6Assimp16aiCreateAnimMeshEPK6aiMeshbbbbb:
   48|     22|{
   49|     22|    aiAnimMesh *animesh = new aiAnimMesh;
   50|     22|    animesh->mNumVertices = mesh->mNumVertices;
   51|     22|    if (needPositions && mesh->mVertices) {
  ------------------
  |  Branch (51:9): [True: 0, False: 22]
  |  Branch (51:26): [True: 0, False: 0]
  ------------------
   52|      0|        animesh->mVertices = new aiVector3D[animesh->mNumVertices];
   53|      0|        std::memcpy(animesh->mVertices, mesh->mVertices, mesh->mNumVertices * sizeof(aiVector3D));
   54|      0|    }
   55|     22|    if (needNormals && mesh->mNormals) {
  ------------------
  |  Branch (55:9): [True: 0, False: 22]
  |  Branch (55:24): [True: 0, False: 0]
  ------------------
   56|      0|        animesh->mNormals = new aiVector3D[animesh->mNumVertices];
   57|      0|        std::memcpy(animesh->mNormals, mesh->mNormals, mesh->mNumVertices * sizeof(aiVector3D));
   58|      0|    }
   59|     22|    if (needTangents && mesh->mTangents) {
  ------------------
  |  Branch (59:9): [True: 0, False: 22]
  |  Branch (59:25): [True: 0, False: 0]
  ------------------
   60|      0|        animesh->mTangents = new aiVector3D[animesh->mNumVertices];
   61|      0|        std::memcpy(animesh->mTangents, mesh->mTangents, mesh->mNumVertices * sizeof(aiVector3D));
   62|      0|    }
   63|     22|    if (needTangents && mesh->mBitangents) {
  ------------------
  |  Branch (63:9): [True: 0, False: 22]
  |  Branch (63:25): [True: 0, False: 0]
  ------------------
   64|      0|        animesh->mBitangents = new aiVector3D[animesh->mNumVertices];
   65|      0|        std::memcpy(animesh->mBitangents, mesh->mBitangents, mesh->mNumVertices * sizeof(aiVector3D));
   66|      0|    }
   67|       |
   68|     22|    if (needColors) {
  ------------------
  |  Branch (68:9): [True: 0, False: 22]
  ------------------
   69|      0|        for (int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) {
  ------------------
  |  Branch (69:25): [True: 0, False: 0]
  ------------------
   70|      0|            if (mesh->mColors[i]) {
  ------------------
  |  Branch (70:17): [True: 0, False: 0]
  ------------------
   71|      0|                animesh->mColors[i] = new aiColor4D[animesh->mNumVertices];
   72|      0|                std::memcpy(animesh->mColors[i], mesh->mColors[i], mesh->mNumVertices * sizeof(aiColor4D));
   73|      0|            } else {
   74|      0|                animesh->mColors[i] = nullptr;
   75|      0|            }
   76|      0|        }
   77|      0|    }
   78|       |
   79|     22|    if (needTexCoords) {
  ------------------
  |  Branch (79:9): [True: 0, False: 22]
  ------------------
   80|      0|        for (int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
  ------------------
  |  Branch (80:25): [True: 0, False: 0]
  ------------------
   81|      0|            if (mesh->mTextureCoords[i]) {
  ------------------
  |  Branch (81:17): [True: 0, False: 0]
  ------------------
   82|      0|                animesh->mTextureCoords[i] = new aiVector3D[animesh->mNumVertices];
   83|      0|                std::memcpy(animesh->mTextureCoords[i], mesh->mTextureCoords[i], mesh->mNumVertices * sizeof(aiVector3D));
   84|      0|            } else {
   85|      0|                animesh->mTextureCoords[i] = nullptr;
   86|      0|            }
   87|      0|        }
   88|      0|    }
   89|     22|    return animesh;
   90|     22|}

_ZNK6Assimp15DefaultIOSystem6ExistsEPKc:
   95|   426k|bool DefaultIOSystem::Exists(const char *pFile) const {
   96|   426k|    if (pFile == nullptr) {
  ------------------
  |  Branch (96:9): [True: 0, False: 426k]
  ------------------
   97|      0|        return false;
   98|      0|    }
   99|       |
  100|       |#ifdef _WIN32
  101|       |    struct __stat64 filestat;
  102|       |    if (_wstat64(Utf8ToWide(pFile).c_str(), &filestat) != 0) {
  103|       |        return false;
  104|       |    }
  105|       |#else
  106|   426k|	struct stat statbuf;
  107|   426k|    if (stat(pFile, &statbuf) != 0) {
  ------------------
  |  Branch (107:9): [True: 423k, False: 3.25k]
  ------------------
  108|   423k|        return false;
  109|   423k|    }
  110|       |    // test for a regular file
  111|  3.25k|    if (!S_ISREG(statbuf.st_mode)) {
  ------------------
  |  Branch (111:9): [True: 3.25k, False: 0]
  ------------------
  112|  3.25k|        return false;
  113|  3.25k|    }
  114|      0|#endif
  115|       |
  116|      0|    return true;
  117|  3.25k|}
_ZN6Assimp15DefaultIOSystem4OpenEPKcS2_:
  121|    774|IOStream *DefaultIOSystem::Open(const char *strFile, const char *strMode) {
  122|    774|    ai_assert(strFile != nullptr);
  123|    774|    ai_assert(strMode != nullptr);
  124|    774|    FILE *file;
  125|       |
  126|       |#ifdef _WIN32
  127|       |    std::wstring name = Utf8ToWide(strFile);
  128|       |    if (name.empty()) {
  129|       |        return nullptr;
  130|       |    }
  131|       |
  132|       |    file = ::_wfopen(name.c_str(), Utf8ToWide(strMode).c_str());
  133|       |#else
  134|    774|    file = ::fopen(strFile, strMode);
  135|    774|#endif
  136|       |
  137|    774|    if (!file) {
  ------------------
  |  Branch (137:9): [True: 774, False: 0]
  ------------------
  138|    774|        return nullptr;
  139|    774|    }
  140|       |
  141|      0|    return new DefaultIOStream(file, strFile);
  142|    774|}
_ZNK6Assimp15DefaultIOSystem14getOsSeparatorEv:
  152|  14.1k|char DefaultIOSystem::getOsSeparator() const {
  153|  14.1k|#ifndef _WIN32
  154|  14.1k|    return '/';
  155|       |#else
  156|       |    return '\\';
  157|       |#endif
  158|  14.1k|}

_ZN6Assimp6Logger5debugEPKc:
  166|  79.5k|void Logger::debug(const char *message) {
  167|       |
  168|       |    // SECURITY FIX: otherwise it's easy to produce overruns since
  169|       |    // sometimes importers will include data from the input file
  170|       |    // (i.e. node names) in their messages.
  171|  79.5k|    if (strlen(message) > MAX_LOG_MESSAGE_LENGTH) {
  ------------------
  |  Branch (171:9): [True: 0, False: 79.5k]
  ------------------
  172|      0|        return OnDebug("<fixme: long message discarded>");
  173|      0|    }
  174|  79.5k|    return OnDebug(message);
  175|  79.5k|}
_ZN6Assimp6Logger12verboseDebugEPKc:
  178|    109|void Logger::verboseDebug(const char *message) {
  179|       |
  180|       |    // SECURITY FIX: see above
  181|    109|    if (strlen(message) > MAX_LOG_MESSAGE_LENGTH) {
  ------------------
  |  Branch (181:9): [True: 0, False: 109]
  ------------------
  182|      0|        return OnVerboseDebug("<fixme: long message discarded>");
  183|      0|    }
  184|    109|    return OnVerboseDebug(message);
  185|    109|}
_ZN6Assimp6Logger4infoEPKc:
  188|   269k|void Logger::info(const char *message) {
  189|       |
  190|       |    // SECURITY FIX: see above
  191|   269k|    if (strlen(message) > MAX_LOG_MESSAGE_LENGTH) {
  ------------------
  |  Branch (191:9): [True: 0, False: 269k]
  ------------------
  192|      0|        return OnInfo("<fixme: long message discarded>");
  193|      0|    }
  194|   269k|    return OnInfo(message);
  195|   269k|}
_ZN6Assimp6Logger4warnEPKc:
  198|  4.03k|void Logger::warn(const char *message) {
  199|       |
  200|       |    // SECURITY FIX: see above
  201|  4.03k|    if (strlen(message) > MAX_LOG_MESSAGE_LENGTH) {
  ------------------
  |  Branch (201:9): [True: 0, False: 4.03k]
  ------------------
  202|      0|        return OnWarn("<fixme: long message discarded>");
  203|      0|    }
  204|  4.03k|    return OnWarn(message);
  205|  4.03k|}
_ZN6Assimp6Logger5errorEPKc:
  208|  6.21k|void Logger::error(const char *message) {
  209|       |    // SECURITY FIX: see above
  210|  6.21k|    if (strlen(message) > MAX_LOG_MESSAGE_LENGTH) {
  ------------------
  |  Branch (210:9): [True: 110, False: 6.10k]
  ------------------
  211|    110|        return OnError("<fixme: long message discarded>");
  212|    110|    }
  213|  6.10k|    return OnError(message);
  214|  6.21k|}
_ZN6Assimp13DefaultLogger12isNullLoggerEv:
  232|  9.47k|bool DefaultLogger::isNullLogger() {
  233|  9.47k|    return m_pLogger == &s_pNullLogger;
  234|  9.47k|}
_ZN6Assimp13DefaultLogger3getEv:
  237|   359k|Logger *DefaultLogger::get() {
  238|   359k|    return m_pLogger;
  239|   359k|}

_ZN6Assimp22DefaultProgressHandler6UpdateEf:
   59|  59.6k|    bool Update(float) override {
   60|  59.6k|        return false;
   61|  59.6k|    }

_ZN15DeadlyErrorBaseC2EN6Assimp9Formatter15basic_formatterIcNSt3__111char_traitsIcEENS3_9allocatorIcEEEE:
   52|  8.71k|        runtime_error(std::string(f)){}

_ZN6Assimp16FileSystemFilterC2ERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEPNS_8IOSystemE:
   68|  3.86k|    : mWrapped  (old)
   69|  3.86k|    , mSrc_file(file)
   70|  3.86k|    , mSep(mWrapped->getOsSeparator()) {
   71|  3.86k|        ai_assert(nullptr != mWrapped);
   72|       |
   73|       |        // Determine base directory
   74|  3.86k|        mBase = mSrc_file;
   75|  3.86k|        std::string::size_type ss2;
   76|  3.86k|        if (std::string::npos != (ss2 = mBase.find_last_of("\\/")))  {
  ------------------
  |  Branch (76:13): [True: 0, False: 3.86k]
  ------------------
   77|      0|            mBase.erase(ss2,mBase.length()-ss2);
   78|  3.86k|        } else {
   79|  3.86k|            mBase = std::string();
   80|  3.86k|        }
   81|       |
   82|       |        // make sure the directory is terminated properly
   83|  3.86k|        char s;
   84|       |
   85|  3.86k|        if ( mBase.empty() ) {
  ------------------
  |  Branch (85:14): [True: 3.86k, False: 0]
  ------------------
   86|  3.86k|            mBase = ".";
   87|  3.86k|            mBase += getOsSeparator();
   88|  3.86k|        } else if ((s = *(mBase.end()-1)) != '\\' && s != '/') {
  ------------------
  |  Branch (88:20): [True: 0, False: 0]
  |  Branch (88:20): [True: 0, False: 0]
  |  Branch (88:54): [True: 0, False: 0]
  ------------------
   89|      0|            mBase += getOsSeparator();
   90|      0|        }
   91|       |
   92|  3.86k|        DefaultLogger::get()->info("Import root directory is \'", mBase, "\'");
   93|  3.86k|    }
_ZNK6Assimp16FileSystemFilter9BuildPathERNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
  222|    500|    void BuildPath (std::string& in) const {
  223|    500|        ai_assert( nullptr != mWrapped );
  224|       |        // if we can already access the file, great.
  225|    500|        if (in.length() < 3 || mWrapped->Exists(in)) {
  ------------------
  |  Branch (225:13): [True: 2, False: 498]
  |  Branch (225:32): [True: 0, False: 498]
  ------------------
  226|      2|            return;
  227|      2|        }
  228|       |
  229|       |        // Determine whether this is a relative path (Windows-specific - most assets are packaged on Windows).
  230|    498|        if (in[1] != ':') {
  ------------------
  |  Branch (230:13): [True: 488, False: 10]
  ------------------
  231|       |
  232|       |            // append base path and try
  233|    488|            const std::string tmp = mBase + in;
  234|    488|            if (mWrapped->Exists(tmp)) {
  ------------------
  |  Branch (234:17): [True: 0, False: 488]
  ------------------
  235|      0|                in = tmp;
  236|      0|                return;
  237|      0|            }
  238|    488|        }
  239|       |
  240|       |        // Chop of the file name and look in the model directory, if
  241|       |        // this fails try all sub paths of the given path, i.e.
  242|       |        // if the given path is foo/bar/something.lwo, try
  243|       |        // <base>/something.lwo
  244|       |        // <base>/bar/something.lwo
  245|       |        // <base>/foo/bar/something.lwo
  246|    498|        std::string::size_type pos = in.rfind('/');
  247|    498|        if (std::string::npos == pos) {
  ------------------
  |  Branch (247:13): [True: 49, False: 449]
  ------------------
  248|     49|            pos = in.rfind('\\');
  249|     49|        }
  250|       |
  251|    498|        if (std::string::npos != pos)   {
  ------------------
  |  Branch (251:13): [True: 455, False: 43]
  ------------------
  252|    455|            std::string tmp;
  253|    455|            std::string::size_type last_dirsep = std::string::npos;
  254|       |
  255|   426k|            while(true) {
  ------------------
  |  Branch (255:19): [True: 426k, Folded]
  ------------------
  256|   426k|                tmp = mBase;
  257|   426k|                tmp += mSep;
  258|       |
  259|   426k|                std::string::size_type dirsep = in.rfind('/', last_dirsep);
  260|   426k|                if (std::string::npos == dirsep) {
  ------------------
  |  Branch (260:21): [True: 579, False: 425k]
  ------------------
  261|    579|                    dirsep = in.rfind('\\', last_dirsep);
  262|    579|                }
  263|       |
  264|   426k|                if (std::string::npos == dirsep || dirsep == 0) {
  ------------------
  |  Branch (264:21): [True: 449, False: 425k]
  |  Branch (264:52): [True: 6, False: 425k]
  ------------------
  265|       |                    // we did try this already.
  266|    455|                    break;
  267|    455|                }
  268|       |
  269|   425k|                last_dirsep = dirsep-1;
  270|       |
  271|   425k|                tmp += in.substr(dirsep+1, in.length()-pos);
  272|   425k|                if (mWrapped->Exists(tmp)) {
  ------------------
  |  Branch (272:21): [True: 0, False: 425k]
  ------------------
  273|      0|                    in = tmp;
  274|      0|                    return;
  275|      0|                }
  276|   425k|            }
  277|    455|        }
  278|       |
  279|       |        // hopefully the underlying file system has another few tricks to access this file ...
  280|    498|    }
_ZNK6Assimp16FileSystemFilter7CleanupERNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
  285|    250|    void Cleanup (std::string& in) const {
  286|    250|        if(in.empty()) {
  ------------------
  |  Branch (286:12): [True: 0, False: 250]
  ------------------
  287|      0|            return;
  288|      0|        }
  289|       |
  290|       |        // Remove a very common issue when we're parsing file names: spaces at the
  291|       |        // beginning of the path.
  292|    250|        char last = 0;
  293|    250|        std::string::iterator it = in.begin();
  294|    304|        while (IsSpaceOrNewLine( *it ))++it;
  ------------------
  |  Branch (294:16): [True: 54, False: 250]
  ------------------
  295|    250|        if (it != in.begin()) {
  ------------------
  |  Branch (295:13): [True: 16, False: 234]
  ------------------
  296|     16|            in.erase(in.begin(),it+1);
  297|     16|        }
  298|       |
  299|    250|        const char separator = getOsSeparator();
  300|  3.52M|        for (it = in.begin(); it < in.end(); ++it) {
  ------------------
  |  Branch (300:31): [True: 3.52M, False: 250]
  ------------------
  301|  3.52M|            const size_t remaining = std::distance(in.end(), it);
  302|       |            // Exclude :// and \\, which remain untouched.
  303|       |            // https://sourceforge.net/tracker/?func=detail&aid=3031725&group_id=226462&atid=1067632
  304|  3.52M|            if (remaining >= 3u && !strncmp(&*it, "://", 3 )) {
  ------------------
  |  Branch (304:17): [True: 3.52M, False: 0]
  |  Branch (304:36): [True: 119, False: 3.52M]
  ------------------
  305|    119|                it += 3;
  306|    119|                continue;
  307|    119|            }
  308|  3.52M|            if (it == in.begin() && remaining >= 2 && !strncmp(&*it, "\\\\", 2)) {
  ------------------
  |  Branch (308:17): [True: 250, False: 3.52M]
  |  Branch (308:17): [True: 0, False: 3.52M]
  |  Branch (308:37): [True: 250, False: 0]
  |  Branch (308:55): [True: 0, False: 250]
  ------------------
  309|      0|                it += 2;
  310|      0|                continue;
  311|      0|            }
  312|       |
  313|       |            // Cleanup path delimiters
  314|  3.52M|            if (*it == '/' || (*it) == '\\') {
  ------------------
  |  Branch (314:17): [True: 214k, False: 3.30M]
  |  Branch (314:31): [True: 132, False: 3.30M]
  ------------------
  315|   214k|                *it = separator;
  316|       |
  317|       |                // And we're removing double delimiters, frequent issue with
  318|       |                // incorrectly composited paths ...
  319|   214k|                if (last == *it) {
  ------------------
  |  Branch (319:21): [True: 3.99k, False: 210k]
  ------------------
  320|  3.99k|                    it = in.erase(it);
  321|  3.99k|                    --it;
  322|  3.99k|                }
  323|  3.30M|            } else if (*it == '%' && in.end() - it > 2) {
  ------------------
  |  Branch (323:24): [True: 1.18k, False: 3.30M]
  |  Branch (323:24): [True: 1.17k, False: 3.30M]
  |  Branch (323:38): [True: 1.17k, False: 5]
  ------------------
  324|       |                // Hex sequence in URIs
  325|  1.17k|                if( IsHex((&*it)[0]) && IsHex((&*it)[1]) ) {
  ------------------
  |  Branch (325:21): [True: 0, False: 1.17k]
  |  Branch (325:41): [True: 0, False: 0]
  ------------------
  326|      0|                    *it = HexOctetToDecimal(&*it);
  327|      0|                    it = in.erase(it+1,it+2);
  328|      0|                    --it;
  329|      0|                }
  330|  1.17k|            }
  331|       |
  332|  3.52M|            last = *it;
  333|  3.52M|        }
  334|    250|    }
_ZN6Assimp5IsHexEc:
   56|  1.17k|inline bool IsHex(char s) {
   57|  1.17k|    return (s>='0' && s<='9') || (s>='a' && s<='f') || (s>='A' && s<='F');
  ------------------
  |  Branch (57:13): [True: 0, False: 1.17k]
  |  Branch (57:23): [True: 0, False: 0]
  |  Branch (57:35): [True: 0, False: 1.17k]
  |  Branch (57:45): [True: 0, False: 0]
  |  Branch (57:57): [True: 0, False: 1.17k]
  |  Branch (57:67): [True: 0, False: 0]
  ------------------
   58|  1.17k|}
_ZNK6Assimp16FileSystemFilter14getOsSeparatorEv:
  116|  4.11k|    char getOsSeparator() const {
  117|  4.11k|        return mSep;
  118|  4.11k|    }
_ZN6Assimp16FileSystemFilter4OpenEPKcS2_:
  122|  7.99k|    IOStream* Open( const char* pFile, const char* pMode = "rb") {
  123|  7.99k|        ai_assert( nullptr != mWrapped );
  124|  7.99k|        if ( nullptr == pFile || nullptr == pMode ) {
  ------------------
  |  Branch (124:14): [True: 0, False: 7.99k]
  |  Branch (124:34): [True: 0, False: 7.99k]
  ------------------
  125|      0|            return nullptr;
  126|      0|        }
  127|       |
  128|  7.99k|        ai_assert( nullptr != pFile );
  129|  7.99k|        ai_assert( nullptr != pMode );
  130|       |
  131|       |        // First try the unchanged path
  132|  7.99k|        IOStream* s = mWrapped->Open(pFile,pMode);
  133|       |
  134|  7.99k|        if (nullptr == s) {
  ------------------
  |  Branch (134:13): [True: 250, False: 7.74k]
  ------------------
  135|    250|            std::string tmp = pFile;
  136|       |
  137|       |            // Try to convert between absolute and relative paths
  138|    250|            BuildPath(tmp);
  139|    250|            s = mWrapped->Open(tmp,pMode);
  140|       |
  141|    250|            if (nullptr == s) {
  ------------------
  |  Branch (141:17): [True: 250, False: 0]
  ------------------
  142|       |                // Finally, look for typical issues with paths
  143|       |                // and try to correct them. This is our last
  144|       |                // resort.
  145|    250|                tmp = pFile;
  146|    250|                Cleanup(tmp);
  147|    250|                BuildPath(tmp);
  148|    250|                s = mWrapped->Open(tmp,pMode);
  149|    250|            }
  150|    250|        }
  151|       |
  152|  7.99k|        return s;
  153|  7.99k|    }
_ZN6Assimp16FileSystemFilterD2Ev:
   96|  3.86k|    ~FileSystemFilter() = default;

_ZN6Assimp6Intern22AllocateFromAssimpHeapnwEm:
  114|  51.9k|void* AllocateFromAssimpHeap::operator new ( size_t num_bytes)  {
  115|  51.9k|    return ::operator new(num_bytes);
  116|  51.9k|}
_ZN6Assimp6Intern22AllocateFromAssimpHeapdlEPv:
  127|  51.9k|void AllocateFromAssimpHeap::operator delete ( void* data)  {
  128|  51.9k|    return ::operator delete(data);
  129|  51.9k|}
_ZN6Assimp8ImporterC2Ev:
  150|  5.13k| : pimpl( new ImporterPimpl ) {
  151|  5.13k|    pimpl->mScene = nullptr;
  152|  5.13k|    pimpl->mErrorString = std::string();
  153|       |
  154|       |    // Allocate a default IO handler
  155|  5.13k|    pimpl->mIOHandler = new DefaultIOSystem;
  156|  5.13k|    pimpl->mIsDefaultHandler = true;
  157|  5.13k|    pimpl->bExtraVerbose     = false; // disable extra verbose mode by default
  158|       |
  159|  5.13k|    pimpl->mProgressHandler = new DefaultProgressHandler();
  160|  5.13k|    pimpl->mIsDefaultProgressHandler = true;
  161|       |
  162|  5.13k|    GetImporterInstanceList(pimpl->mImporter);
  163|  5.13k|    GetPostProcessingStepInstanceList(pimpl->mPostProcessingSteps);
  164|       |
  165|       |    // Allocate a SharedPostProcessInfo object and store pointers to it in all post-process steps in the list.
  166|  5.13k|    pimpl->mPPShared = new SharedPostProcessInfo();
  167|  5.13k|    for (std::vector<BaseProcess*>::iterator it =  pimpl->mPostProcessingSteps.begin();
  168|   174k|        it != pimpl->mPostProcessingSteps.end();
  ------------------
  |  Branch (168:9): [True: 169k, False: 5.13k]
  ------------------
  169|   169k|        ++it)   {
  170|       |
  171|   169k|        (*it)->SetSharedData(pimpl->mPPShared);
  172|   169k|    }
  173|  5.13k|}
_ZN6Assimp8ImporterD2Ev:
  177|  5.13k|Importer::~Importer() {
  178|       |    // Delete all import plugins
  179|  5.13k|	DeleteImporterInstanceList(pimpl->mImporter);
  180|       |
  181|       |    // Delete all post-processing plug-ins
  182|   174k|    for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); ++a ) {
  ------------------
  |  Branch (182:30): [True: 169k, False: 5.13k]
  ------------------
  183|   169k|        delete pimpl->mPostProcessingSteps[a];
  184|   169k|    }
  185|       |
  186|       |    // Delete the assigned IO and progress handler
  187|  5.13k|    delete pimpl->mIOHandler;
  188|  5.13k|    delete pimpl->mProgressHandler;
  189|       |
  190|       |    // Kill imported scene. Destructor's should do that recursively
  191|  5.13k|    delete pimpl->mScene;
  192|       |
  193|       |    // Delete shared post-processing data
  194|  5.13k|    delete pimpl->mPPShared;
  195|       |
  196|       |    // and finally the pimpl itself
  197|  5.13k|    delete pimpl;
  198|  5.13k|}
_ZN6Assimp8Importer16UnregisterLoaderEPNS_12BaseImporterE:
  251|   236k|aiReturn Importer::UnregisterLoader(BaseImporter* pImp) {
  252|   236k|    if(!pImp) {
  ------------------
  |  Branch (252:8): [True: 0, False: 236k]
  ------------------
  253|       |        // unregistering a nullptr importer is no problem for us ... really!
  254|      0|        return AI_SUCCESS;
  255|      0|    }
  256|       |
  257|   236k|    ASSIMP_BEGIN_EXCEPTION_REGION();
  258|   236k|    std::vector<BaseImporter*>::iterator it = std::find(pimpl->mImporter.begin(),
  259|   236k|        pimpl->mImporter.end(),pImp);
  260|       |
  261|   236k|    if (it != pimpl->mImporter.end())   {
  ------------------
  |  Branch (261:9): [True: 236k, False: 0]
  ------------------
  262|   236k|        pimpl->mImporter.erase(it);
  263|   236k|        ASSIMP_LOG_INFO("Unregistering custom importer: ");
  264|   236k|        return AI_SUCCESS;
  265|   236k|    }
  266|   236k|    ASSIMP_LOG_WARN("Unable to remove custom importer: I can't find you ...");
  267|      0|    ASSIMP_END_EXCEPTION_REGION(aiReturn);
  268|       |
  269|       |    return AI_FAILURE;
  270|   236k|}
_ZN6Assimp8Importer12SetIOHandlerEPNS_8IOSystemE:
  297|  10.2k|void Importer::SetIOHandler( IOSystem* pIOHandler) {
  298|  10.2k|    ai_assert(nullptr != pimpl);
  299|       |
  300|  10.2k|    ASSIMP_BEGIN_EXCEPTION_REGION();
  301|       |    // If the new handler is zero, allocate a default IO implementation.
  302|  10.2k|    if (!pIOHandler) {
  ------------------
  |  Branch (302:9): [True: 0, False: 10.2k]
  ------------------
  303|       |        // Release pointer in the possession of the caller
  304|      0|        pimpl->mIOHandler = new DefaultIOSystem();
  305|      0|        pimpl->mIsDefaultHandler = true;
  306|  10.2k|    } else if (pimpl->mIOHandler != pIOHandler) { // Otherwise register the custom handler
  ------------------
  |  Branch (306:16): [True: 10.2k, False: 0]
  ------------------
  307|  10.2k|        delete pimpl->mIOHandler;
  308|  10.2k|        pimpl->mIOHandler = pIOHandler;
  309|  10.2k|        pimpl->mIsDefaultHandler = false;
  310|  10.2k|    }
  311|  10.2k|    ASSIMP_END_EXCEPTION_REGION(void);
  312|  10.2k|}
_ZNK6Assimp8Importer18GetProgressHandlerEv:
  352|  28.7k|ProgressHandler* Importer::GetProgressHandler() const {
  353|  28.7k|    ai_assert(nullptr != pimpl);
  354|       |
  355|  28.7k|    return pimpl->mProgressHandler;
  356|  28.7k|}
_Z14_ValidateFlagsj:
  368|  1.54k|bool _ValidateFlags(unsigned int pFlags) {
  369|  1.54k|    if (pFlags & aiProcess_GenSmoothNormals && pFlags & aiProcess_GenNormals)   {
  ------------------
  |  Branch (369:9): [True: 1.54k, False: 0]
  |  Branch (369:48): [True: 0, False: 1.54k]
  ------------------
  370|      0|        ASSIMP_LOG_ERROR("#aiProcess_GenSmoothNormals and #aiProcess_GenNormals are incompatible");
  371|      0|        return false;
  372|      0|    }
  373|  1.54k|    if (pFlags & aiProcess_OptimizeGraph && pFlags & aiProcess_PreTransformVertices)    {
  ------------------
  |  Branch (373:9): [True: 0, False: 1.54k]
  |  Branch (373:45): [True: 0, False: 0]
  ------------------
  374|      0|        ASSIMP_LOG_ERROR("#aiProcess_OptimizeGraph and #aiProcess_PreTransformVertices are incompatible");
  375|      0|        return false;
  376|      0|    }
  377|  1.54k|    return true;
  378|  1.54k|}
_ZN6Assimp8Importer18ReadFileFromMemoryEPKvmjPKc:
  485|  5.13k|const aiScene* Importer::ReadFileFromMemory(const void* pBuffer, size_t pLength, unsigned int pFlags, const char* pHint ) {
  486|  5.13k|    ai_assert(nullptr != pimpl);
  487|       |
  488|  5.13k|    IOSystem* io = pimpl->mIOHandler;
  489|  5.13k|    try {
  490|  5.13k|        if (pHint == nullptr) {
  ------------------
  |  Branch (490:13): [True: 0, False: 5.13k]
  ------------------
  491|      0|            pHint = "";
  492|      0|        }
  493|  5.13k|        if (!pBuffer || !pLength || strlen(pHint) > MaxLenHint ) {
  ------------------
  |  Branch (493:13): [True: 0, False: 5.13k]
  |  Branch (493:25): [True: 0, False: 5.13k]
  |  Branch (493:37): [True: 0, False: 5.13k]
  ------------------
  494|      0|            pimpl->mErrorString = "Invalid parameters passed to ReadFileFromMemory()";
  495|      0|            return nullptr;
  496|      0|        }
  497|       |        // prevent deletion of the previous IOHandler
  498|  5.13k|        pimpl->mIOHandler = nullptr;
  499|       |
  500|  5.13k|        SetIOHandler(new MemoryIOSystem((const uint8_t*)pBuffer,pLength,io));
  501|       |
  502|       |        // read the file and recover the previous IOSystem
  503|  5.13k|        static const size_t BufSize(Importer::MaxLenHint + 28);
  504|  5.13k|        char fbuff[BufSize];
  505|  5.13k|        ai_snprintf(fbuff, BufSize, "%s.%s",AI_MEMORYIO_MAGIC_FILENAME,pHint);
  506|       |
  507|  5.13k|        ReadFile(fbuff,pFlags);
  508|  5.13k|        SetIOHandler(io);
  509|  5.13k|    } catch(const DeadlyImportError &e) {
  510|      0|        pimpl->mErrorString = e.what();
  511|      0|        pimpl->mException = std::current_exception();
  512|      0|        SetIOHandler(io);
  513|      0|        return ExceptionSwallower<const aiScene*>()();                                                                                                    \
  514|      0|    } catch(...) {
  515|      0|        pimpl->mErrorString = "Unknown exception";
  516|      0|        pimpl->mException = std::current_exception();
  517|      0|        SetIOHandler(io);
  518|      0|        return ExceptionSwallower<const aiScene*>()();                                                                                                    \
  519|      0|
  520|      0|    }
  521|       |
  522|  5.13k|    return pimpl->mScene;
  523|  5.13k|}
_Z15WriteLogOpeningRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE:
  526|  5.13k|void WriteLogOpening(const std::string& file) {
  527|       |
  528|  5.13k|    ASSIMP_LOG_INFO("Load ", file);
  529|       |
  530|       |    // print a full version dump. This is nice because we don't
  531|       |    // need to ask the authors of incoming bug reports for
  532|       |    // the library version they're using - a log dump is
  533|       |    // sufficient.
  534|  5.13k|    const unsigned int flags = aiGetCompileFlags();
  535|  5.13k|    std::stringstream stream;
  536|  5.13k|    stream << "Assimp " << aiGetVersionMajor() << "." << aiGetVersionMinor() << "." << aiGetVersionRevision() << " "
  537|       |#if defined(ASSIMP_BUILD_ARCHITECTURE)
  538|       |           << ASSIMP_BUILD_ARCHITECTURE
  539|       |#elif defined(_M_IX86) || defined(__x86_32__) || defined(__i386__)
  540|       |           << "x86"
  541|       |#elif defined(_M_X64) || defined(__x86_64__)
  542|       |           << "amd64"
  543|       |#elif defined(_M_IA64) || defined(__ia64__)
  544|       |           << "itanium"
  545|       |#elif defined(__ppc__) || defined(__powerpc__)
  546|       |           << "ppc32"
  547|       |#elif defined(__powerpc64__)
  548|       |           << "ppc64"
  549|       |#elif defined(__arm__)
  550|       |           << "arm"
  551|       |#else
  552|       |           << "<unknown architecture>"
  553|       |#endif
  554|  5.13k|           << " "
  555|       |#if defined(ASSIMP_BUILD_COMPILER)
  556|       |           << (ASSIMP_BUILD_COMPILER)
  557|       |#elif defined(_MSC_VER)
  558|       |           << "msvc"
  559|       |#elif defined(__GNUC__)
  560|       |           << "gcc"
  561|       |#elif defined(__clang__)
  562|       |           << "clang"
  563|       |#elif defined(__EMSCRIPTEN__)
  564|       |           << "emscripten"
  565|       |#elif defined(__MINGW32__)
  566|       |           << "MinGW-w64 32bit"
  567|       |#elif defined(__MINGW64__)
  568|       |           << "MinGW-w64 64bit"
  569|       |#else
  570|       |           << "<unknown compiler>"
  571|       |#endif
  572|       |
  573|  5.13k|#ifdef ASSIMP_BUILD_DEBUG
  574|  5.13k|           << " debug"
  575|  5.13k|#endif
  576|       |
  577|  5.13k|           << (flags & ASSIMP_CFLAGS_NOBOOST ? " noboost" : "")
  ------------------
  |  |  105|  5.13k|#define ASSIMP_CFLAGS_NOBOOST           0x8
  ------------------
  |  Branch (577:16): [True: 0, False: 5.13k]
  ------------------
  578|  5.13k|           << (flags & ASSIMP_CFLAGS_SHARED ? " shared" : "")
  ------------------
  |  |   98|  5.13k|#define ASSIMP_CFLAGS_SHARED  0x1
  ------------------
  |  Branch (578:16): [True: 0, False: 5.13k]
  ------------------
  579|  5.13k|           << (flags & ASSIMP_CFLAGS_SINGLETHREADED ? " singlethreaded" : "")
  ------------------
  |  |  107|  5.13k|#define ASSIMP_CFLAGS_SINGLETHREADED    0x10
  ------------------
  |  Branch (579:16): [True: 5.13k, False: 0]
  ------------------
  580|  5.13k|           << (flags & ASSIMP_CFLAGS_DOUBLE_SUPPORT ? " double : " : "single : ");
  ------------------
  |  |  109|  5.13k|#define ASSIMP_CFLAGS_DOUBLE_SUPPORT 0x20
  ------------------
  |  Branch (580:16): [True: 0, False: 5.13k]
  ------------------
  581|       |
  582|       |    ASSIMP_LOG_DEBUG(stream.str());
  583|  5.13k|}
_ZN6Assimp8Importer8ReadFileEPKcj:
  587|  5.13k|const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) {
  588|  5.13k|    ai_assert(nullptr != pimpl);
  589|       |
  590|  5.13k|    ASSIMP_BEGIN_EXCEPTION_REGION();
  591|  5.13k|    const std::string pFile(_pFile);
  592|       |
  593|       |    // ----------------------------------------------------------------------
  594|       |    // Put a large try block around everything to catch all std::exception's
  595|       |    // that might be thrown by STL containers or by new().
  596|       |    // ImportErrorException's are throw by ourselves and caught elsewhere.
  597|       |    //-----------------------------------------------------------------------
  598|       |
  599|  5.13k|    WriteLogOpening(pFile);
  600|       |
  601|       |#ifdef ASSIMP_CATCH_GLOBAL_EXCEPTIONS
  602|       |    try
  603|       |#endif // ! ASSIMP_CATCH_GLOBAL_EXCEPTIONS
  604|  5.13k|    {
  605|       |        // Check whether this Importer instance has already loaded
  606|       |        // a scene. In this case we need to delete the old one
  607|  5.13k|        if (pimpl->mScene)  {
  ------------------
  |  Branch (607:13): [True: 0, False: 5.13k]
  ------------------
  608|       |
  609|      0|            ASSIMP_LOG_DEBUG("(Deleting previous scene)");
  610|      0|            FreeScene();
  611|      0|        }
  612|       |
  613|       |        // First check if the file is accessible at all
  614|  5.13k|        if( !pimpl->mIOHandler->Exists( pFile)) {
  ------------------
  |  Branch (614:13): [True: 0, False: 5.13k]
  ------------------
  615|       |
  616|      0|            pimpl->mErrorString = "Unable to open file \"" + pFile + "\".";
  617|      0|            ASSIMP_LOG_ERROR(pimpl->mErrorString);
  618|      0|            return nullptr;
  619|      0|        }
  620|       |
  621|  5.13k|        std::unique_ptr<Profiler> profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME, 0) ? new Profiler() : nullptr);
  ------------------
  |  Branch (621:44): [True: 0, False: 5.13k]
  ------------------
  622|  5.13k|        if (profiler) {
  ------------------
  |  Branch (622:13): [True: 0, False: 5.13k]
  ------------------
  623|      0|            profiler->BeginRegion("total");
  624|      0|        }
  625|       |
  626|       |        // Find an worker class which can handle the file extension.
  627|       |        // Multiple importers may be able to handle the same extension (.xml!); gather them all.
  628|  5.13k|        SetPropertyInteger("importerIndex", -1);
  629|  5.13k|        struct ImporterAndIndex {
  630|  5.13k|            BaseImporter * importer;
  631|  5.13k|            unsigned int   index;
  632|  5.13k|        };
  633|  5.13k|        std::vector<ImporterAndIndex> possibleImporters;
  634|  15.3k|        for (unsigned int a = 0; a < pimpl->mImporter.size(); a++)  {
  ------------------
  |  Branch (634:34): [True: 10.2k, False: 5.13k]
  ------------------
  635|       |
  636|       |            // Every importer has a list of supported extensions.
  637|  10.2k|            std::set<std::string> extensions;
  638|  10.2k|            pimpl->mImporter[a]->GetExtensionList(extensions);
  639|       |
  640|  10.2k|            if (BaseImporter::HasExtension(pFile, extensions)) {
  ------------------
  |  Branch (640:17): [True: 10.2k, False: 0]
  ------------------
  641|  10.2k|                ImporterAndIndex candidate = { pimpl->mImporter[a], a };
  642|  10.2k|                possibleImporters.push_back(candidate);
  643|  10.2k|            }
  644|  10.2k|        }
  645|       |
  646|       |        // If just one importer supports this extension, pick it and close the case.
  647|  5.13k|        BaseImporter* imp = nullptr;
  648|  5.13k|        if (1 == possibleImporters.size()) {
  ------------------
  |  Branch (648:13): [True: 0, False: 5.13k]
  ------------------
  649|      0|            imp = possibleImporters[0].importer;
  650|      0|            SetPropertyInteger("importerIndex", possibleImporters[0].index);
  651|      0|        }
  652|       |        // If multiple importers claim this file extension, ask them to look at the actual file data to decide.
  653|       |        // This can happen e.g. with XML (COLLADA vs. Irrlicht).
  654|  5.13k|        else {
  655|  11.2k|            for (std::vector<ImporterAndIndex>::const_iterator it = possibleImporters.begin(); it < possibleImporters.end(); ++it) {
  ------------------
  |  Branch (655:96): [True: 9.93k, False: 1.27k]
  ------------------
  656|  9.93k|                BaseImporter & importer = *it->importer;
  657|       |
  658|  9.93k|                ASSIMP_LOG_INFO("Found a possible importer: " + std::string(importer.GetInfo()->mName) + "; trying signature-based detection");
  659|  9.93k|                if (importer.CanRead( pFile, pimpl->mIOHandler, true)) {
  ------------------
  |  Branch (659:21): [True: 3.86k, False: 6.07k]
  ------------------
  660|  3.86k|                    imp = &importer;
  661|  3.86k|                    SetPropertyInteger("importerIndex", it->index);
  662|  3.86k|                    break;
  663|  3.86k|                }
  664|       |
  665|  9.93k|            }
  666|       |
  667|  5.13k|        }
  668|       |
  669|  5.13k|        if (!imp)   {
  ------------------
  |  Branch (669:13): [True: 1.27k, False: 3.86k]
  ------------------
  670|       |            // not so bad yet ... try format auto detection.
  671|  1.27k|            ASSIMP_LOG_INFO("File extension not known, trying signature-based detection");
  672|  3.81k|            for( unsigned int a = 0; a < pimpl->mImporter.size(); a++)  {
  ------------------
  |  Branch (672:38): [True: 2.54k, False: 1.27k]
  ------------------
  673|  2.54k|                if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, true)) {
  ------------------
  |  Branch (673:21): [True: 0, False: 2.54k]
  ------------------
  674|      0|                    imp = pimpl->mImporter[a];
  675|      0|                    SetPropertyInteger("importerIndex", a);
  676|      0|                    break;
  677|      0|                }
  678|  2.54k|            }
  679|       |            // Put a proper error message if no suitable importer was found
  680|  1.27k|            if( !imp)   {
  ------------------
  |  Branch (680:17): [True: 1.27k, False: 0]
  ------------------
  681|  1.27k|                pimpl->mErrorString = "No suitable reader found for the file format of file \"" + pFile + "\".";
  682|  1.27k|                ASSIMP_LOG_ERROR(pimpl->mErrorString);
  683|  1.27k|                return nullptr;
  684|  1.27k|            }
  685|  1.27k|        }
  686|       |
  687|       |        // Get file size for progress handler
  688|  3.86k|        IOStream * fileIO = pimpl->mIOHandler->Open( pFile );
  689|  3.86k|        uint32_t fileSize = 0;
  690|  3.86k|        if (fileIO)
  ------------------
  |  Branch (690:13): [True: 3.86k, False: 0]
  ------------------
  691|  3.86k|        {
  692|  3.86k|            fileSize = static_cast<uint32_t>(fileIO->FileSize());
  693|  3.86k|            pimpl->mIOHandler->Close( fileIO );
  694|  3.86k|        }
  695|       |
  696|       |        // Dispatch the reading to the worker class for this format
  697|  3.86k|        const aiImporterDesc *desc( imp->GetInfo() );
  698|  3.86k|        std::string ext( "unknown" );
  699|  3.86k|        if ( nullptr != desc ) {
  ------------------
  |  Branch (699:14): [True: 3.86k, False: 0]
  ------------------
  700|  3.86k|            ext = desc->mName;
  701|  3.86k|        }
  702|  3.86k|        ASSIMP_LOG_INFO("Found a matching importer for this file format: ", ext, "." );
  703|  3.86k|        pimpl->mProgressHandler->UpdateFileRead( 0, fileSize );
  704|       |
  705|  3.86k|        if (profiler) {
  ------------------
  |  Branch (705:13): [True: 0, False: 3.86k]
  ------------------
  706|      0|            profiler->BeginRegion("import");
  707|      0|        }
  708|       |
  709|  3.86k|        pimpl->mScene = imp->ReadFile( this, pFile, pimpl->mIOHandler);
  710|  3.86k|        pimpl->mProgressHandler->UpdateFileRead( fileSize, fileSize );
  711|       |
  712|  3.86k|        if (profiler) {
  ------------------
  |  Branch (712:13): [True: 0, False: 3.86k]
  ------------------
  713|      0|            profiler->EndRegion("import");
  714|      0|        }
  715|       |
  716|  3.86k|        SetPropertyString("sourceFilePath", pFile);
  717|       |
  718|       |        // If successful, apply all active post processing steps to the imported data
  719|  3.86k|        if( pimpl->mScene)  {
  ------------------
  |  Branch (719:13): [True: 2.02k, False: 1.83k]
  ------------------
  720|  2.02k|            if (!pimpl->mScene->mMetaData || !pimpl->mScene->mMetaData->HasKey(AI_METADATA_SOURCE_FORMAT)) {
  ------------------
  |  Branch (720:17): [True: 0, False: 2.02k]
  |  Branch (720:46): [True: 2.02k, False: 0]
  ------------------
  721|  2.02k|                if (!pimpl->mScene->mMetaData) {
  ------------------
  |  Branch (721:21): [True: 0, False: 2.02k]
  ------------------
  722|      0|                    pimpl->mScene->mMetaData = new aiMetadata;
  723|      0|                }
  724|  2.02k|                pimpl->mScene->mMetaData->Add(AI_METADATA_SOURCE_FORMAT, aiString(ext));
  725|  2.02k|            }
  726|       |
  727|  2.02k|#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
  728|       |            // The ValidateDS process is an exception. It is executed first, even before ScenePreprocessor is called.
  729|  2.02k|            if (pFlags & aiProcess_ValidateDataStructure) {
  ------------------
  |  Branch (729:17): [True: 2.02k, False: 0]
  ------------------
  730|  2.02k|                ValidateDSProcess ds;
  731|  2.02k|                ds.ExecuteOnScene (this);
  732|  2.02k|                if (!pimpl->mScene) {
  ------------------
  |  Branch (732:21): [True: 481, False: 1.54k]
  ------------------
  733|    481|                    return nullptr;
  734|    481|                }
  735|  2.02k|            }
  736|  1.54k|#endif // ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
  737|       |
  738|       |            // Preprocess the scene and prepare it for post-processing
  739|  1.54k|            if (profiler) {
  ------------------
  |  Branch (739:17): [True: 0, False: 1.54k]
  ------------------
  740|      0|                profiler->BeginRegion("preprocess");
  741|      0|            }
  742|       |
  743|  1.54k|            ScenePreprocessor pre(pimpl->mScene);
  744|  1.54k|            pre.ProcessScene();
  745|       |
  746|  1.54k|            if (profiler) {
  ------------------
  |  Branch (746:17): [True: 0, False: 1.54k]
  ------------------
  747|      0|                profiler->EndRegion("preprocess");
  748|      0|            }
  749|       |
  750|       |            // Ensure that the validation process won't be called twice
  751|  1.54k|            ApplyPostProcessing(pFlags & (~aiProcess_ValidateDataStructure));
  752|  1.54k|        }
  753|       |        // if failed, extract the error string
  754|  1.83k|        else if( !pimpl->mScene) {
  ------------------
  |  Branch (754:18): [True: 1.83k, False: 0]
  ------------------
  755|  1.83k|            pimpl->mErrorString = imp->GetErrorText();
  756|  1.83k|            pimpl->mException = imp->GetException();
  757|  1.83k|        }
  758|       |
  759|       |        // clear any data allocated by post-process steps
  760|  3.38k|        pimpl->mPPShared->Clean();
  761|       |
  762|  3.38k|        if (profiler) {
  ------------------
  |  Branch (762:13): [True: 0, False: 3.38k]
  ------------------
  763|      0|            profiler->EndRegion("total");
  764|      0|        }
  765|  3.38k|    }
  766|       |#ifdef ASSIMP_CATCH_GLOBAL_EXCEPTIONS
  767|       |    catch (std::exception &e) {
  768|       |#if (defined _MSC_VER) &&   (defined _CPPRTTI)
  769|       |        // if we have RTTI get the full name of the exception that occurred
  770|       |        pimpl->mErrorString = std::string(typeid( e ).name()) + ": " + e.what();
  771|       |#else
  772|       |        pimpl->mErrorString = std::string("std::exception: ") + e.what();
  773|       |#endif
  774|       |        pimpl->mException = std::current_exception();
  775|       |
  776|       |        ASSIMP_LOG_ERROR(pimpl->mErrorString);
  777|       |        delete pimpl->mScene; pimpl->mScene = nullptr;
  778|       |    }
  779|       |#endif // ! ASSIMP_CATCH_GLOBAL_EXCEPTIONS
  780|       |
  781|       |    // either successful or failure - the pointer expresses it anyways
  782|  3.38k|    ASSIMP_END_EXCEPTION_REGION_WITH_ERROR_STRING(const aiScene*, pimpl->mErrorString, pimpl->mException);
  783|       |
  784|  3.38k|    return pimpl->mScene;
  785|  5.13k|}
_ZN6Assimp8Importer19ApplyPostProcessingEj:
  790|  1.54k|const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags) {
  791|  1.54k|    ai_assert(nullptr != pimpl);
  792|       |
  793|  1.54k|    ASSIMP_BEGIN_EXCEPTION_REGION();
  794|       |    // Return immediately if no scene is active
  795|  1.54k|    if (!pimpl->mScene) {
  ------------------
  |  Branch (795:9): [True: 0, False: 1.54k]
  ------------------
  796|      0|        return nullptr;
  797|      0|    }
  798|       |
  799|       |    // If no flags are given, return the current scene with no further action
  800|  1.54k|    if (!pFlags) {
  ------------------
  |  Branch (800:9): [True: 0, False: 1.54k]
  ------------------
  801|      0|        return pimpl->mScene;
  802|      0|    }
  803|       |
  804|       |    // In debug builds: run basic flag validation
  805|  1.54k|    ai_assert(_ValidateFlags(pFlags));
  806|  1.54k|    ASSIMP_LOG_INFO("Entering post processing pipeline");
  807|       |
  808|  1.54k|#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
  809|       |    // The ValidateDS process plays an exceptional role. It isn't contained in the global
  810|       |    // list of post-processing steps, so we need to call it manually.
  811|  1.54k|    if (pFlags & aiProcess_ValidateDataStructure) {
  ------------------
  |  Branch (811:9): [True: 0, False: 1.54k]
  ------------------
  812|      0|        ValidateDSProcess ds;
  813|      0|        ds.ExecuteOnScene (this);
  814|      0|        if (!pimpl->mScene) {
  ------------------
  |  Branch (814:13): [True: 0, False: 0]
  ------------------
  815|      0|            return nullptr;
  816|      0|        }
  817|      0|    }
  818|  1.54k|#endif // no validation
  819|  1.54k|#ifdef ASSIMP_BUILD_DEBUG
  820|  1.54k|    if (pimpl->bExtraVerbose)
  ------------------
  |  Branch (820:9): [True: 0, False: 1.54k]
  ------------------
  821|      0|    {
  822|       |#ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
  823|       |        ASSIMP_LOG_ERROR("Verbose Import is not available due to build settings");
  824|       |#endif  // no validation
  825|      0|        pFlags |= aiProcess_ValidateDataStructure;
  826|      0|    }
  827|       |#else
  828|       |    if (pimpl->bExtraVerbose) {
  829|       |        ASSIMP_LOG_WARN("Not a debug build, ignoring extra verbose setting");
  830|       |    }
  831|       |#endif // ! DEBUG
  832|       |
  833|  1.54k|    std::unique_ptr<Profiler> profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME, 0) ? new Profiler() : nullptr);
  ------------------
  |  Branch (833:40): [True: 0, False: 1.54k]
  ------------------
  834|  51.8k|    for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++)   {
  ------------------
  |  Branch (834:30): [True: 50.3k, False: 1.50k]
  ------------------
  835|  50.3k|        BaseProcess* process = pimpl->mPostProcessingSteps[a];
  836|  50.3k|        pimpl->mProgressHandler->UpdatePostProcess(static_cast<int>(a), static_cast<int>(pimpl->mPostProcessingSteps.size()) );
  837|  50.3k|        if( process->IsActive( pFlags)) {
  ------------------
  |  Branch (837:13): [True: 22.8k, False: 27.5k]
  ------------------
  838|  22.8k|            if (profiler) {
  ------------------
  |  Branch (838:17): [True: 0, False: 22.8k]
  ------------------
  839|      0|                profiler->BeginRegion("postprocess");
  840|      0|            }
  841|       |
  842|  22.8k|            process->ExecuteOnScene ( this );
  843|       |
  844|  22.8k|            if (profiler) {
  ------------------
  |  Branch (844:17): [True: 0, False: 22.8k]
  ------------------
  845|      0|                profiler->EndRegion("postprocess");
  846|      0|            }
  847|  22.8k|        }
  848|  50.3k|        if( !pimpl->mScene) {
  ------------------
  |  Branch (848:13): [True: 45, False: 50.3k]
  ------------------
  849|     45|            break;
  850|     45|        }
  851|  50.3k|#ifdef ASSIMP_BUILD_DEBUG
  852|  50.3k|#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
  853|       |        // If the extra verbose mode is active, execute the ValidateDataStructureStep again - after each step
  854|  50.3k|        if (pimpl->bExtraVerbose)   {
  ------------------
  |  Branch (854:13): [True: 0, False: 50.3k]
  ------------------
  855|      0|            ASSIMP_LOG_DEBUG("Verbose Import: re-validating data structures");
  856|       |
  857|      0|            ValidateDSProcess ds;
  858|      0|            ds.ExecuteOnScene (this);
  859|      0|            if( !pimpl->mScene) {
  ------------------
  |  Branch (859:17): [True: 0, False: 0]
  ------------------
  860|      0|                ASSIMP_LOG_ERROR("Verbose Import: failed to re-validate data structures");
  861|      0|                break;
  862|      0|            }
  863|      0|        }
  864|  50.3k|#endif  // no validation
  865|  50.3k|#endif // ! DEBUG
  866|  50.3k|    }
  867|  1.54k|    pimpl->mProgressHandler->UpdatePostProcess( static_cast<int>(pimpl->mPostProcessingSteps.size()),
  868|  1.54k|        static_cast<int>(pimpl->mPostProcessingSteps.size()) );
  869|       |
  870|       |    // update private scene flags
  871|  1.54k|    if( pimpl->mScene ) {
  ------------------
  |  Branch (871:9): [True: 1.50k, False: 45]
  ------------------
  872|  1.50k|      ScenePriv(pimpl->mScene)->mPPStepsApplied |= pFlags;
  873|  1.50k|    }
  874|       |
  875|       |    // clear any data allocated by post-process steps
  876|  1.54k|    pimpl->mPPShared->Clean();
  877|  1.54k|    ASSIMP_LOG_INFO("Leaving post processing pipeline");
  878|       |
  879|  1.54k|    ASSIMP_END_EXCEPTION_REGION(const aiScene*);
  880|       |
  881|  1.54k|    return pimpl->mScene;
  882|  1.54k|}
_ZNK6Assimp8Importer16GetImporterCountEv:
  969|  5.13k|size_t Importer::GetImporterCount() const {
  970|  5.13k|    ai_assert(nullptr != pimpl);
  971|       |
  972|  5.13k|    return pimpl->mImporter.size();
  973|  5.13k|}
_ZNK6Assimp8Importer15GetImporterInfoEm:
  976|   246k|const aiImporterDesc* Importer::GetImporterInfo(size_t index) const {
  977|   246k|    ai_assert(nullptr != pimpl);
  978|       |
  979|   246k|    if (index >= pimpl->mImporter.size()) {
  ------------------
  |  Branch (979:9): [True: 0, False: 246k]
  ------------------
  980|      0|        return nullptr;
  981|      0|    }
  982|   246k|    return pimpl->mImporter[index]->GetInfo();
  983|   246k|}
_ZNK6Assimp8Importer11GetImporterEm:
  987|   246k|BaseImporter* Importer::GetImporter (size_t index) const {
  988|   246k|    ai_assert(nullptr != pimpl);
  989|       |
  990|   246k|    if (index >= pimpl->mImporter.size()) {
  ------------------
  |  Branch (990:9): [True: 0, False: 246k]
  ------------------
  991|      0|        return nullptr;
  992|      0|    }
  993|   246k|    return pimpl->mImporter[index];
  994|   246k|}
_ZN6Assimp8Importer18SetPropertyIntegerEPKci:
 1063|  8.99k|bool Importer::SetPropertyInteger(const char* szName, int iValue) {
 1064|  8.99k|    ai_assert(nullptr != pimpl);
 1065|       |
 1066|  8.99k|    bool existing;
 1067|  8.99k|    ASSIMP_BEGIN_EXCEPTION_REGION();
 1068|  8.99k|        existing = SetGenericProperty<int>(pimpl->mIntProperties, szName,iValue);
 1069|  8.99k|    ASSIMP_END_EXCEPTION_REGION(bool);
 1070|  8.99k|    return existing;
 1071|  8.99k|}
_ZN6Assimp8Importer16SetPropertyFloatEPKcf:
 1075|  2.02k|bool Importer::SetPropertyFloat(const char* szName, ai_real iValue) {
 1076|  2.02k|    ai_assert(nullptr != pimpl);
 1077|       |
 1078|  2.02k|    bool existing;
 1079|  2.02k|    ASSIMP_BEGIN_EXCEPTION_REGION();
 1080|  2.02k|        existing = SetGenericProperty<ai_real>(pimpl->mFloatProperties, szName,iValue);
 1081|  2.02k|    ASSIMP_END_EXCEPTION_REGION(bool);
 1082|  2.02k|    return existing;
 1083|  2.02k|}
_ZN6Assimp8Importer17SetPropertyStringEPKcRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEE:
 1087|  3.86k|bool Importer::SetPropertyString(const char* szName, const std::string& value) {
 1088|  3.86k|    ai_assert(nullptr != pimpl);
 1089|       |
 1090|  3.86k|    bool existing;
 1091|  3.86k|    ASSIMP_BEGIN_EXCEPTION_REGION();
 1092|  3.86k|        existing = SetGenericProperty<std::string>(pimpl->mStringProperties, szName,value);
 1093|  3.86k|    ASSIMP_END_EXCEPTION_REGION(bool);
 1094|  3.86k|    return existing;
 1095|  3.86k|}
_ZNK6Assimp8Importer18GetPropertyIntegerEPKci:
 1123|  21.8k|int Importer::GetPropertyInteger(const char* szName, int iErrorReturn /*= 0xffffffff*/) const {
 1124|  21.8k|    ai_assert(nullptr != pimpl);
 1125|       |
 1126|  21.8k|    return GetGenericProperty<int>(pimpl->mIntProperties,szName,iErrorReturn);
 1127|  21.8k|}
_ZNK6Assimp8Importer16GetPropertyFloatEPKcf:
 1131|  4.55k|ai_real Importer::GetPropertyFloat(const char* szName, ai_real iErrorReturn /*= 10e10*/) const {
 1132|  4.55k|    ai_assert(nullptr != pimpl);
 1133|       |
 1134|  4.55k|    return GetGenericProperty<ai_real>(pimpl->mFloatProperties,szName,iErrorReturn);
 1135|  4.55k|}
_ZNK6Assimp8Importer17GetPropertyStringEPKcRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEE:
 1139|  1.54k|std::string Importer::GetPropertyString(const char* szName, const std::string& iErrorReturn /*= ""*/) const {
 1140|  1.54k|    ai_assert(nullptr != pimpl);
 1141|       |
 1142|  1.54k|    return GetGenericProperty<std::string>(pimpl->mStringProperties,szName,iErrorReturn);
 1143|  1.54k|}
_ZNK6Assimp8Importer18GetPropertyPointerEPKcPv:
 1155|  3.53k|void* Importer::GetPropertyPointer(const char* szName, void* iErrorReturn /*= nullptr*/) const {
 1156|  3.53k|    ai_assert(nullptr != pimpl);
 1157|       |
 1158|  3.53k|    return GetGenericProperty<void*>(pimpl->mPointerProperties,szName,iErrorReturn);
 1159|  3.53k|}

_ZN6Assimp13ImporterPimplC2Ev:
  137|  5.13k|        mIOHandler( nullptr ),
  138|  5.13k|        mIsDefaultHandler( false ),
  139|  5.13k|        mProgressHandler( nullptr ),
  140|  5.13k|        mIsDefaultProgressHandler( false ),
  141|  5.13k|        mImporter(),
  142|  5.13k|        mPostProcessingSteps(),
  143|  5.13k|        mScene( nullptr ),
  144|  5.13k|        mErrorString(),
  145|  5.13k|        mException(),
  146|  5.13k|        mIntProperties(),
  147|  5.13k|        mFloatProperties(),
  148|  5.13k|        mStringProperties(),
  149|  5.13k|        mMatrixProperties(),
  150|  5.13k|        mPointerProperties(),
  151|  5.13k|        bExtraVerbose( false ),
  152|  5.13k|        mPPShared( nullptr ) {
  153|       |    // empty
  154|  5.13k|}
_ZN6Assimp13ImporterPimplD2Ev:
  133|  5.13k|    ~ImporterPimpl() = default;

_ZN6Assimp23GetImporterInstanceListERNSt3__16vectorIPNS_12BaseImporterENS0_9allocatorIS3_EEEE:
  215|  5.13k|void GetImporterInstanceList(std::vector<BaseImporter *> &out) {
  216|       |
  217|       |    // Some importers may be unimplemented or otherwise unsuitable for general use
  218|       |    // in their current state. Devs can set ASSIMP_ENABLE_DEV_IMPORTERS in their
  219|       |    // local environment to enable them, otherwise they're left out of the registry.
  220|       |#if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP
  221|       |    // not supported under uwp
  222|       |    const char *envStr = std::getenv("ASSIMP_ENABLE_DEV_IMPORTERS");
  223|       |#else
  224|  5.13k|    const char *envStr = { "0" };
  225|  5.13k|#endif
  226|  5.13k|    bool devImportersEnabled = envStr && strcmp(envStr, "0");
  ------------------
  |  Branch (226:32): [True: 5.13k, False: 0]
  |  Branch (226:42): [True: 0, False: 5.13k]
  ------------------
  227|       |
  228|       |    // Ensure no unused var warnings if all uses are #ifndef'd away below:
  229|  5.13k|    (void)devImportersEnabled;
  230|       |
  231|       |    // ----------------------------------------------------------------------------
  232|       |    // Add an instance of each worker class here
  233|       |    // (register_new_importers_here)
  234|       |    // ----------------------------------------------------------------------------
  235|  5.13k|    out.reserve(64);
  236|       |#if !defined(ASSIMP_BUILD_NO_USD_IMPORTER)
  237|       |    out.push_back(new USDImporter());
  238|       |#endif
  239|  5.13k|#if (!defined ASSIMP_BUILD_NO_X_IMPORTER)
  240|  5.13k|    out.push_back(new XFileImporter());
  241|  5.13k|#endif
  242|  5.13k|#if (!defined ASSIMP_BUILD_NO_OBJ_IMPORTER)
  243|  5.13k|    out.push_back(new ObjFileImporter());
  244|  5.13k|#endif
  245|  5.13k|#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
  246|  5.13k|    out.push_back(new AMFImporter());
  247|  5.13k|#endif
  248|  5.13k|#if (!defined ASSIMP_BUILD_NO_3DS_IMPORTER)
  249|  5.13k|    out.push_back(new Discreet3DSImporter());
  250|  5.13k|#endif
  251|       |#if (!defined ASSIMP_BUILD_NO_M3D_IMPORTER)
  252|       |    out.push_back(new M3DImporter());
  253|       |#endif
  254|  5.13k|#if (!defined ASSIMP_BUILD_NO_MD3_IMPORTER)
  255|  5.13k|    out.push_back(new MD3Importer());
  256|  5.13k|#endif
  257|  5.13k|#if (!defined ASSIMP_BUILD_NO_MD2_IMPORTER)
  258|  5.13k|    out.push_back(new MD2Importer());
  259|  5.13k|#endif
  260|  5.13k|#if (!defined ASSIMP_BUILD_NO_PLY_IMPORTER)
  261|  5.13k|    out.push_back(new PLYImporter());
  262|  5.13k|#endif
  263|  5.13k|#if (!defined ASSIMP_BUILD_NO_MDL_IMPORTER)
  264|  5.13k|    out.push_back(new MDLImporter());
  265|  5.13k|#endif
  266|  5.13k|#if (!defined ASSIMP_BUILD_NO_ASE_IMPORTER)
  267|  5.13k|#if (!defined ASSIMP_BUILD_NO_3DS_IMPORTER)
  268|  5.13k|    out.push_back(new ASEImporter());
  269|  5.13k|#endif
  270|  5.13k|#endif
  271|  5.13k|#if (!defined ASSIMP_BUILD_NO_HMP_IMPORTER)
  272|  5.13k|    out.push_back(new HMPImporter());
  273|  5.13k|#endif
  274|  5.13k|#if (!defined ASSIMP_BUILD_NO_SMD_IMPORTER)
  275|  5.13k|    out.push_back(new SMDImporter());
  276|  5.13k|#endif
  277|  5.13k|#if (!defined ASSIMP_BUILD_NO_MDC_IMPORTER)
  278|  5.13k|    out.push_back(new MDCImporter());
  279|  5.13k|#endif
  280|  5.13k|#if (!defined ASSIMP_BUILD_NO_MD5_IMPORTER)
  281|  5.13k|    out.push_back(new MD5Importer());
  282|  5.13k|#endif
  283|  5.13k|#if (!defined ASSIMP_BUILD_NO_STL_IMPORTER)
  284|  5.13k|    out.push_back(new STLImporter());
  285|  5.13k|#endif
  286|  5.13k|#if (!defined ASSIMP_BUILD_NO_LWO_IMPORTER)
  287|  5.13k|    out.push_back(new LWOImporter());
  288|  5.13k|#endif
  289|  5.13k|#if (!defined ASSIMP_BUILD_NO_DXF_IMPORTER)
  290|  5.13k|    out.push_back(new DXFImporter());
  291|  5.13k|#endif
  292|  5.13k|#if (!defined ASSIMP_BUILD_NO_NFF_IMPORTER)
  293|  5.13k|    out.push_back(new NFFImporter());
  294|  5.13k|#endif
  295|  5.13k|#if (!defined ASSIMP_BUILD_NO_RAW_IMPORTER)
  296|  5.13k|    out.push_back(new RAWImporter());
  297|  5.13k|#endif
  298|  5.13k|#if (!defined ASSIMP_BUILD_NO_SIB_IMPORTER)
  299|  5.13k|    out.push_back(new SIBImporter());
  300|  5.13k|#endif
  301|  5.13k|#if (!defined ASSIMP_BUILD_NO_OFF_IMPORTER)
  302|  5.13k|    out.push_back(new OFFImporter());
  303|  5.13k|#endif
  304|  5.13k|#if (!defined ASSIMP_BUILD_NO_AC_IMPORTER)
  305|  5.13k|    out.push_back(new AC3DImporter());
  306|  5.13k|#endif
  307|  5.13k|#if (!defined ASSIMP_BUILD_NO_BVH_IMPORTER)
  308|  5.13k|    out.push_back(new BVHLoader());
  309|  5.13k|#endif
  310|  5.13k|#if (!defined ASSIMP_BUILD_NO_IRRMESH_IMPORTER)
  311|  5.13k|    out.push_back(new IRRMeshImporter());
  312|  5.13k|#endif
  313|  5.13k|#if (!defined ASSIMP_BUILD_NO_IRR_IMPORTER)
  314|  5.13k|    out.push_back(new IRRImporter());
  315|  5.13k|#endif
  316|  5.13k|#if (!defined ASSIMP_BUILD_NO_Q3D_IMPORTER)
  317|  5.13k|    out.push_back(new Q3DImporter());
  318|  5.13k|#endif
  319|  5.13k|#if (!defined ASSIMP_BUILD_NO_B3D_IMPORTER)
  320|  5.13k|    out.push_back(new B3DImporter());
  321|  5.13k|#endif
  322|  5.13k|#if (!defined ASSIMP_BUILD_NO_COLLADA_IMPORTER)
  323|  5.13k|    out.push_back(new ColladaLoader());
  324|  5.13k|#endif
  325|  5.13k|#if (!defined ASSIMP_BUILD_NO_TERRAGEN_IMPORTER)
  326|  5.13k|    out.push_back(new TerragenImporter());
  327|  5.13k|#endif
  328|  5.13k|#if (!defined ASSIMP_BUILD_NO_CSM_IMPORTER)
  329|  5.13k|    out.push_back(new CSMImporter());
  330|  5.13k|#endif
  331|  5.13k|#if (!defined ASSIMP_BUILD_NO_3D_IMPORTER)
  332|  5.13k|    out.push_back(new UnrealImporter());
  333|  5.13k|#endif
  334|  5.13k|#if (!defined ASSIMP_BUILD_NO_LWS_IMPORTER)
  335|  5.13k|    out.push_back(new LWSImporter());
  336|  5.13k|#endif
  337|  5.13k|#if (!defined ASSIMP_BUILD_NO_OGRE_IMPORTER)
  338|  5.13k|    out.push_back(new Ogre::OgreImporter());
  339|  5.13k|#endif
  340|  5.13k|#if (!defined ASSIMP_BUILD_NO_OPENGEX_IMPORTER)
  341|  5.13k|    out.push_back(new OpenGEX::OpenGEXImporter());
  342|  5.13k|#endif
  343|  5.13k|#if (!defined ASSIMP_BUILD_NO_MS3D_IMPORTER)
  344|  5.13k|    out.push_back(new MS3DImporter());
  345|  5.13k|#endif
  346|  5.13k|#if (!defined ASSIMP_BUILD_NO_COB_IMPORTER)
  347|  5.13k|    out.push_back(new COBImporter());
  348|  5.13k|#endif
  349|  5.13k|#if (!defined ASSIMP_BUILD_NO_BLEND_IMPORTER)
  350|  5.13k|    out.push_back(new BlenderImporter());
  351|  5.13k|#endif
  352|  5.13k|#if (!defined ASSIMP_BUILD_NO_Q3BSP_IMPORTER)
  353|  5.13k|    out.push_back(new Q3BSPFileImporter());
  354|  5.13k|#endif
  355|  5.13k|#if (!defined ASSIMP_BUILD_NO_NDO_IMPORTER)
  356|  5.13k|    out.push_back(new NDOImporter());
  357|  5.13k|#endif
  358|  5.13k|#if (!defined ASSIMP_BUILD_NO_IFC_IMPORTER)
  359|  5.13k|    out.push_back(new IFCImporter());
  360|  5.13k|#endif
  361|  5.13k|#if (!defined ASSIMP_BUILD_NO_XGL_IMPORTER)
  362|  5.13k|    out.push_back(new XGLImporter());
  363|  5.13k|#endif
  364|  5.13k|#if (!defined ASSIMP_BUILD_NO_FBX_IMPORTER)
  365|  5.13k|    out.push_back(new FBXImporter());
  366|  5.13k|#endif
  367|  5.13k|#if (!defined ASSIMP_BUILD_NO_ASSBIN_IMPORTER)
  368|  5.13k|    out.push_back(new AssbinImporter());
  369|  5.13k|#endif
  370|  5.13k|#if (!defined ASSIMP_BUILD_NO_GLTF_IMPORTER && !defined ASSIMP_BUILD_NO_GLTF1_IMPORTER)
  371|  5.13k|    out.push_back(new glTFImporter());
  372|  5.13k|#endif
  373|  5.13k|#if (!defined ASSIMP_BUILD_NO_GLTF_IMPORTER && !defined ASSIMP_BUILD_NO_GLTF2_IMPORTER)
  374|  5.13k|    out.push_back(new glTF2Importer());
  375|  5.13k|#endif
  376|       |#if (!defined ASSIMP_BUILD_NO_C4D_IMPORTER)
  377|       |    out.push_back(new C4DImporter());
  378|       |#endif
  379|  5.13k|#if (!defined ASSIMP_BUILD_NO_3MF_IMPORTER)
  380|  5.13k|    out.push_back(new D3MFImporter());
  381|  5.13k|#endif
  382|  5.13k|#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
  383|  5.13k|    out.push_back(new X3DImporter());
  384|  5.13k|#endif
  385|  5.13k|#ifndef ASSIMP_BUILD_NO_MMD_IMPORTER
  386|  5.13k|    out.push_back(new MMDImporter());
  387|  5.13k|#endif
  388|  5.13k|#ifndef ASSIMP_BUILD_NO_IQM_IMPORTER
  389|  5.13k|    out.push_back(new IQMImporter());
  390|  5.13k|#endif
  391|  5.13k|}
_ZN6Assimp26DeleteImporterInstanceListERNSt3__16vectorIPNS_12BaseImporterENS0_9allocatorIS3_EEEE:
  394|  5.13k|void DeleteImporterInstanceList(std::vector<BaseImporter *> &deleteList) {
  395|  15.3k|    for (size_t i = 0; i < deleteList.size(); ++i) {
  ------------------
  |  Branch (395:24): [True: 10.2k, False: 5.13k]
  ------------------
  396|  10.2k|        delete deleteList[i];
  397|  10.2k|        deleteList[i] = nullptr;
  398|  10.2k|    } //for
  399|  5.13k|}

_ZN6Assimp33GetPostProcessingStepInstanceListERNSt3__16vectorIPNS_11BaseProcessENS0_9allocatorIS3_EEEE:
  147|  5.13k|{
  148|       |    // ----------------------------------------------------------------------------
  149|       |    // Add an instance of each post processing step here in the order
  150|       |    // of sequence it is executed. Steps that are added here are not
  151|       |    // validated - as RegisterPPStep() does - all dependencies must be given.
  152|       |    // ----------------------------------------------------------------------------
  153|  5.13k|    out.reserve(31);
  154|  5.13k|#if (!defined ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS)
  155|  5.13k|    out.push_back( new MakeLeftHandedProcess());
  156|  5.13k|#endif
  157|  5.13k|#if (!defined ASSIMP_BUILD_NO_FLIPUVS_PROCESS)
  158|  5.13k|    out.push_back( new FlipUVsProcess());
  159|  5.13k|#endif
  160|  5.13k|#if (!defined ASSIMP_BUILD_NO_FLIPWINDINGORDER_PROCESS)
  161|  5.13k|    out.push_back( new FlipWindingOrderProcess());
  162|  5.13k|#endif
  163|  5.13k|#if (!defined ASSIMP_BUILD_NO_REMOVEVC_PROCESS)
  164|  5.13k|    out.push_back( new RemoveVCProcess());
  165|  5.13k|#endif
  166|  5.13k|#if (!defined ASSIMP_BUILD_NO_REMOVE_REDUNDANTMATERIALS_PROCESS)
  167|  5.13k|    out.push_back( new RemoveRedundantMatsProcess());
  168|  5.13k|#endif
  169|  5.13k|#if (!defined ASSIMP_BUILD_NO_EMBEDTEXTURES_PROCESS)
  170|  5.13k|    out.push_back( new EmbedTexturesProcess());
  171|  5.13k|#endif
  172|  5.13k|#if (!defined ASSIMP_BUILD_NO_FINDINSTANCES_PROCESS)
  173|  5.13k|    out.push_back( new FindInstancesProcess());
  174|  5.13k|#endif
  175|  5.13k|#if (!defined ASSIMP_BUILD_NO_OPTIMIZEGRAPH_PROCESS)
  176|  5.13k|    out.push_back( new OptimizeGraphProcess());
  177|  5.13k|#endif
  178|  5.13k|#ifndef ASSIMP_BUILD_NO_GENUVCOORDS_PROCESS
  179|  5.13k|    out.push_back( new ComputeUVMappingProcess());
  180|  5.13k|#endif
  181|  5.13k|#ifndef ASSIMP_BUILD_NO_TRANSFORMTEXCOORDS_PROCESS
  182|  5.13k|    out.push_back( new TextureTransformStep());
  183|  5.13k|#endif
  184|  5.13k|#if (!defined ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS)
  185|  5.13k|    out.push_back( new ScaleProcess());
  186|  5.13k|#endif
  187|  5.13k|#if (!defined ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS)
  188|  5.13k|    out.push_back( new ArmaturePopulate());
  189|  5.13k|#endif
  190|  5.13k|#if (!defined ASSIMP_BUILD_NO_PRETRANSFORMVERTICES_PROCESS)
  191|  5.13k|    out.push_back( new PretransformVertices());
  192|  5.13k|#endif
  193|  5.13k|#if (!defined ASSIMP_BUILD_NO_TRIANGULATE_PROCESS)
  194|  5.13k|    out.push_back( new TriangulateProcess());
  195|  5.13k|#endif
  196|  5.13k|#if (!defined ASSIMP_BUILD_NO_FINDDEGENERATES_PROCESS)
  197|       |    //find degenerates should run after triangulation (to sort out small
  198|       |    //generated triangles) but before sort by p types (in case there are lines
  199|       |    //and points generated and inserted into a mesh)
  200|  5.13k|    out.push_back( new FindDegeneratesProcess());
  201|  5.13k|#endif
  202|  5.13k|#if (!defined ASSIMP_BUILD_NO_SORTBYPTYPE_PROCESS)
  203|  5.13k|    out.push_back( new SortByPTypeProcess());
  204|  5.13k|#endif
  205|  5.13k|#if (!defined ASSIMP_BUILD_NO_FINDINVALIDDATA_PROCESS)
  206|  5.13k|    out.push_back( new FindInvalidDataProcess());
  207|  5.13k|#endif
  208|  5.13k|#if (!defined ASSIMP_BUILD_NO_OPTIMIZEMESHES_PROCESS)
  209|  5.13k|    out.push_back( new OptimizeMeshesProcess());
  210|  5.13k|#endif
  211|  5.13k|#if (!defined ASSIMP_BUILD_NO_FIXINFACINGNORMALS_PROCESS)
  212|  5.13k|    out.push_back( new FixInfacingNormalsProcess());
  213|  5.13k|#endif
  214|  5.13k|#if (!defined ASSIMP_BUILD_NO_SPLITBYBONECOUNT_PROCESS)
  215|  5.13k|    out.push_back( new SplitByBoneCountProcess());
  216|  5.13k|#endif
  217|  5.13k|#if (!defined ASSIMP_BUILD_NO_SPLITLARGEMESHES_PROCESS)
  218|  5.13k|    out.push_back( new SplitLargeMeshesProcess_Triangle());
  219|  5.13k|#endif
  220|  5.13k|#if (!defined ASSIMP_BUILD_NO_GENFACENORMALS_PROCESS)
  221|  5.13k|    out.push_back( new DropFaceNormalsProcess());
  222|  5.13k|#endif
  223|  5.13k|#if (!defined ASSIMP_BUILD_NO_GENFACENORMALS_PROCESS)
  224|  5.13k|    out.push_back( new GenFaceNormalsProcess());
  225|  5.13k|#endif
  226|       |    // .........................................................................
  227|       |    // DON'T change the order of these five ..
  228|       |    // XXX this is actually a design weakness that dates back to the time
  229|       |    // when Importer would maintain the postprocessing step list exclusively.
  230|       |    // Now that others access it too, we need a better solution.
  231|  5.13k|    out.push_back( new ComputeSpatialSortProcess());
  232|       |    // .........................................................................
  233|       |
  234|  5.13k|#if (!defined ASSIMP_BUILD_NO_GENVERTEXNORMALS_PROCESS)
  235|  5.13k|    out.push_back( new GenVertexNormalsProcess());
  236|  5.13k|#endif
  237|  5.13k|#if (!defined ASSIMP_BUILD_NO_CALCTANGENTS_PROCESS)
  238|  5.13k|    out.push_back( new CalcTangentsProcess());
  239|  5.13k|#endif
  240|  5.13k|#if (!defined ASSIMP_BUILD_NO_JOINVERTICES_PROCESS)
  241|  5.13k|    out.push_back( new JoinVerticesProcess());
  242|  5.13k|#endif
  243|       |
  244|       |    // .........................................................................
  245|  5.13k|    out.push_back( new DestroySpatialSortProcess());
  246|       |    // .........................................................................
  247|       |
  248|  5.13k|#if (!defined ASSIMP_BUILD_NO_SPLITLARGEMESHES_PROCESS)
  249|  5.13k|    out.push_back( new SplitLargeMeshesProcess_Vertex());
  250|  5.13k|#endif
  251|  5.13k|#if (!defined ASSIMP_BUILD_NO_DEBONE_PROCESS)
  252|  5.13k|    out.push_back( new DeboneProcess());
  253|  5.13k|#endif
  254|  5.13k|#if (!defined ASSIMP_BUILD_NO_LIMITBONEWEIGHTS_PROCESS)
  255|  5.13k|    out.push_back( new LimitBoneWeightsProcess());
  256|  5.13k|#endif
  257|  5.13k|#if (!defined ASSIMP_BUILD_NO_IMPROVECACHELOCALITY_PROCESS)
  258|  5.13k|    out.push_back( new ImproveCacheLocalityProcess());
  259|  5.13k|#endif
  260|  5.13k|#if (!defined ASSIMP_BUILD_NO_GENBOUNDINGBOXES_PROCESS)
  261|  5.13k|    out.push_back(new GenBoundingBoxesProcess);
  262|  5.13k|#endif
  263|  5.13k|}

_ZN6Assimp17ScenePreprocessor12ProcessSceneEv:
   50|  1.54k|void ScenePreprocessor::ProcessScene() {
   51|  1.54k|    ai_assert(scene != nullptr);
  ------------------
  |  |   67|  1.54k|#   define ai_assert(expression) (void)((!!(expression)) || (Assimp::aiAssertViolation(#expression, __FILE__, __LINE__), 0))
  |  |  ------------------
  |  |  |  Branch (67:41): [True: 1.54k, False: 0]
  |  |  |  Branch (67:61): [True: 0, False: 0]
  |  |  ------------------
  ------------------
   52|       |
   53|       |    // Process all meshes
   54|  2.98k|    for (unsigned int i = 0; i < scene->mNumMeshes; ++i) {
  ------------------
  |  Branch (54:30): [True: 1.43k, False: 1.54k]
  ------------------
   55|  1.43k|        if (nullptr == scene->mMeshes[i]) {
  ------------------
  |  Branch (55:13): [True: 0, False: 1.43k]
  ------------------
   56|      0|            continue;
   57|      0|        }
   58|  1.43k|        ProcessMesh(scene->mMeshes[i]);
   59|  1.43k|    }
   60|       |
   61|       |    // - nothing to do for nodes for the moment
   62|       |    // - nothing to do for textures for the moment
   63|       |    // - nothing to do for lights for the moment
   64|       |    // - nothing to do for cameras for the moment
   65|       |
   66|       |    // Process all animations
   67|  1.62k|    for (unsigned int i = 0; i < scene->mNumAnimations; ++i) {
  ------------------
  |  Branch (67:30): [True: 74, False: 1.54k]
  ------------------
   68|     74|        if (nullptr == scene->mAnimations[i]) {
  ------------------
  |  Branch (68:13): [True: 0, False: 74]
  ------------------
   69|      0|            continue;
   70|      0|        }
   71|     74|        ProcessAnimation(scene->mAnimations[i]);
   72|     74|    }
   73|       |
   74|       |    // Generate a default material if none was specified
   75|  1.54k|    if (!scene->mNumMaterials && scene->mNumMeshes) {
  ------------------
  |  Branch (75:9): [True: 0, False: 1.54k]
  |  Branch (75:34): [True: 0, False: 0]
  ------------------
   76|      0|        scene->mMaterials = new aiMaterial *[2];
   77|      0|        aiMaterial *helper;
   78|       |
   79|      0|        aiString name;
   80|       |
   81|      0|        scene->mMaterials[scene->mNumMaterials] = helper = new aiMaterial();
   82|      0|        aiColor3D clr(0.6f, 0.6f, 0.6f);
   83|      0|        helper->AddProperty(&clr, 1, AI_MATKEY_COLOR_DIFFUSE);
   84|       |
   85|       |        // setup the default name to make this material identifiable
   86|      0|        name.Set(AI_DEFAULT_MATERIAL_NAME);
   87|      0|        helper->AddProperty(&name, AI_MATKEY_NAME);
   88|       |
   89|      0|        ASSIMP_LOG_DEBUG("ScenePreprocessor: Adding default material \'" AI_DEFAULT_MATERIAL_NAME "\'");
   90|       |
   91|      0|        for (unsigned int i = 0; i < scene->mNumMeshes; ++i) {
  ------------------
  |  Branch (91:34): [True: 0, False: 0]
  ------------------
   92|      0|            if (nullptr == scene->mMeshes[i]) {
  ------------------
  |  Branch (92:17): [True: 0, False: 0]
  ------------------
   93|      0|                continue;
   94|      0|            }
   95|      0|            scene->mMeshes[i]->mMaterialIndex = scene->mNumMaterials;
   96|      0|        }
   97|       |
   98|      0|        scene->mNumMaterials++;
   99|      0|    }
  100|  1.54k|}
_ZN6Assimp17ScenePreprocessor11ProcessMeshEP6aiMesh:
  103|  1.43k|void ScenePreprocessor::ProcessMesh(aiMesh *mesh) {
  104|       |    // If aiMesh::mNumUVComponents is *not* set assign the default value of 2
  105|  12.9k|    for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
  ------------------
  |  Branch (105:30): [True: 11.4k, False: 1.43k]
  ------------------
  106|  11.4k|        if (!mesh->mTextureCoords[i]) {
  ------------------
  |  Branch (106:13): [True: 11.0k, False: 467]
  ------------------
  107|  11.0k|            mesh->mNumUVComponents[i] = 0;
  108|  11.0k|            continue;
  109|  11.0k|        }
  110|       |
  111|    467|        if (!mesh->mNumUVComponents[i]) {
  ------------------
  |  Branch (111:13): [True: 0, False: 467]
  ------------------
  112|      0|            mesh->mNumUVComponents[i] = 2;
  113|      0|        }
  114|       |
  115|    467|        aiVector3D *p = mesh->mTextureCoords[i], *end = p + mesh->mNumVertices;
  116|       |
  117|       |        // Ensure unused components are zeroed. This will make 1D texture channels work
  118|       |        // as if they were 2D channels .. just in case an application doesn't handle
  119|       |        // this case
  120|    467|        if (2 == mesh->mNumUVComponents[i]) {
  ------------------
  |  Branch (120:13): [True: 399, False: 68]
  ------------------
  121|  4.47k|            for (; p != end; ++p) {
  ------------------
  |  Branch (121:20): [True: 4.07k, False: 399]
  ------------------
  122|  4.07k|                p->z = 0.f;
  123|  4.07k|            }
  124|    399|        } else if (1 == mesh->mNumUVComponents[i]) {
  ------------------
  |  Branch (124:20): [True: 40, False: 28]
  ------------------
  125|    729|            for (; p != end; ++p) {
  ------------------
  |  Branch (125:20): [True: 689, False: 40]
  ------------------
  126|    689|                p->z = p->y = 0.f;
  127|    689|            }
  128|     40|        } else if (3 == mesh->mNumUVComponents[i]) {
  ------------------
  |  Branch (128:20): [True: 14, False: 14]
  ------------------
  129|       |            // Really 3D coordinates? Check whether the third coordinate is != 0 for at least one element
  130|    112|            for (; p != end; ++p) {
  ------------------
  |  Branch (130:20): [True: 109, False: 3]
  ------------------
  131|    109|                if (p->z != 0) {
  ------------------
  |  Branch (131:21): [True: 11, False: 98]
  ------------------
  132|     11|                    break;
  133|     11|                }
  134|    109|            }
  135|     14|            if (p == end) {
  ------------------
  |  Branch (135:17): [True: 3, False: 11]
  ------------------
  136|      3|                ASSIMP_LOG_WARN("ScenePreprocessor: UVs are declared to be 3D but they're obviously not. Reverting to 2D.");
  137|      3|                mesh->mNumUVComponents[i] = 2;
  138|      3|            }
  139|     14|        }
  140|    467|    }
  141|       |
  142|       |    // If the information which primitive types are there in the
  143|       |    // mesh is currently not available, compute it.
  144|  1.43k|    if (!mesh->mPrimitiveTypes) {
  ------------------
  |  Branch (144:9): [True: 0, False: 1.43k]
  ------------------
  145|      0|        ai_assert(mesh->mFaces != nullptr);
  ------------------
  |  |   67|      0|#   define ai_assert(expression) (void)((!!(expression)) || (Assimp::aiAssertViolation(#expression, __FILE__, __LINE__), 0))
  |  |  ------------------
  |  |  |  Branch (67:41): [True: 0, False: 0]
  |  |  |  Branch (67:61): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  146|      0|        for (unsigned int a = 0; a < mesh->mNumFaces; ++a) {
  ------------------
  |  Branch (146:34): [True: 0, False: 0]
  ------------------
  147|      0|            aiFace &face = mesh->mFaces[a];
  148|      0|            switch (face.mNumIndices) {
  149|      0|            case 3u:
  ------------------
  |  Branch (149:13): [True: 0, False: 0]
  ------------------
  150|      0|                mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
  151|      0|                break;
  152|       |
  153|      0|            case 2u:
  ------------------
  |  Branch (153:13): [True: 0, False: 0]
  ------------------
  154|      0|                mesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
  155|      0|                break;
  156|       |
  157|      0|            case 1u:
  ------------------
  |  Branch (157:13): [True: 0, False: 0]
  ------------------
  158|      0|                mesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
  159|      0|                break;
  160|       |
  161|      0|            default:
  ------------------
  |  Branch (161:13): [True: 0, False: 0]
  ------------------
  162|      0|                mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
  163|      0|                break;
  164|      0|            }
  165|      0|        }
  166|      0|    }
  167|       |
  168|       |    // If tangents and normals are given but no bitangents compute them
  169|  1.43k|    if (mesh->mTangents && mesh->mNormals && !mesh->mBitangents) {
  ------------------
  |  Branch (169:9): [True: 0, False: 1.43k]
  |  Branch (169:28): [True: 0, False: 0]
  |  Branch (169:46): [True: 0, False: 0]
  ------------------
  170|      0|        mesh->mBitangents = new aiVector3D[mesh->mNumVertices];
  171|      0|        for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
  ------------------
  |  Branch (171:34): [True: 0, False: 0]
  ------------------
  172|      0|            mesh->mBitangents[i] = mesh->mNormals[i] ^ mesh->mTangents[i];
  173|      0|        }
  174|      0|    }
  175|  1.43k|}
_ZN6Assimp17ScenePreprocessor16ProcessAnimationEP11aiAnimation:
  178|     74|void ScenePreprocessor::ProcessAnimation(aiAnimation *anim) {
  179|     74|    double first = 10e10, last = -10e10;
  180|    148|    for (unsigned int i = 0; i < anim->mNumChannels; ++i) {
  ------------------
  |  Branch (180:30): [True: 74, False: 74]
  ------------------
  181|     74|        aiNodeAnim *channel = anim->mChannels[i];
  182|       |
  183|       |        //  If the exact duration of the animation is not given
  184|       |        //  compute it now.
  185|     74|        if (anim->mDuration == -1.) {
  ------------------
  |  Branch (185:13): [True: 0, False: 74]
  ------------------
  186|       |            // Position keys
  187|      0|            for (unsigned int j = 0; j < channel->mNumPositionKeys; ++j) {
  ------------------
  |  Branch (187:38): [True: 0, False: 0]
  ------------------
  188|      0|                aiVectorKey &key = channel->mPositionKeys[j];
  189|      0|                first = std::min(first, key.mTime);
  190|      0|                last = std::max(last, key.mTime);
  191|      0|            }
  192|       |
  193|       |            // Scaling keys
  194|      0|            for (unsigned int j = 0; j < channel->mNumScalingKeys; ++j) {
  ------------------
  |  Branch (194:38): [True: 0, False: 0]
  ------------------
  195|      0|                aiVectorKey &key = channel->mScalingKeys[j];
  196|      0|                first = std::min(first, key.mTime);
  197|      0|                last = std::max(last, key.mTime);
  198|      0|            }
  199|       |
  200|       |            // Rotation keys
  201|      0|            for (unsigned int j = 0; j < channel->mNumRotationKeys; ++j) {
  ------------------
  |  Branch (201:38): [True: 0, False: 0]
  ------------------
  202|      0|                aiQuatKey &key = channel->mRotationKeys[j];
  203|      0|                first = std::min(first, key.mTime);
  204|      0|                last = std::max(last, key.mTime);
  205|      0|            }
  206|      0|        }
  207|       |
  208|       |        // Check whether the animation channel has no rotation
  209|       |        // or position tracks. In this case we generate a dummy
  210|       |        // track from the information we have in the transformation
  211|       |        // matrix of the corresponding node.
  212|     74|        if (!channel->mNumRotationKeys || !channel->mNumPositionKeys || !channel->mNumScalingKeys) {
  ------------------
  |  Branch (212:13): [True: 10, False: 64]
  |  Branch (212:43): [True: 48, False: 16]
  |  Branch (212:73): [True: 16, False: 0]
  ------------------
  213|       |            // Find the node that belongs to this animation
  214|     74|            aiNode *node = scene->mRootNode->FindNode(channel->mNodeName);
  215|     74|            if (node) // ValidateDS will complain later if 'node' is nullptr
  ------------------
  |  Branch (215:17): [True: 62, False: 12]
  ------------------
  216|     62|            {
  217|       |                // Decompose the transformation matrix of the node
  218|     62|                aiVector3D scaling, position;
  219|     62|                aiQuaternion rotation;
  220|       |
  221|     62|                node->mTransformation.Decompose(scaling, rotation, position);
  222|       |
  223|       |                // No rotation keys? Generate a dummy track
  224|     62|                if (!channel->mNumRotationKeys) {
  ------------------
  |  Branch (224:21): [True: 10, False: 52]
  ------------------
  225|     10|                    if (channel->mRotationKeys) {
  ------------------
  |  Branch (225:25): [True: 1, False: 9]
  ------------------
  226|      1|                        delete[] channel->mRotationKeys;
  227|      1|                        channel->mRotationKeys = nullptr;
  228|      1|                    }
  229|     10|                    ai_assert(!channel->mRotationKeys);
  ------------------
  |  |   67|     10|#   define ai_assert(expression) (void)((!!(expression)) || (Assimp::aiAssertViolation(#expression, __FILE__, __LINE__), 0))
  |  |  ------------------
  |  |  |  Branch (67:41): [True: 10, False: 0]
  |  |  |  Branch (67:61): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  230|     10|                    channel->mNumRotationKeys = 1;
  231|     10|                    channel->mRotationKeys = new aiQuatKey[1];
  232|     10|                    aiQuatKey &q = channel->mRotationKeys[0];
  233|       |
  234|     10|                    q.mTime = 0.;
  235|     10|                    q.mValue = rotation;
  236|       |
  237|     10|                    ASSIMP_LOG_VERBOSE_DEBUG("ScenePreprocessor: Dummy rotation track has been generated");
  238|     52|                } else {
  239|     52|                    ai_assert(channel->mRotationKeys);
  ------------------
  |  |   67|     52|#   define ai_assert(expression) (void)((!!(expression)) || (Assimp::aiAssertViolation(#expression, __FILE__, __LINE__), 0))
  |  |  ------------------
  |  |  |  Branch (67:41): [True: 52, False: 0]
  |  |  |  Branch (67:61): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  240|     52|                }
  241|       |
  242|       |                // No scaling keys? Generate a dummy track
  243|     62|                if (!channel->mNumScalingKeys) {
  ------------------
  |  Branch (243:21): [True: 62, False: 0]
  ------------------
  244|     62|                    if (channel->mScalingKeys) {
  ------------------
  |  Branch (244:25): [True: 0, False: 62]
  ------------------
  245|      0|                        delete[] channel->mScalingKeys;
  246|      0|                        channel->mScalingKeys = nullptr;
  247|      0|                    }
  248|     62|                    ai_assert(!channel->mScalingKeys);
  ------------------
  |  |   67|     62|#   define ai_assert(expression) (void)((!!(expression)) || (Assimp::aiAssertViolation(#expression, __FILE__, __LINE__), 0))
  |  |  ------------------
  |  |  |  Branch (67:41): [True: 62, False: 0]
  |  |  |  Branch (67:61): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  249|     62|                    channel->mNumScalingKeys = 1;
  250|     62|                    channel->mScalingKeys = new aiVectorKey[1];
  251|     62|                    aiVectorKey &q = channel->mScalingKeys[0];
  252|       |
  253|     62|                    q.mTime = 0.;
  254|     62|                    q.mValue = scaling;
  255|       |
  256|     62|                    ASSIMP_LOG_VERBOSE_DEBUG("ScenePreprocessor: Dummy scaling track has been generated");
  257|     62|                } else {
  258|      0|                    ai_assert(channel->mScalingKeys);
  ------------------
  |  |   67|      0|#   define ai_assert(expression) (void)((!!(expression)) || (Assimp::aiAssertViolation(#expression, __FILE__, __LINE__), 0))
  |  |  ------------------
  |  |  |  Branch (67:41): [True: 0, False: 0]
  |  |  |  Branch (67:61): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  259|      0|                }
  260|       |
  261|       |                // No position keys? Generate a dummy track
  262|     62|                if (!channel->mNumPositionKeys) {
  ------------------
  |  Branch (262:21): [True: 37, False: 25]
  ------------------
  263|     37|                    if (channel->mPositionKeys) {
  ------------------
  |  Branch (263:25): [True: 2, False: 35]
  ------------------
  264|      2|                        delete[] channel->mPositionKeys;
  265|      2|                        channel->mPositionKeys = nullptr;
  266|      2|                    }
  267|     37|                    ai_assert(!channel->mPositionKeys);
  ------------------
  |  |   67|     37|#   define ai_assert(expression) (void)((!!(expression)) || (Assimp::aiAssertViolation(#expression, __FILE__, __LINE__), 0))
  |  |  ------------------
  |  |  |  Branch (67:41): [True: 37, False: 0]
  |  |  |  Branch (67:61): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  268|     37|                    channel->mNumPositionKeys = 1;
  269|     37|                    channel->mPositionKeys = new aiVectorKey[1];
  270|     37|                    aiVectorKey &q = channel->mPositionKeys[0];
  271|       |
  272|     37|                    q.mTime = 0.;
  273|     37|                    q.mValue = position;
  274|       |
  275|     37|                    ASSIMP_LOG_VERBOSE_DEBUG("ScenePreprocessor: Dummy position track has been generated");
  276|     37|                } else {
  277|     25|                    ai_assert(channel->mPositionKeys);
  ------------------
  |  |   67|     25|#   define ai_assert(expression) (void)((!!(expression)) || (Assimp::aiAssertViolation(#expression, __FILE__, __LINE__), 0))
  |  |  ------------------
  |  |  |  Branch (67:41): [True: 25, False: 0]
  |  |  |  Branch (67:61): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  278|     25|                }
  279|     62|            }
  280|     74|        }
  281|     74|    }
  282|       |
  283|     74|    if (anim->mDuration == -1.) {
  ------------------
  |  Branch (283:9): [True: 0, False: 74]
  ------------------
  284|       |        ASSIMP_LOG_VERBOSE_DEBUG("ScenePreprocessor: Setting animation duration");
  285|      0|        anim->mDuration = last - std::min(first, 0.);
  286|      0|    }
  287|     74|}

_ZN6Assimp17ScenePreprocessorC2EP7aiScene:
   79|  1.54k|            scene(_scene) {}

_ZN6Assimp9ScenePrivEP7aiScene:
   85|  1.50k|ScenePrivateData* ScenePriv(aiScene* in) {
   86|  1.50k|    ai_assert( nullptr != in );
   87|  1.50k|    if ( nullptr == in ) {
  ------------------
  |  Branch (87:10): [True: 0, False: 1.50k]
  ------------------
   88|      0|        return nullptr;
   89|      0|    }
   90|  1.50k|    return static_cast<ScenePrivateData*>(in->mPrivate);
   91|  1.50k|}
_ZN6Assimp16ScenePrivateDataC2Ev:
   77|  3.86k|: mOrigImporter( nullptr )
   78|  3.86k|, mPPStepsApplied( 0 )
   79|  3.86k|, mIsCopy( false ) {
   80|       |    // empty
   81|  3.86k|}

_ZN6Assimp11SpatialSortC2Ev:
   69|  2.96k|        mPlaneNormal(PlaneInit),
   70|  2.96k|        mFinalized(false) {
   71|  2.96k|    mPlaneNormal.Normalize();
   72|  2.96k|}
_ZN6Assimp11SpatialSort4FillEPK10aiVector3tIfEjjb:
   77|  2.16k|        bool pFinalize /*= true */) {
   78|  2.16k|    mPositions.clear();
   79|  2.16k|    mFinalized = false;
   80|  2.16k|    Append(pPositions, pNumPositions, pElementOffset, pFinalize);
   81|  2.16k|    mFinalized = pFinalize;
   82|  2.16k|}
_ZNK6Assimp11SpatialSort17CalculateDistanceERK10aiVector3tIfE:
   85|  73.9k|ai_real SpatialSort::CalculateDistance(const aiVector3D &pPosition) const {
   86|  73.9k|    return (pPosition - mCentroid) * mPlaneNormal;
   87|  73.9k|}
_ZN6Assimp11SpatialSort8FinalizeEv:
   90|  2.16k|void SpatialSort::Finalize() {
   91|  2.16k|    const ai_real scale = 1.0f / mPositions.size();
   92|  51.1k|    for (unsigned int i = 0; i < mPositions.size(); i++) {
  ------------------
  |  Branch (92:30): [True: 49.0k, False: 2.16k]
  ------------------
   93|  49.0k|        mCentroid += scale * mPositions[i].mPosition;
   94|  49.0k|    }
   95|  51.1k|    for (unsigned int i = 0; i < mPositions.size(); i++) {
  ------------------
  |  Branch (95:30): [True: 49.0k, False: 2.16k]
  ------------------
   96|  49.0k|        mPositions[i].mDistance = CalculateDistance(mPositions[i].mPosition);
   97|  49.0k|    }
   98|  2.16k|    std::sort(mPositions.begin(), mPositions.end());
   99|  2.16k|    mFinalized = true;
  100|  2.16k|}
_ZN6Assimp11SpatialSort6AppendEPK10aiVector3tIfEjjb:
  105|  2.16k|        bool pFinalize /*= true */) {
  106|  2.16k|    ai_assert(!mFinalized && "You cannot add positions to the SpatialSort object after it has been finalized.");
  ------------------
  |  |   67|  4.32k|#   define ai_assert(expression) (void)((!!(expression)) || (Assimp::aiAssertViolation(#expression, __FILE__, __LINE__), 0))
  |  |  ------------------
  |  |  |  Branch (67:45): [True: 2.16k, False: 0]
  |  |  |  Branch (67:45): [True: 0, Folded]
  |  |  |  Branch (67:61): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  107|       |    // store references to all given positions along with their distance to the reference plane
  108|  2.16k|    const size_t initial = mPositions.size();
  109|  2.16k|    mPositions.reserve(initial + pNumPositions);
  110|  51.1k|    for (unsigned int a = 0; a < pNumPositions; a++) {
  ------------------
  |  Branch (110:30): [True: 49.0k, False: 2.16k]
  ------------------
  111|  49.0k|        const char *tempPointer = reinterpret_cast<const char *>(pPositions);
  112|  49.0k|        const aiVector3D *vec = reinterpret_cast<const aiVector3D *>(tempPointer + a * pElementOffset);
  113|  49.0k|        mPositions.emplace_back(static_cast<unsigned int>(a + initial), *vec);
  114|  49.0k|    }
  115|       |
  116|  2.16k|    if (pFinalize) {
  ------------------
  |  Branch (116:9): [True: 2.16k, False: 0]
  ------------------
  117|       |        // now sort the array ascending by distance.
  118|  2.16k|        Finalize();
  119|  2.16k|    }
  120|  2.16k|}
_ZNK6Assimp11SpatialSort13FindPositionsERK10aiVector3tIfEfRNSt3__16vectorIjNS5_9allocatorIjEEEE:
  125|  24.9k|        ai_real pRadius, std::vector<unsigned int> &poResults) const {
  126|  24.9k|    ai_assert(mFinalized && "The SpatialSort object must be finalized before FindPositions can be called.");
  ------------------
  |  |   67|  49.9k|#   define ai_assert(expression) (void)((!!(expression)) || (Assimp::aiAssertViolation(#expression, __FILE__, __LINE__), 0))
  |  |  ------------------
  |  |  |  Branch (67:45): [True: 24.9k, False: 0]
  |  |  |  Branch (67:45): [True: 0, Folded]
  |  |  |  Branch (67:61): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  127|  24.9k|    const ai_real dist = CalculateDistance(pPosition);
  128|  24.9k|    const ai_real minDist = dist - pRadius, maxDist = dist + pRadius;
  129|       |
  130|       |    // clear the array
  131|  24.9k|    poResults.clear();
  132|       |
  133|       |    // quick check for positions outside the range
  134|  24.9k|    if (mPositions.size() == 0)
  ------------------
  |  Branch (134:9): [True: 0, False: 24.9k]
  ------------------
  135|      0|        return;
  136|  24.9k|    if (maxDist < mPositions.front().mDistance)
  ------------------
  |  Branch (136:9): [True: 0, False: 24.9k]
  ------------------
  137|      0|        return;
  138|  24.9k|    if (minDist > mPositions.back().mDistance)
  ------------------
  |  Branch (138:9): [True: 0, False: 24.9k]
  ------------------
  139|      0|        return;
  140|       |
  141|       |    // do a binary search for the minimal distance to start the iteration there
  142|  24.9k|    unsigned int index = (unsigned int)mPositions.size() / 2;
  143|  24.9k|    unsigned int binaryStepSize = (unsigned int)mPositions.size() / 4;
  144|   127k|    while (binaryStepSize > 1) {
  ------------------
  |  Branch (144:12): [True: 102k, False: 24.9k]
  ------------------
  145|   102k|        if (mPositions[index].mDistance < minDist)
  ------------------
  |  Branch (145:13): [True: 41.1k, False: 61.1k]
  ------------------
  146|  41.1k|            index += binaryStepSize;
  147|  61.1k|        else
  148|  61.1k|            index -= binaryStepSize;
  149|       |
  150|   102k|        binaryStepSize /= 2;
  151|   102k|    }
  152|       |
  153|       |    // depending on the direction of the last step we need to single step a bit back or forth
  154|       |    // to find the actual beginning element of the range
  155|  44.4k|    while (index > 0 && mPositions[index].mDistance > minDist)
  ------------------
  |  Branch (155:12): [True: 39.3k, False: 5.09k]
  |  Branch (155:25): [True: 19.4k, False: 19.8k]
  ------------------
  156|  19.4k|        index--;
  157|  42.6k|    while (index < (mPositions.size() - 1) && mPositions[index].mDistance < minDist)
  ------------------
  |  Branch (157:12): [True: 42.2k, False: 339]
  |  Branch (157:47): [True: 17.6k, False: 24.6k]
  ------------------
  158|  17.6k|        index++;
  159|       |
  160|       |    // Mow start iterating from there until the first position lays outside of the distance range.
  161|       |    // Add all positions inside the distance range within the given radius to the result array
  162|  24.9k|    std::vector<Entry>::const_iterator it = mPositions.begin() + index;
  163|  24.9k|    const ai_real pSquared = pRadius * pRadius;
  164|   223k|    while (it->mDistance < maxDist) {
  ------------------
  |  Branch (164:12): [True: 203k, False: 20.2k]
  ------------------
  165|   203k|        if ((it->mPosition - pPosition).SquareLength() < pSquared)
  ------------------
  |  Branch (165:13): [True: 59.8k, False: 143k]
  ------------------
  166|  59.8k|            poResults.push_back(it->mIndex);
  167|   203k|        ++it;
  168|   203k|        if (it == mPositions.end())
  ------------------
  |  Branch (168:13): [True: 4.67k, False: 198k]
  ------------------
  169|  4.67k|            break;
  170|   203k|    }
  171|       |
  172|       |    // that's it
  173|  24.9k|}

aiGetVersionMinor:
   72|  5.13k|ASSIMP_API unsigned int aiGetVersionMinor() {
   73|  5.13k|    return VER_MINOR;
  ------------------
  |  |    8|  5.13k|#define VER_MINOR 0
  ------------------
   74|  5.13k|}
aiGetVersionMajor:
   78|  5.13k|ASSIMP_API unsigned int aiGetVersionMajor() {
   79|  5.13k|    return VER_MAJOR;
  ------------------
  |  |    7|  5.13k|#define VER_MAJOR 6
  ------------------
   80|  5.13k|}
aiGetCompileFlags:
   84|  5.13k|ASSIMP_API unsigned int aiGetCompileFlags() {
   85|       |
   86|  5.13k|    unsigned int flags = 0;
   87|       |
   88|       |#ifdef ASSIMP_BUILD_BOOST_WORKAROUND
   89|       |    flags |= ASSIMP_CFLAGS_NOBOOST;
   90|       |#endif
   91|  5.13k|#ifdef ASSIMP_BUILD_SINGLETHREADED
   92|  5.13k|    flags |= ASSIMP_CFLAGS_SINGLETHREADED;
  ------------------
  |  |  107|  5.13k|#define ASSIMP_CFLAGS_SINGLETHREADED    0x10
  ------------------
   93|  5.13k|#endif
   94|  5.13k|#ifdef ASSIMP_BUILD_DEBUG
   95|  5.13k|    flags |= ASSIMP_CFLAGS_DEBUG;
  ------------------
  |  |  102|  5.13k|#define ASSIMP_CFLAGS_DEBUG   0x4
  ------------------
   96|  5.13k|#endif
   97|       |#ifdef ASSIMP_BUILD_DLL_EXPORT
   98|       |    flags |= ASSIMP_CFLAGS_SHARED;
   99|       |#endif
  100|       |#ifdef _STLPORT_VERSION
  101|       |    flags |= ASSIMP_CFLAGS_STLPORT;
  102|       |#endif
  103|       |#ifdef ASSIMP_DOUBLE_PRECISION
  104|       |    flags |= ASSIMP_CFLAGS_DOUBLE_SUPPORT;
  105|       |#endif
  106|       |
  107|  5.13k|    return flags;
  108|  5.13k|}
aiGetVersionRevision:
  111|  5.13k|ASSIMP_API unsigned int aiGetVersionRevision() {
  112|  5.13k|    return GitVersion;
  ------------------
  |  |    4|  5.13k|#define GitVersion 0x8ff00557
  ------------------
  113|  5.13k|}

_ZN6Assimp23VertexTriangleAdjacencyC2EP6aiFacejjb:
   55|    371|        bool bComputeNumTriangles /*= false*/) {
   56|       |    // compute the number of referenced vertices if it wasn't specified by the caller
   57|    371|    const aiFace *const pcFaceEnd = pcFaces + iNumFaces;
   58|    371|    if (0 == iNumVertices) {
  ------------------
  |  Branch (58:9): [True: 0, False: 371]
  ------------------
   59|      0|        for (aiFace *pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace) {
  ------------------
  |  Branch (59:40): [True: 0, False: 0]
  ------------------
   60|      0|            ai_assert(nullptr != pcFace);
   61|      0|            ai_assert(3 == pcFace->mNumIndices);
   62|      0|            iNumVertices = std::max(iNumVertices, pcFace->mIndices[0]);
   63|      0|            iNumVertices = std::max(iNumVertices, pcFace->mIndices[1]);
   64|      0|            iNumVertices = std::max(iNumVertices, pcFace->mIndices[2]);
   65|      0|        }
   66|      0|    }
   67|       |
   68|    371|    mNumVertices = iNumVertices + 1;
   69|       |
   70|    371|    unsigned int *pi;
   71|       |
   72|       |    // allocate storage
   73|    371|    if (bComputeNumTriangles) {
  ------------------
  |  Branch (73:9): [True: 371, False: 0]
  ------------------
   74|    371|        pi = mLiveTriangles = new unsigned int[iNumVertices + 1];
   75|    371|        ::memset(mLiveTriangles, 0, sizeof(unsigned int) * (iNumVertices + 1));
   76|    371|        mOffsetTable = new unsigned int[iNumVertices + 2] + 1;
   77|    371|    } else {
   78|      0|        pi = mOffsetTable = new unsigned int[iNumVertices + 2] + 1;
   79|      0|        ::memset(mOffsetTable, 0, sizeof(unsigned int) * (iNumVertices + 1));
   80|      0|        mLiveTriangles = nullptr; // important, otherwise the d'tor would crash
   81|      0|    }
   82|       |
   83|       |    // get a pointer to the end of the buffer
   84|    371|    unsigned int *piEnd = pi + iNumVertices;
   85|    371|    *piEnd++ = 0u;
   86|       |
   87|       |    // first pass: compute the number of faces referencing each vertex
   88|  10.2k|    for (aiFace *pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace) {
  ------------------
  |  Branch (88:36): [True: 9.86k, False: 371]
  ------------------
   89|  9.86k|        unsigned nind = pcFace->mNumIndices;
   90|  9.86k|        unsigned *ind = pcFace->mIndices;
   91|  9.86k|        if (nind > 0) pi[ind[0]]++;
  ------------------
  |  Branch (91:13): [True: 9.86k, False: 0]
  ------------------
   92|  9.86k|        if (nind > 1) pi[ind[1]]++;
  ------------------
  |  Branch (92:13): [True: 9.86k, False: 0]
  ------------------
   93|  9.86k|        if (nind > 2) pi[ind[2]]++;
  ------------------
  |  Branch (93:13): [True: 9.86k, False: 0]
  ------------------
   94|  9.86k|    }
   95|       |
   96|       |    // second pass: compute the final offset table
   97|    371|    unsigned int iSum = 0;
   98|    371|    unsigned int *piCurOut = this->mOffsetTable;
   99|  10.2k|    for (unsigned int *piCur = pi; piCur != piEnd; ++piCur, ++piCurOut) {
  ------------------
  |  Branch (99:36): [True: 9.91k, False: 371]
  ------------------
  100|       |
  101|  9.91k|        unsigned int iLastSum = iSum;
  102|  9.91k|        iSum += *piCur;
  103|  9.91k|        *piCurOut = iLastSum;
  104|  9.91k|    }
  105|    371|    pi = this->mOffsetTable;
  106|       |
  107|       |    // third pass: compute the final table
  108|    371|    this->mAdjacencyTable = new unsigned int[iSum];
  109|    371|    iSum = 0;
  110|  10.2k|    for (aiFace *pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace, ++iSum) {
  ------------------
  |  Branch (110:36): [True: 9.86k, False: 371]
  ------------------
  111|  9.86k|        unsigned nind = pcFace->mNumIndices;
  112|  9.86k|        unsigned *ind = pcFace->mIndices;
  113|       |
  114|  9.86k|        if (nind > 0) mAdjacencyTable[pi[ind[0]]++] = iSum;
  ------------------
  |  Branch (114:13): [True: 9.86k, False: 0]
  ------------------
  115|  9.86k|        if (nind > 1) mAdjacencyTable[pi[ind[1]]++] = iSum;
  ------------------
  |  Branch (115:13): [True: 9.86k, False: 0]
  ------------------
  116|  9.86k|        if (nind > 2) mAdjacencyTable[pi[ind[2]]++] = iSum;
  ------------------
  |  Branch (116:13): [True: 9.86k, False: 0]
  ------------------
  117|  9.86k|    }
  118|       |    // fourth pass: undo the offset computations made during the third pass
  119|       |    // We could do this in a separate buffer, but this would be TIMES slower.
  120|    371|    --mOffsetTable;
  121|    371|    *mOffsetTable = 0u;
  122|    371|}
_ZN6Assimp23VertexTriangleAdjacencyD2Ev:
  124|    371|VertexTriangleAdjacency::~VertexTriangleAdjacency() {
  125|       |    // delete allocated storage
  126|    371|    delete[] mOffsetTable;
  127|    371|    delete[] mAdjacencyTable;
  128|    371|    delete[] mLiveTriangles;
  129|    371|}

_ZNK6Assimp23VertexTriangleAdjacency20GetAdjacentTrianglesEj:
   85|  4.65k|    unsigned int* GetAdjacentTriangles(unsigned int iVertIndex) const {
   86|       |        ai_assert(iVertIndex < mNumVertices);
   87|  4.65k|        return &mAdjacencyTable[ mOffsetTable[iVertIndex]];
   88|  4.65k|    }

aiTextureTypeToString:
   49|  44.5k|const char *aiTextureTypeToString(aiTextureType in) {
   50|  44.5k|    switch (in) {
   51|      0|    case aiTextureType_NONE:
  ------------------
  |  Branch (51:5): [True: 0, False: 44.5k]
  ------------------
   52|      0|        return "n/a";
   53|  2.62k|    case aiTextureType_DIFFUSE:
  ------------------
  |  Branch (53:5): [True: 2.62k, False: 41.9k]
  ------------------
   54|  2.62k|        return "Diffuse";
   55|  2.62k|    case aiTextureType_SPECULAR:
  ------------------
  |  Branch (55:5): [True: 2.62k, False: 41.9k]
  ------------------
   56|  2.62k|        return "Specular";
   57|  2.62k|    case aiTextureType_AMBIENT:
  ------------------
  |  Branch (57:5): [True: 2.62k, False: 41.9k]
  ------------------
   58|  2.62k|        return "Ambient";
   59|  2.62k|    case aiTextureType_EMISSIVE:
  ------------------
  |  Branch (59:5): [True: 2.62k, False: 41.9k]
  ------------------
   60|  2.62k|        return "Emissive";
   61|  2.62k|    case aiTextureType_OPACITY:
  ------------------
  |  Branch (61:5): [True: 2.62k, False: 41.9k]
  ------------------
   62|  2.62k|        return "Opacity";
   63|  2.62k|    case aiTextureType_NORMALS:
  ------------------
  |  Branch (63:5): [True: 2.62k, False: 41.9k]
  ------------------
   64|  2.62k|        return "Normals";
   65|  2.62k|    case aiTextureType_HEIGHT:
  ------------------
  |  Branch (65:5): [True: 2.62k, False: 41.9k]
  ------------------
   66|  2.62k|        return "Height";
   67|  2.62k|    case aiTextureType_SHININESS:
  ------------------
  |  Branch (67:5): [True: 2.62k, False: 41.9k]
  ------------------
   68|  2.62k|        return "Shininess";
   69|  2.62k|    case aiTextureType_DISPLACEMENT:
  ------------------
  |  Branch (69:5): [True: 2.62k, False: 41.9k]
  ------------------
   70|  2.62k|        return "Displacement";
   71|  2.62k|    case aiTextureType_LIGHTMAP:
  ------------------
  |  Branch (71:5): [True: 2.62k, False: 41.9k]
  ------------------
   72|  2.62k|        return "Lightmap";
   73|  2.62k|    case aiTextureType_REFLECTION:
  ------------------
  |  Branch (73:5): [True: 2.62k, False: 41.9k]
  ------------------
   74|  2.62k|        return "Reflection";
   75|  2.62k|    case aiTextureType_BASE_COLOR:
  ------------------
  |  Branch (75:5): [True: 2.62k, False: 41.9k]
  ------------------
   76|  2.62k|        return "BaseColor";
   77|  2.62k|    case aiTextureType_NORMAL_CAMERA:
  ------------------
  |  Branch (77:5): [True: 2.62k, False: 41.9k]
  ------------------
   78|  2.62k|        return "NormalCamera";
   79|  2.62k|    case aiTextureType_EMISSION_COLOR:
  ------------------
  |  Branch (79:5): [True: 2.62k, False: 41.9k]
  ------------------
   80|  2.62k|        return "EmissionColor";
   81|  2.62k|    case aiTextureType_METALNESS:
  ------------------
  |  Branch (81:5): [True: 2.62k, False: 41.9k]
  ------------------
   82|  2.62k|        return "Metalness";
   83|  2.62k|    case aiTextureType_DIFFUSE_ROUGHNESS:
  ------------------
  |  Branch (83:5): [True: 2.62k, False: 41.9k]
  ------------------
   84|  2.62k|        return "DiffuseRoughness";
   85|  2.62k|    case aiTextureType_AMBIENT_OCCLUSION:
  ------------------
  |  Branch (85:5): [True: 2.62k, False: 41.9k]
  ------------------
   86|  2.62k|        return "AmbientOcclusion";
   87|      0|    case aiTextureType_SHEEN:
  ------------------
  |  Branch (87:5): [True: 0, False: 44.5k]
  ------------------
   88|      0|        return "Sheen";
   89|      0|    case aiTextureType_CLEARCOAT:
  ------------------
  |  Branch (89:5): [True: 0, False: 44.5k]
  ------------------
   90|      0|        return "Clearcoat";
   91|      0|    case aiTextureType_TRANSMISSION:
  ------------------
  |  Branch (91:5): [True: 0, False: 44.5k]
  ------------------
   92|      0|        return "Transmission";
   93|      0|    case aiTextureType_MAYA_BASE:
  ------------------
  |  Branch (93:5): [True: 0, False: 44.5k]
  ------------------
   94|      0|        return "MayaBase";
   95|      0|    case aiTextureType_MAYA_SPECULAR:
  ------------------
  |  Branch (95:5): [True: 0, False: 44.5k]
  ------------------
   96|      0|        return "MayaSpecular";
   97|      0|    case aiTextureType_MAYA_SPECULAR_COLOR:
  ------------------
  |  Branch (97:5): [True: 0, False: 44.5k]
  ------------------
   98|      0|        return "MayaSpecularColor";
   99|      0|    case aiTextureType_MAYA_SPECULAR_ROUGHNESS:
  ------------------
  |  Branch (99:5): [True: 0, False: 44.5k]
  ------------------
  100|      0|        return "MayaSpecularRoughness";
  101|      0|    case aiTextureType_ANISOTROPY:
  ------------------
  |  Branch (101:5): [True: 0, False: 44.5k]
  ------------------
  102|      0|        return "Anisotropy";
  103|      0|    case aiTextureType_GLTF_METALLIC_ROUGHNESS:
  ------------------
  |  Branch (103:5): [True: 0, False: 44.5k]
  ------------------
  104|      0|        return "glTFMetallicRoughness";
  105|      0|    case aiTextureType_UNKNOWN:
  ------------------
  |  Branch (105:5): [True: 0, False: 44.5k]
  ------------------
  106|      0|        return "Unknown";
  107|      0|    default:
  ------------------
  |  Branch (107:5): [True: 0, False: 44.5k]
  ------------------
  108|      0|        break;
  109|  44.5k|    }
  110|      0|    ai_assert(false);
  ------------------
  |  |   67|      0|#   define ai_assert(expression) (void)((!!(expression)) || (Assimp::aiAssertViolation(#expression, __FILE__, __LINE__), 0))
  |  |  ------------------
  |  |  |  Branch (67:41): [Folded, False: 0]
  |  |  |  Branch (67:61): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  111|      0|    return "BUG";
  112|  44.5k|}

_ZN7aiSceneC2Ev:
   46|  3.86k|        mFlags(0),
   47|  3.86k|        mRootNode(nullptr),
   48|  3.86k|        mNumMeshes(0),
   49|  3.86k|        mMeshes(nullptr),
   50|  3.86k|        mNumMaterials(0),
   51|  3.86k|        mMaterials(nullptr),
   52|  3.86k|        mNumAnimations(0),
   53|  3.86k|        mAnimations(nullptr),
   54|  3.86k|        mNumTextures(0),
   55|  3.86k|        mTextures(nullptr),
   56|  3.86k|        mNumLights(0),
   57|  3.86k|        mLights(nullptr),
   58|  3.86k|        mNumCameras(0),
   59|  3.86k|        mCameras(nullptr),
   60|  3.86k|        mMetaData(nullptr),
   61|  3.86k|        mName(),
   62|  3.86k|        mNumSkeletons(0),
   63|  3.86k|        mSkeletons(nullptr),
   64|  3.86k|        mPrivate(new Assimp::ScenePrivateData()) {
   65|       |    // empty
   66|  3.86k|}
_ZN7aiSceneD2Ev:
   68|  3.86k|aiScene::~aiScene() {
   69|       |    // delete all sub-objects recursively
   70|  3.86k|    delete mRootNode;
   71|       |
   72|       |    // To make sure we won't crash if the data is invalid it's
   73|       |    // much better to check whether both mNumXXX and mXXX are
   74|       |    // valid instead of relying on just one of them.
   75|  3.86k|    if (mNumMeshes && mMeshes) {
  ------------------
  |  Branch (75:9): [True: 1.38k, False: 2.47k]
  |  Branch (75:23): [True: 1.38k, False: 0]
  ------------------
   76|  3.79k|        for (unsigned int a = 0; a < mNumMeshes; ++a) {
  ------------------
  |  Branch (76:34): [True: 2.40k, False: 1.38k]
  ------------------
   77|  2.40k|            delete mMeshes[a];
   78|  2.40k|        }
   79|  1.38k|    }
   80|  3.86k|    delete[] mMeshes;
   81|       |
   82|  3.86k|    if (mNumMaterials && mMaterials) {
  ------------------
  |  Branch (82:9): [True: 2.35k, False: 1.50k]
  |  Branch (82:26): [True: 2.35k, False: 0]
  ------------------
   83|  6.03k|        for (unsigned int a = 0; a < mNumMaterials; ++a) {
  ------------------
  |  Branch (83:34): [True: 3.67k, False: 2.35k]
  ------------------
   84|  3.67k|            delete mMaterials[a];
   85|  3.67k|        }
   86|  2.35k|    }
   87|  3.86k|    delete[] mMaterials;
   88|       |
   89|  3.86k|    if (mNumAnimations && mAnimations) {
  ------------------
  |  Branch (89:9): [True: 198, False: 3.66k]
  |  Branch (89:27): [True: 198, False: 0]
  ------------------
   90|    455|        for (unsigned int a = 0; a < mNumAnimations; ++a) {
  ------------------
  |  Branch (90:34): [True: 257, False: 198]
  ------------------
   91|    257|            delete mAnimations[a];
   92|    257|        }
   93|    198|    }
   94|  3.86k|    delete[] mAnimations;
   95|       |
   96|  3.86k|    if (mNumTextures && mTextures) {
  ------------------
  |  Branch (96:9): [True: 111, False: 3.75k]
  |  Branch (96:25): [True: 111, False: 0]
  ------------------
   97|    222|        for (unsigned int a = 0; a < mNumTextures; ++a) {
  ------------------
  |  Branch (97:34): [True: 111, False: 111]
  ------------------
   98|    111|            delete mTextures[a];
   99|    111|        }
  100|    111|    }
  101|  3.86k|    delete[] mTextures;
  102|       |
  103|  3.86k|    if (mNumLights && mLights) {
  ------------------
  |  Branch (103:9): [True: 0, False: 3.86k]
  |  Branch (103:23): [True: 0, False: 0]
  ------------------
  104|      0|        for (unsigned int a = 0; a < mNumLights; ++a) {
  ------------------
  |  Branch (104:34): [True: 0, False: 0]
  ------------------
  105|      0|            delete mLights[a];
  106|      0|        }
  107|      0|    }
  108|  3.86k|    delete[] mLights;
  109|       |
  110|  3.86k|    if (mNumCameras && mCameras) {
  ------------------
  |  Branch (110:9): [True: 35, False: 3.82k]
  |  Branch (110:24): [True: 35, False: 0]
  ------------------
  111|     85|        for (unsigned int a = 0; a < mNumCameras; ++a) {
  ------------------
  |  Branch (111:34): [True: 50, False: 35]
  ------------------
  112|     50|            delete mCameras[a];
  113|     50|        }
  114|     35|    }
  115|  3.86k|    delete[] mCameras;
  116|       |
  117|  3.86k|    aiMetadata::Dealloc(mMetaData);
  118|       |
  119|  3.86k|    delete[] mSkeletons;
  120|       |
  121|  3.86k|    delete static_cast<Assimp::ScenePrivateData *>(mPrivate);
  122|  3.86k|}
_ZN6aiNodeC2ERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  136|  7.73k|        mName(name),
  137|  7.73k|        mParent(nullptr),
  138|  7.73k|        mNumChildren(0),
  139|  7.73k|        mChildren(nullptr),
  140|  7.73k|        mNumMeshes(0),
  141|  7.73k|        mMeshes(nullptr),
  142|  7.73k|        mMetaData(nullptr) {
  143|       |    // empty
  144|  7.73k|}
_ZN6aiNodeD2Ev:
  147|  7.73k|aiNode::~aiNode() {
  148|       |    // delete all children recursively
  149|       |    // to make sure we won't crash if the data is invalid ...
  150|  7.73k|    if (mNumChildren && mChildren) {
  ------------------
  |  Branch (150:9): [True: 3.66k, False: 4.06k]
  |  Branch (150:25): [True: 3.66k, False: 0]
  ------------------
  151|  9.60k|        for (unsigned int a = 0; a < mNumChildren; a++)
  ------------------
  |  Branch (151:34): [True: 5.93k, False: 3.66k]
  ------------------
  152|  5.93k|            delete mChildren[a];
  153|  3.66k|    }
  154|  7.73k|    delete[] mChildren;
  155|  7.73k|    delete[] mMeshes;
  156|  7.73k|    delete mMetaData;
  157|  7.73k|}
_ZN6aiNode8FindNodeEPKc:
  176|    179|aiNode *aiNode::FindNode(const char *name) {
  177|    179|    if (!::strcmp(mName.data, name)) return this;
  ------------------
  |  Branch (177:9): [True: 62, False: 117]
  ------------------
  178|    120|    for (unsigned int i = 0; i < mNumChildren; ++i) {
  ------------------
  |  Branch (178:30): [True: 105, False: 15]
  ------------------
  179|    105|        aiNode *const p = mChildren[i]->FindNode(name);
  180|    105|        if (p) {
  ------------------
  |  Branch (180:13): [True: 102, False: 3]
  ------------------
  181|    102|            return p;
  182|    102|        }
  183|    105|    }
  184|       |    // there is definitely no sub-node with this name
  185|     15|    return nullptr;
  186|    117|}

_ZN6Assimp13GeometryUtils5heronEfff:
   49|  36.2k|ai_real GeometryUtils::heron( ai_real a, ai_real b, ai_real c ) {
   50|  36.2k|    const ai_real s    = (a + b + c) * 0.5;
   51|  36.2k|    const ai_real area = pow((s * ( s - a ) * ( s - b ) * ( s - c ) ), static_cast<ai_real>(0.5));
   52|  36.2k|    return area;
   53|  36.2k|}
_ZN6Assimp13GeometryUtils10distance3DERK10aiVector3tIfES4_:
   56|   108k|ai_real GeometryUtils::distance3D( const aiVector3D &vA, const aiVector3D &vB ) {
   57|   108k|    const ai_real lx = ( vB.x - vA.x );
   58|   108k|    const ai_real ly = ( vB.y - vA.y );
   59|   108k|    const ai_real lz = ( vB.z - vA.z );
   60|   108k|    const ai_real a  = lx*lx + ly*ly + lz*lz;
   61|   108k|    const ai_real d  = pow( a, static_cast<ai_real>(0.5));
   62|       |
   63|   108k|    return d;
   64|   108k|}
_ZN6Assimp13GeometryUtils23calculateAreaOfTriangleERK6aiFaceP6aiMesh:
   67|  36.2k|ai_real GeometryUtils::calculateAreaOfTriangle( const aiFace& face, aiMesh* mesh ) {
   68|  36.2k|    ai_real area = 0;
   69|  36.2k|    if (mesh == nullptr) {
  ------------------
  |  Branch (69:9): [True: 0, False: 36.2k]
  ------------------
   70|      0|        return area;
   71|      0|    }
   72|       |
   73|  36.2k|    const aiVector3D vA( mesh->mVertices[ face.mIndices[ 0 ] ] );
   74|  36.2k|    const aiVector3D vB( mesh->mVertices[ face.mIndices[ 1 ] ] );
   75|  36.2k|    const aiVector3D vC( mesh->mVertices[ face.mIndices[ 2 ] ] );
   76|       |
   77|  36.2k|    const ai_real a = distance3D( vA, vB );
   78|  36.2k|    const ai_real b = distance3D( vB, vC );
   79|  36.2k|    const ai_real c = distance3D( vC, vA );
   80|  36.2k|    area = heron( a, b, c );
   81|       |
   82|  36.2k|    return area;
   83|  36.2k|}

aiGetMaterialProperty:
   63|  5.26k|        const aiMaterialProperty **pPropOut) {
   64|  5.26k|    ai_assert(pMat != nullptr);
   65|  5.26k|    ai_assert(pKey != nullptr);
   66|  5.26k|    ai_assert(pPropOut != nullptr);
   67|       |
   68|       |    /*  Just search for a property with exactly this name ..
   69|       |     *  could be improved by hashing, but it's possibly
   70|       |     *  no worth the effort (we're bound to C structures,
   71|       |     *  thus std::map or derivates are not applicable. */
   72|  55.8k|    for (unsigned int i = 0; i < pMat->mNumProperties; ++i) {
  ------------------
  |  Branch (72:30): [True: 55.7k, False: 44]
  ------------------
   73|  55.7k|        aiMaterialProperty *prop = pMat->mProperties[i];
   74|       |
   75|  55.7k|        if (prop /* just for safety ... */
  ------------------
  |  Branch (75:13): [True: 55.7k, False: 0]
  ------------------
   76|  55.7k|                && 0 == strncmp(prop->mKey.data, pKey, strlen(pKey)) && (UINT_MAX == type || prop->mSemantic == type) /* UINT_MAX is a wild-card, but this is undocumented :-) */
  ------------------
  |  Branch (76:20): [True: 5.21k, False: 50.5k]
  |  Branch (76:74): [True: 0, False: 5.21k]
  |  Branch (76:94): [True: 5.21k, False: 0]
  ------------------
   77|  5.21k|                && (UINT_MAX == index || prop->mIndex == index)) {
  ------------------
  |  Branch (77:21): [True: 0, False: 5.21k]
  |  Branch (77:42): [True: 5.21k, False: 0]
  ------------------
   78|  5.21k|            *pPropOut = pMat->mProperties[i];
   79|  5.21k|            return AI_SUCCESS;
   80|  5.21k|        }
   81|  55.7k|    }
   82|     44|    *pPropOut = nullptr;
   83|       |
   84|       |    return AI_FAILURE;
   85|  5.26k|}
aiGetMaterialFloatArray:
  194|  2.62k|        unsigned int *pMax) {
  195|  2.62k|    return GetMaterialFloatArray(pMat, pKey, type, index, pOut, pMax);
  196|  2.62k|}
aiGetMaterialIntegerArray:
  205|  2.62k|        unsigned int *pMax) {
  206|  2.62k|    ai_assert(pOut != nullptr);
  207|  2.62k|    ai_assert(pMat != nullptr);
  208|       |
  209|  2.62k|    const aiMaterialProperty *prop;
  210|  2.62k|    aiGetMaterialProperty(pMat, pKey, type, index, &prop);
  211|  2.62k|    if (!prop) {
  ------------------
  |  Branch (211:9): [True: 18, False: 2.60k]
  ------------------
  212|     18|        return AI_FAILURE;
  213|     18|    }
  214|       |
  215|       |    // data is given in ints, simply copy it
  216|  2.60k|    unsigned int iWrite = 0;
  217|  2.60k|    if (aiPTI_Integer == prop->mType || aiPTI_Buffer == prop->mType) {
  ------------------
  |  Branch (217:9): [True: 0, False: 2.60k]
  |  Branch (217:41): [True: 2.60k, False: 0]
  ------------------
  218|  2.60k|        iWrite = std::max(static_cast<unsigned int>(prop->mDataLength / sizeof(int32_t)), 1u);
  219|  2.60k|        if (pMax) {
  ------------------
  |  Branch (219:13): [True: 0, False: 2.60k]
  ------------------
  220|      0|            iWrite = std::min(*pMax, iWrite);
  221|      0|        }
  222|  2.60k|        if (1 == prop->mDataLength) {
  ------------------
  |  Branch (222:13): [True: 0, False: 2.60k]
  ------------------
  223|       |            // bool type, 1 byte
  224|      0|            *pOut = static_cast<int>(*prop->mData);
  225|  2.60k|        } else {
  226|  5.20k|            for (unsigned int a = 0; a < iWrite; ++a) {
  ------------------
  |  Branch (226:38): [True: 2.60k, False: 2.60k]
  ------------------
  227|  2.60k|                pOut[a] = static_cast<int>(reinterpret_cast<int32_t *>(prop->mData)[a]);
  228|  2.60k|            }
  229|  2.60k|        }
  230|  2.60k|        if (pMax) {
  ------------------
  |  Branch (230:13): [True: 0, False: 2.60k]
  ------------------
  231|      0|            *pMax = iWrite;
  232|      0|        }
  233|  2.60k|    }
  234|       |    // data is given in floats convert to int
  235|      0|    else if (aiPTI_Float == prop->mType) {
  ------------------
  |  Branch (235:14): [True: 0, False: 0]
  ------------------
  236|      0|        iWrite = prop->mDataLength / sizeof(float);
  237|      0|        if (pMax) {
  ------------------
  |  Branch (237:13): [True: 0, False: 0]
  ------------------
  238|      0|            iWrite = std::min(*pMax, iWrite);
  239|      0|            ;
  240|      0|        }
  241|      0|        for (unsigned int a = 0; a < iWrite; ++a) {
  ------------------
  |  Branch (241:34): [True: 0, False: 0]
  ------------------
  242|      0|            pOut[a] = static_cast<int>(reinterpret_cast<float *>(prop->mData)[a]);
  243|      0|        }
  244|      0|        if (pMax) {
  ------------------
  |  Branch (244:13): [True: 0, False: 0]
  ------------------
  245|      0|            *pMax = iWrite;
  246|      0|        }
  247|      0|    }
  248|       |    // it is a string ... no way to read something out of this
  249|      0|    else {
  250|      0|        if (pMax) {
  ------------------
  |  Branch (250:13): [True: 0, False: 0]
  ------------------
  251|      0|            iWrite = *pMax;
  252|      0|        }
  253|       |        // strings are zero-terminated with a 32 bit length prefix, so this is safe
  254|      0|        const char *cur = prop->mData + 4;
  255|      0|        ai_assert(prop->mDataLength >= 5);
  256|      0|        ai_assert(!prop->mData[prop->mDataLength - 1]);
  257|      0|        for (unsigned int a = 0;; ++a) {
  258|      0|            pOut[a] = strtol10(cur, &cur);
  259|      0|            if (a == iWrite - 1) {
  ------------------
  |  Branch (259:17): [True: 0, False: 0]
  ------------------
  260|      0|                break;
  261|      0|            }
  262|      0|            if (!IsSpace(*cur)) {
  ------------------
  |  Branch (262:17): [True: 0, False: 0]
  ------------------
  263|      0|                ASSIMP_LOG_ERROR("Material property", pKey,
  264|      0|                                 " is a string; failed to parse an integer array out of it.");
  265|      0|                return AI_FAILURE;
  266|      0|            }
  267|      0|        }
  268|       |
  269|      0|        if (pMax) {
  ------------------
  |  Branch (269:13): [True: 0, False: 0]
  ------------------
  270|      0|            *pMax = iWrite;
  271|      0|        }
  272|      0|    }
  273|  2.60k|    return AI_SUCCESS;
  274|  2.60k|}
aiGetMaterialString:
  311|     20|        aiString *pOut) {
  312|     20|    ai_assert(pOut != nullptr);
  313|       |
  314|     20|    const aiMaterialProperty *prop{nullptr};
  315|     20|    aiGetMaterialProperty(pMat, pKey, type, index, &prop);
  316|     20|    if (!prop) {
  ------------------
  |  Branch (316:9): [True: 8, False: 12]
  ------------------
  317|      8|        return AI_FAILURE;
  318|      8|    }
  319|       |
  320|     12|    if (aiPTI_String == prop->mType) {
  ------------------
  |  Branch (320:9): [True: 12, False: 0]
  ------------------
  321|     12|        ai_assert(prop->mDataLength >= 5);
  322|       |
  323|       |        // The string is stored as 32 but length prefix followed by zero-terminated UTF8 data
  324|     12|        pOut->length = static_cast<unsigned int>(*reinterpret_cast<uint32_t *>(prop->mData));
  325|       |
  326|     12|        ai_assert(pOut->length + 1 + 4 == prop->mDataLength);
  327|     12|        ai_assert(!prop->mData[prop->mDataLength - 1]);
  328|     12|        memcpy(pOut->data, prop->mData + 4, pOut->length + 1);
  329|     12|    } else {
  330|       |        // TODO - implement lexical cast as well
  331|      0|        ASSIMP_LOG_ERROR("Material property", pKey, " was found, but is no string");
  332|      0|        return AI_FAILURE;
  333|      0|    }
  334|     12|    return AI_SUCCESS;
  335|     12|}
_ZN10aiMaterialC2Ev:
  418|  4.91k|aiMaterial::aiMaterial() : mProperties(nullptr), mNumProperties(0), mNumAllocated(DefaultNumAllocated) {
  419|       |    // Allocate 5 entries by default
  420|  4.91k|    mProperties = new aiMaterialProperty *[DefaultNumAllocated];
  421|  4.91k|}
_ZN10aiMaterialD2Ev:
  424|  4.91k|aiMaterial::~aiMaterial() {
  425|  4.91k|    Clear();
  426|       |
  427|  4.91k|    delete[] mProperties;
  428|  4.91k|}
_ZN10aiMaterial5ClearEv:
  439|  4.91k|void aiMaterial::Clear() {
  440|  60.0k|    for (unsigned int i = 0; i < mNumProperties; ++i) {
  ------------------
  |  Branch (440:30): [True: 55.0k, False: 4.91k]
  ------------------
  441|       |        // delete this entry
  442|  55.0k|        delete mProperties[i];
  443|  55.0k|        AI_DEBUG_INVALIDATE_PTR(mProperties[i]);
  444|  55.0k|    }
  445|  4.91k|    mNumProperties = 0;
  446|       |
  447|       |    // The array remains allocated, we just invalidated its contents
  448|  4.91k|}
_ZN10aiMaterial17AddBinaryPropertyEPKvjPKcjj18aiPropertyTypeInfo:
  480|  55.0k|        aiPropertyTypeInfo pType) {
  481|  55.0k|    ai_assert(pInput != nullptr);
  482|  55.0k|    ai_assert(pKey != nullptr);
  483|  55.0k|    ai_assert(0 != pSizeInBytes);
  484|       |
  485|  55.0k|    if (0 == pSizeInBytes) {
  ------------------
  |  Branch (485:9): [True: 0, False: 55.0k]
  ------------------
  486|      0|        return AI_FAILURE;
  487|      0|    }
  488|       |
  489|       |    // first search the list whether there is already an entry with this key
  490|  55.0k|    unsigned int iOutIndex(UINT_MAX);
  491|   375k|    for (unsigned int i = 0; i < mNumProperties; ++i) {
  ------------------
  |  Branch (491:30): [True: 320k, False: 55.0k]
  ------------------
  492|   320k|        aiMaterialProperty *prop(mProperties[i]);
  493|       |
  494|   320k|        if (prop /* just for safety */ && !strcmp(prop->mKey.data, pKey) &&
  ------------------
  |  Branch (494:13): [True: 320k, False: 0]
  |  Branch (494:43): [True: 1.22k, False: 319k]
  ------------------
  495|  1.22k|                prop->mSemantic == type && prop->mIndex == index) {
  ------------------
  |  Branch (495:17): [True: 0, False: 1.22k]
  |  Branch (495:44): [True: 0, False: 0]
  ------------------
  496|       |
  497|      0|            delete mProperties[i];
  498|      0|            iOutIndex = i;
  499|      0|        }
  500|   320k|    }
  501|       |
  502|       |    // Allocate a new material property
  503|  55.0k|    auto pcNew = std::make_unique<aiMaterialProperty>();
  504|       |
  505|       |    // .. and fill it
  506|  55.0k|    pcNew->mType = pType;
  507|  55.0k|    pcNew->mSemantic = type;
  508|  55.0k|    pcNew->mIndex = index;
  509|       |
  510|  55.0k|    pcNew->mDataLength = pSizeInBytes;
  511|  55.0k|    pcNew->mData = new char[pSizeInBytes];
  512|  55.0k|    memcpy(pcNew->mData, pInput, pSizeInBytes);
  513|       |
  514|  55.0k|    pcNew->mKey.length = static_cast<ai_uint32>(::strlen(pKey));
  515|  55.0k|    ai_assert(AI_MAXLEN > pcNew->mKey.length);
  516|  55.0k|    strcpy(pcNew->mKey.data, pKey);
  517|       |
  518|  55.0k|    if (UINT_MAX != iOutIndex) {
  ------------------
  |  Branch (518:9): [True: 0, False: 55.0k]
  ------------------
  519|      0|        mProperties[iOutIndex] = pcNew.release();
  520|      0|        return AI_SUCCESS;
  521|      0|    }
  522|       |
  523|       |    // resize the array ... double the storage allocated
  524|  55.0k|    if (mNumProperties == mNumAllocated) {
  ------------------
  |  Branch (524:9): [True: 9.33k, False: 45.7k]
  ------------------
  525|  9.33k|        const unsigned int iOld = mNumAllocated;
  526|  9.33k|        mNumAllocated *= 2;
  527|       |
  528|  9.33k|        aiMaterialProperty **ppTemp;
  529|  9.33k|        try {
  530|  9.33k|            ppTemp = new aiMaterialProperty *[mNumAllocated];
  531|  9.33k|        } catch (std::bad_alloc &) {
  532|      0|            return AI_OUTOFMEMORY;
  533|      0|        }
  534|       |
  535|       |        // just copy all items over; then replace the old array
  536|  9.33k|        memcpy(ppTemp, mProperties, iOld * sizeof(void *));
  537|       |
  538|  9.33k|        delete[] mProperties;
  539|  9.33k|        mProperties = ppTemp;
  540|  9.33k|    }
  541|       |    // push back ...
  542|  55.0k|    mProperties[mNumProperties++] = pcNew.release();
  543|       |
  544|       |    return AI_SUCCESS;
  545|  55.0k|}
_ZN10aiMaterial11AddPropertyEPK8aiStringPKcjj:
  551|  7.80k|        unsigned int index) {
  552|       |    ai_assert(sizeof(ai_uint32) == 4);
  553|  7.80k|    return AddBinaryProperty(pInput,
  554|  7.80k|            static_cast<unsigned int>(pInput->length + 1 + 4),
  555|  7.80k|            pKey,
  556|  7.80k|            type,
  557|  7.80k|            index,
  558|  7.80k|            aiPTI_String);
  559|  7.80k|}
_ZN6Assimp19ComputeMaterialHashEPK10aiMaterialb:
  562|  1.40k|uint32_t Assimp::ComputeMaterialHash(const aiMaterial *mat, bool includeMatName /*= false*/) {
  563|  1.40k|    uint32_t hash = 1503; // magic start value, chosen to be my birthday :-)
  564|  19.9k|    for (unsigned int i = 0; i < mat->mNumProperties; ++i) {
  ------------------
  |  Branch (564:30): [True: 18.5k, False: 1.40k]
  ------------------
  565|       |        // Exclude all properties whose first character is '?' from the hash
  566|       |        // See doc for aiMaterialProperty.
  567|  18.5k|        const aiMaterialProperty *prop = mat->mProperties[i];
  568|  18.5k|        if (nullptr != prop && (includeMatName || prop->mKey.data[0] != '?')) {
  ------------------
  |  Branch (568:13): [True: 18.5k, False: 0]
  |  Branch (568:33): [True: 0, False: 18.5k]
  |  Branch (568:51): [True: 17.4k, False: 1.04k]
  ------------------
  569|       |
  570|  17.4k|            hash = SuperFastHash(prop->mKey.data, (unsigned int)prop->mKey.length, hash);
  571|  17.4k|            hash = SuperFastHash(prop->mData, prop->mDataLength, hash);
  572|       |
  573|       |            // Combine the semantic and the index with the hash
  574|  17.4k|            hash = SuperFastHash((const char *)&prop->mSemantic, sizeof(unsigned int), hash);
  575|  17.4k|            hash = SuperFastHash((const char *)&prop->mIndex, sizeof(unsigned int), hash);
  576|  17.4k|        }
  577|  18.5k|    }
  578|  1.40k|    return hash;
  579|  1.40k|}
MaterialSystem.cpp:_ZN12_GLOBAL__N_121GetMaterialFloatArrayIfEE8aiReturnPK10aiMaterialPKcjjPT_Pj:
   97|  2.62k|        unsigned int *pMax) {
   98|  2.62k|    ai_assert(pOut != nullptr);
   99|  2.62k|    ai_assert(pMat != nullptr);
  100|       |
  101|  2.62k|    const aiMaterialProperty *prop{nullptr};
  102|  2.62k|    aiGetMaterialProperty(pMat, pKey, type, index, &prop);
  103|  2.62k|    if (nullptr == prop) {
  ------------------
  |  Branch (103:9): [True: 18, False: 2.60k]
  ------------------
  104|     18|        return AI_FAILURE;
  105|     18|    }
  106|       |
  107|       |    // data is given in floats, convert to TReal
  108|  2.60k|    unsigned int iWrite = 0;
  109|  2.60k|    if (aiPTI_Float == prop->mType || aiPTI_Buffer == prop->mType) {
  ------------------
  |  Branch (109:9): [True: 2.60k, False: 0]
  |  Branch (109:39): [True: 0, False: 0]
  ------------------
  110|  2.60k|        iWrite = prop->mDataLength / sizeof(float);
  111|  2.60k|        if (pMax) {
  ------------------
  |  Branch (111:13): [True: 0, False: 2.60k]
  ------------------
  112|      0|            iWrite = std::min(*pMax, iWrite);
  113|      0|        }
  114|       |
  115|  5.20k|        for (unsigned int a = 0; a < iWrite; ++a) {
  ------------------
  |  Branch (115:34): [True: 2.60k, False: 2.60k]
  ------------------
  116|  2.60k|            pOut[a] = static_cast<TReal>(reinterpret_cast<float *>(prop->mData)[a]);
  117|  2.60k|        }
  118|       |
  119|  2.60k|        if (pMax) {
  ------------------
  |  Branch (119:13): [True: 0, False: 2.60k]
  ------------------
  120|      0|            *pMax = iWrite;
  121|      0|        }
  122|  2.60k|    } else if (aiPTI_Double == prop->mType) { // data is given in doubles, convert to TReal
  ------------------
  |  Branch (122:16): [True: 0, False: 0]
  ------------------
  123|      0|        iWrite = prop->mDataLength / sizeof(double);
  124|      0|        if (pMax) {
  ------------------
  |  Branch (124:13): [True: 0, False: 0]
  ------------------
  125|      0|            iWrite = std::min(*pMax, iWrite);
  126|      0|            ;
  127|      0|        }
  128|      0|        for (unsigned int a = 0; a < iWrite; ++a) {
  ------------------
  |  Branch (128:34): [True: 0, False: 0]
  ------------------
  129|      0|            pOut[a] = static_cast<TReal>(reinterpret_cast<double *>(prop->mData)[a]);
  130|      0|        }
  131|      0|        if (pMax) {
  ------------------
  |  Branch (131:13): [True: 0, False: 0]
  ------------------
  132|      0|            *pMax = iWrite;
  133|      0|        }
  134|      0|    } else if (aiPTI_Integer == prop->mType) { // data is given in ints, convert to TReal
  ------------------
  |  Branch (134:16): [True: 0, False: 0]
  ------------------
  135|      0|        iWrite = prop->mDataLength / sizeof(int32_t);
  136|      0|        if (pMax) {
  ------------------
  |  Branch (136:13): [True: 0, False: 0]
  ------------------
  137|      0|            iWrite = std::min(*pMax, iWrite);
  138|      0|            ;
  139|      0|        }
  140|      0|        for (unsigned int a = 0; a < iWrite; ++a) {
  ------------------
  |  Branch (140:34): [True: 0, False: 0]
  ------------------
  141|      0|            pOut[a] = static_cast<TReal>(reinterpret_cast<int32_t *>(prop->mData)[a]);
  142|      0|        }
  143|      0|        if (pMax) {
  ------------------
  |  Branch (143:13): [True: 0, False: 0]
  ------------------
  144|      0|            *pMax = iWrite;
  145|      0|        }
  146|      0|    } else { // a string ... read floats separated by spaces
  147|      0|        if (pMax) {
  ------------------
  |  Branch (147:13): [True: 0, False: 0]
  ------------------
  148|      0|            iWrite = *pMax;
  149|      0|        }
  150|       |        // strings are zero-terminated with a 32 bit length prefix, so this is safe
  151|      0|        const char *cur = prop->mData + 4;
  152|      0|        ai_assert(prop->mDataLength >= 5);
  153|      0|        ai_assert(!prop->mData[prop->mDataLength - 1]);
  154|      0|        for (unsigned int a = 0;; ++a) {
  155|      0|            cur = fast_atoreal_move(cur, pOut[a]);
  156|      0|            if (a == iWrite - 1) {
  ------------------
  |  Branch (156:17): [True: 0, False: 0]
  ------------------
  157|      0|                break;
  158|      0|            }
  159|      0|            if (!IsSpace(*cur)) {
  ------------------
  |  Branch (159:17): [True: 0, False: 0]
  ------------------
  160|      0|                ASSIMP_LOG_ERROR("Material property", pKey,
  161|      0|                                 " is a string; failed to parse a float array out of it.");
  162|      0|                return AI_FAILURE;
  163|      0|            }
  164|      0|        }
  165|       |
  166|      0|        if (pMax) {
  ------------------
  |  Branch (166:13): [True: 0, False: 0]
  ------------------
  167|      0|            *pMax = iWrite;
  168|      0|        }
  169|      0|    }
  170|       |
  171|  2.60k|    return AI_SUCCESS;
  172|  2.60k|}

_ZNK6Assimp16ArmaturePopulate8IsActiveEj:
   59|  1.54k|bool ArmaturePopulate::IsActive(unsigned int pFlags) const {
   60|  1.54k|    return (pFlags & aiProcess_PopulateArmatureData) != 0;
   61|  1.54k|}

_ZN6Assimp16ArmaturePopulateC2Ev:
   71|  5.13k|    ArmaturePopulate() = default;

_ZN6Assimp19CalcTangentsProcessC2Ev:
   59|  5.13k|        configMaxAngle(float(AI_DEG_TO_RAD(45.f))), configSourceUV(0) {
   60|       |    // nothing to do here
   61|  5.13k|}
_ZNK6Assimp19CalcTangentsProcess8IsActiveEj:
   65|  1.50k|bool CalcTangentsProcess::IsActive(unsigned int pFlags) const {
   66|  1.50k|    return (pFlags & aiProcess_CalcTangentSpace) != 0;
   67|  1.50k|}
_ZN6Assimp19CalcTangentsProcess15SetupPropertiesEPKNS_8ImporterE:
   71|  1.50k|void CalcTangentsProcess::SetupProperties(const Importer *pImp) {
   72|  1.50k|    ai_assert(nullptr != pImp);
   73|       |
   74|       |    // get the current value of the property
   75|  1.50k|    configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE, 45.f);
   76|  1.50k|    configMaxAngle = std::max(std::min(configMaxAngle, 45.0f), 0.0f);
   77|  1.50k|    configMaxAngle = AI_DEG_TO_RAD(configMaxAngle);
   78|       |
   79|       |    configSourceUV = pImp->GetPropertyInteger(AI_CONFIG_PP_CT_TEXTURE_CHANNEL_INDEX, 0);
   80|  1.50k|}
_ZN6Assimp19CalcTangentsProcess7ExecuteEP7aiScene:
   84|  1.50k|void CalcTangentsProcess::Execute(aiScene *pScene) {
   85|  1.50k|    ai_assert(nullptr != pScene);
   86|       |
   87|  1.50k|    ASSIMP_LOG_DEBUG("CalcTangentsProcess begin");
   88|       |
   89|  1.50k|    bool bHas = false;
   90|  3.66k|    for (unsigned int a = 0; a < pScene->mNumMeshes; a++) {
  ------------------
  |  Branch (90:30): [True: 2.16k, False: 1.50k]
  ------------------
   91|  2.16k|        if (ProcessMesh(pScene->mMeshes[a], a)) bHas = true;
  ------------------
  |  Branch (91:13): [True: 361, False: 1.80k]
  ------------------
   92|  2.16k|    }
   93|       |
   94|  1.50k|    if (bHas) {
  ------------------
  |  Branch (94:9): [True: 310, False: 1.19k]
  ------------------
   95|    310|        ASSIMP_LOG_INFO("CalcTangentsProcess finished. Tangents have been calculated");
   96|  1.19k|    } else {
   97|       |        ASSIMP_LOG_DEBUG("CalcTangentsProcess finished");
   98|  1.19k|    }
   99|  1.50k|}
_ZN6Assimp19CalcTangentsProcess11ProcessMeshEP6aiMeshj:
  103|  2.16k|bool CalcTangentsProcess::ProcessMesh(aiMesh *pMesh, unsigned int meshIndex) {
  104|       |    // we assume that the mesh is still in the verbose vertex format where each face has its own set
  105|       |    // of vertices and no vertices are shared between faces. Sadly I don't know any quick test to
  106|       |    // assert() it here.
  107|       |    // assert( must be verbose, dammit);
  108|       |
  109|  2.16k|    if (pMesh->mTangents) // this implies that mBitangents is also there
  ------------------
  |  Branch (109:9): [True: 0, False: 2.16k]
  ------------------
  110|      0|        return false;
  111|       |
  112|       |    // If the mesh consists of lines and/or points but not of
  113|       |    // triangles or higher-order polygons the normal vectors
  114|       |    // are undefined.
  115|  2.16k|    if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON))) {
  ------------------
  |  Branch (115:9): [True: 1.23k, False: 931]
  ------------------
  116|  1.23k|        ASSIMP_LOG_INFO("Tangents are undefined for line and point meshes");
  117|  1.23k|        return false;
  118|  1.23k|    }
  119|       |
  120|       |    // what we can check, though, is if the mesh has normals and texture coordinates. That's a requirement
  121|    931|    if (pMesh->mNormals == nullptr) {
  ------------------
  |  Branch (121:9): [True: 0, False: 931]
  ------------------
  122|      0|        ASSIMP_LOG_ERROR("Failed to compute tangents; need normals");
  123|      0|        return false;
  124|      0|    }
  125|    931|    if (configSourceUV >= AI_MAX_NUMBER_OF_TEXTURECOORDS || !pMesh->mTextureCoords[configSourceUV]) {
  ------------------
  |  Branch (125:9): [True: 0, False: 931]
  |  Branch (125:61): [True: 570, False: 361]
  ------------------
  126|    570|        ASSIMP_LOG_ERROR("Failed to compute tangents; need UV data in channel", configSourceUV);
  127|    570|        return false;
  128|    570|    }
  129|       |
  130|    361|    const float angleEpsilon = 0.9999f;
  131|       |
  132|    361|    std::vector<bool> vertexDone(pMesh->mNumVertices, false);
  133|    361|    const float qnan = get_qnan();
  134|       |
  135|       |    // create space for the tangents and bitangents
  136|    361|    pMesh->mTangents = new aiVector3D[pMesh->mNumVertices];
  137|    361|    pMesh->mBitangents = new aiVector3D[pMesh->mNumVertices];
  138|       |
  139|    361|    const aiVector3D *meshPos = pMesh->mVertices;
  140|    361|    const aiVector3D *meshNorm = pMesh->mNormals;
  141|    361|    const aiVector3D *meshTex = pMesh->mTextureCoords[configSourceUV];
  142|    361|    aiVector3D *meshTang = pMesh->mTangents;
  143|    361|    aiVector3D *meshBitang = pMesh->mBitangents;
  144|       |
  145|       |    // calculate the tangent and bitangent for every face
  146|  2.76k|    for (unsigned int a = 0; a < pMesh->mNumFaces; a++) {
  ------------------
  |  Branch (146:30): [True: 2.40k, False: 361]
  ------------------
  147|  2.40k|        const aiFace &face = pMesh->mFaces[a];
  148|  2.40k|        if (face.mNumIndices < 3) {
  ------------------
  |  Branch (148:13): [True: 0, False: 2.40k]
  ------------------
  149|       |            // There are less than three indices, thus the tangent vector
  150|       |            // is not defined. We are finished with these vertices now,
  151|       |            // their tangent vectors are set to qnan.
  152|      0|            for (unsigned int i = 0; i < face.mNumIndices; ++i) {
  ------------------
  |  Branch (152:38): [True: 0, False: 0]
  ------------------
  153|      0|                unsigned int idx = face.mIndices[i];
  154|      0|                vertexDone[idx] = true;
  155|      0|                meshTang[idx] = aiVector3D(qnan);
  156|      0|                meshBitang[idx] = aiVector3D(qnan);
  157|      0|            }
  158|       |
  159|      0|            continue;
  160|      0|        }
  161|       |
  162|       |        // triangle or polygon... we always use only the first three indices. A polygon
  163|       |        // is supposed to be planar anyways....
  164|       |        // FIXME: (thom) create correct calculation for multi-vertex polygons maybe?
  165|  2.40k|        const unsigned int p0 = face.mIndices[0], p1 = face.mIndices[1], p2 = face.mIndices[2];
  166|       |
  167|       |        // position differences p1->p2 and p1->p3
  168|  2.40k|        aiVector3D v = meshPos[p1] - meshPos[p0], w = meshPos[p2] - meshPos[p0];
  169|       |
  170|       |        // texture offset p1->p2 and p1->p3
  171|  2.40k|        float sx = meshTex[p1].x - meshTex[p0].x, sy = meshTex[p1].y - meshTex[p0].y;
  172|  2.40k|        float tx = meshTex[p2].x - meshTex[p0].x, ty = meshTex[p2].y - meshTex[p0].y;
  173|  2.40k|        float dirCorrection = (tx * sy - ty * sx) < 0.0f ? -1.0f : 1.0f;
  ------------------
  |  Branch (173:31): [True: 827, False: 1.57k]
  ------------------
  174|       |        // when t1, t2, t3 in same position in UV space, just use default UV direction.
  175|  2.40k|        if (sx * ty == sy * tx) {
  ------------------
  |  Branch (175:13): [True: 1.03k, False: 1.37k]
  ------------------
  176|  1.03k|            sx = 0.0;
  177|  1.03k|            sy = 1.0;
  178|  1.03k|            tx = 1.0;
  179|  1.03k|            ty = 0.0;
  180|  1.03k|        }
  181|       |
  182|       |        // tangent points in the direction where to positive X axis of the texture coord's would point in model space
  183|       |        // bitangent's points along the positive Y axis of the texture coord's, respectively
  184|  2.40k|        aiVector3D tangent, bitangent;
  185|  2.40k|        tangent.x = (w.x * sy - v.x * ty) * dirCorrection;
  186|  2.40k|        tangent.y = (w.y * sy - v.y * ty) * dirCorrection;
  187|  2.40k|        tangent.z = (w.z * sy - v.z * ty) * dirCorrection;
  188|  2.40k|        bitangent.x = (w.x * sx - v.x * tx) * dirCorrection;
  189|  2.40k|        bitangent.y = (w.y * sx - v.y * tx) * dirCorrection;
  190|  2.40k|        bitangent.z = (w.z * sx - v.z * tx) * dirCorrection;
  191|       |
  192|       |        // store for every vertex of that face
  193|  9.62k|        for (unsigned int b = 0; b < face.mNumIndices; ++b) {
  ------------------
  |  Branch (193:34): [True: 7.21k, False: 2.40k]
  ------------------
  194|  7.21k|            unsigned int p = face.mIndices[b];
  195|       |
  196|       |            // project tangent and bitangent into the plane formed by the vertex' normal
  197|  7.21k|            aiVector3D localTangent = tangent - meshNorm[p] * (tangent * meshNorm[p]);
  198|  7.21k|            aiVector3D localBitangent = bitangent - meshNorm[p] * (bitangent * meshNorm[p]);
  199|  7.21k|            localTangent.NormalizeSafe();
  200|  7.21k|            localBitangent.NormalizeSafe();
  201|       |
  202|       |            // reconstruct tangent/bitangent according to normal and bitangent/tangent when it's infinite or NaN.
  203|  7.21k|            bool invalid_tangent = is_special_float(localTangent.x) || is_special_float(localTangent.y) || is_special_float(localTangent.z)
  ------------------
  |  Branch (203:36): [True: 2.00k, False: 5.21k]
  |  Branch (203:72): [True: 101, False: 5.11k]
  |  Branch (203:108): [True: 49, False: 5.06k]
  ------------------
  204|  5.06k|                || (-0.5f < localTangent.x && localTangent.x < 0.5f && -0.5f < localTangent.y && localTangent.y < 0.5f && -0.5f < localTangent.z && localTangent.z < 0.5f);
  ------------------
  |  Branch (204:21): [True: 4.33k, False: 730]
  |  Branch (204:47): [True: 2.83k, False: 1.49k]
  |  Branch (204:72): [True: 2.50k, False: 329]
  |  Branch (204:98): [True: 2.30k, False: 203]
  |  Branch (204:123): [True: 2.22k, False: 81]
  |  Branch (204:149): [True: 2.14k, False: 79]
  ------------------
  205|  7.21k|            bool invalid_bitangent = is_special_float(localBitangent.x) || is_special_float(localBitangent.y) || is_special_float(localBitangent.z)
  ------------------
  |  Branch (205:38): [True: 1.97k, False: 5.23k]
  |  Branch (205:76): [True: 96, False: 5.14k]
  |  Branch (205:114): [True: 57, False: 5.08k]
  ------------------
  206|  5.08k|                || (-0.5f < localBitangent.x && localBitangent.x < 0.5f && -0.5f < localBitangent.y && localBitangent.y < 0.5f && -0.5f < localBitangent.z && localBitangent.z < 0.5f);
  ------------------
  |  Branch (206:21): [True: 4.33k, False: 749]
  |  Branch (206:49): [True: 3.69k, False: 637]
  |  Branch (206:76): [True: 2.88k, False: 816]
  |  Branch (206:104): [True: 2.49k, False: 393]
  |  Branch (206:131): [True: 2.33k, False: 156]
  |  Branch (206:159): [True: 2.26k, False: 70]
  ------------------
  207|  7.21k|            if (invalid_tangent != invalid_bitangent) {
  ------------------
  |  Branch (207:17): [True: 1.10k, False: 6.11k]
  ------------------
  208|  1.10k|                if (invalid_tangent) {
  ------------------
  |  Branch (208:21): [True: 504, False: 600]
  ------------------
  209|    504|                    localTangent = meshNorm[p] ^ localBitangent;
  210|    504|                    localTangent.NormalizeSafe();
  211|    600|                } else {
  212|    600|                    localBitangent = localTangent ^ meshNorm[p];
  213|    600|                    localBitangent.NormalizeSafe();
  214|    600|                }
  215|  1.10k|            }
  216|       |
  217|       |            // and write it into the mesh.
  218|  7.21k|            meshTang[p] = localTangent;
  219|  7.21k|            meshBitang[p] = localBitangent;
  220|  7.21k|        }
  221|  2.40k|    }
  222|       |
  223|       |    // create a helper to quickly find locally close vertices among the vertex array
  224|       |    // FIX: check whether we can reuse the SpatialSort of a previous step
  225|    361|    SpatialSort *vertexFinder = nullptr;
  226|    361|    SpatialSort _vertexFinder;
  227|    361|    float posEpsilon = 10e-6f;
  228|    361|    if (shared) {
  ------------------
  |  Branch (228:9): [True: 361, False: 0]
  ------------------
  229|    361|        std::vector<std::pair<SpatialSort, float>> *avf;
  230|    361|        shared->GetProperty(AI_SPP_SPATIAL_SORT, avf);
  ------------------
  |  |  166|    361|#define AI_SPP_SPATIAL_SORT "$Spat"
  ------------------
  231|    361|        if (avf) {
  ------------------
  |  Branch (231:13): [True: 361, False: 0]
  ------------------
  232|    361|            std::pair<SpatialSort, float> &blubb = avf->operator[](meshIndex);
  233|    361|            vertexFinder = &blubb.first;
  234|    361|            posEpsilon = blubb.second;
  235|    361|            ;
  236|    361|        }
  237|    361|    }
  238|    361|    if (!vertexFinder) {
  ------------------
  |  Branch (238:9): [True: 0, False: 361]
  ------------------
  239|      0|        _vertexFinder.Fill(pMesh->mVertices, pMesh->mNumVertices, sizeof(aiVector3D));
  240|      0|        vertexFinder = &_vertexFinder;
  241|      0|        posEpsilon = ComputePositionEpsilon(pMesh);
  242|      0|    }
  243|    361|    std::vector<unsigned int> verticesFound;
  244|       |
  245|    361|    const float fLimit = std::cos(configMaxAngle);
  246|    361|    std::vector<unsigned int> closeVertices;
  247|       |
  248|       |    // in the second pass we now smooth out all tangents and bitangents at the same local position
  249|       |    // if they are not too far off.
  250|  6.37k|    for (unsigned int a = 0; a < pMesh->mNumVertices; a++) {
  ------------------
  |  Branch (250:30): [True: 6.01k, False: 361]
  ------------------
  251|  6.01k|        if (vertexDone[a])
  ------------------
  |  Branch (251:13): [True: 1.39k, False: 4.61k]
  ------------------
  252|  1.39k|            continue;
  253|       |
  254|  4.61k|        const aiVector3D &origPos = pMesh->mVertices[a];
  255|  4.61k|        const aiVector3D &origNorm = pMesh->mNormals[a];
  256|  4.61k|        const aiVector3D &origTang = pMesh->mTangents[a];
  257|  4.61k|        const aiVector3D &origBitang = pMesh->mBitangents[a];
  258|  4.61k|        closeVertices.resize(0);
  259|       |
  260|       |        // find all vertices close to that position
  261|  4.61k|        vertexFinder->FindPositions(origPos, posEpsilon, verticesFound);
  262|       |
  263|  4.61k|        closeVertices.reserve(verticesFound.size() + 5);
  264|  4.61k|        closeVertices.push_back(a);
  265|       |
  266|       |        // look among them for other vertices sharing the same normal and a close-enough tangent/bitangent
  267|  57.3k|        for (unsigned int b = 0; b < verticesFound.size(); b++) {
  ------------------
  |  Branch (267:34): [True: 52.7k, False: 4.61k]
  ------------------
  268|  52.7k|            unsigned int idx = verticesFound[b];
  269|  52.7k|            if (vertexDone[idx])
  ------------------
  |  Branch (269:17): [True: 11.8k, False: 40.9k]
  ------------------
  270|  11.8k|                continue;
  271|  40.9k|            if (meshNorm[idx] * origNorm < angleEpsilon)
  ------------------
  |  Branch (271:17): [True: 31.3k, False: 9.53k]
  ------------------
  272|  31.3k|                continue;
  273|  9.53k|            if (meshTang[idx] * origTang < fLimit)
  ------------------
  |  Branch (273:17): [True: 5.30k, False: 4.22k]
  ------------------
  274|  5.30k|                continue;
  275|  4.22k|            if (meshBitang[idx] * origBitang < fLimit)
  ------------------
  |  Branch (275:17): [True: 1.13k, False: 3.09k]
  ------------------
  276|  1.13k|                continue;
  277|       |
  278|       |            // it's similar enough -> add it to the smoothing group
  279|  3.09k|            closeVertices.push_back(idx);
  280|  3.09k|            vertexDone[idx] = true;
  281|  3.09k|        }
  282|       |
  283|       |        // smooth the tangents and bitangents of all vertices that were found to be close enough
  284|  4.61k|        aiVector3D smoothTangent(0, 0, 0), smoothBitangent(0, 0, 0);
  285|  12.3k|        for (unsigned int b = 0; b < closeVertices.size(); ++b) {
  ------------------
  |  Branch (285:34): [True: 7.70k, False: 4.61k]
  ------------------
  286|  7.70k|            smoothTangent += meshTang[closeVertices[b]];
  287|  7.70k|            smoothBitangent += meshBitang[closeVertices[b]];
  288|  7.70k|        }
  289|  4.61k|        smoothTangent.Normalize();
  290|  4.61k|        smoothBitangent.Normalize();
  291|       |
  292|       |        // and write it back into all affected tangents
  293|  12.3k|        for (unsigned int b = 0; b < closeVertices.size(); ++b) {
  ------------------
  |  Branch (293:34): [True: 7.70k, False: 4.61k]
  ------------------
  294|  7.70k|            meshTang[closeVertices[b]] = smoothTangent;
  295|  7.70k|            meshBitang[closeVertices[b]] = smoothBitangent;
  296|  7.70k|        }
  297|  4.61k|    }
  298|    361|    return true;
  299|    931|}

_ZNK6Assimp23ComputeUVMappingProcess8IsActiveEj:
   61|  1.54k|bool ComputeUVMappingProcess::IsActive(unsigned int pFlags) const {
   62|  1.54k|    return (pFlags & aiProcess_GenUVCoords) != 0;
   63|  1.54k|}
_ZN6Assimp23ComputeUVMappingProcess7ExecuteEP7aiScene:
  345|  1.54k|void ComputeUVMappingProcess::Execute(aiScene *pScene) {
  346|  1.54k|    ASSIMP_LOG_DEBUG("GenUVCoordsProcess begin");
  347|  1.54k|    char buffer[1024];
  348|       |
  349|  1.54k|    if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) {
  ------------------
  |  Branch (349:9): [True: 0, False: 1.54k]
  ------------------
  350|      0|        throw DeadlyImportError("Post-processing order mismatch: expecting pseudo-indexed (\"verbose\") vertices here");
  351|      0|    }
  352|       |
  353|  1.54k|    std::list<MappingInfo> mappingStack;
  354|       |
  355|       |    // Iterate through all materials and search for non-UV mapped textures
  356|  2.92k|    for (unsigned int i = 0; i < pScene->mNumMaterials; ++i) {
  ------------------
  |  Branch (356:30): [True: 1.38k, False: 1.54k]
  ------------------
  357|  1.38k|        mappingStack.clear();
  358|  1.38k|        aiMaterial *mat = pScene->mMaterials[i];
  359|  1.38k|        if (mat == nullptr) {
  ------------------
  |  Branch (359:13): [True: 0, False: 1.38k]
  ------------------
  360|      0|            ASSIMP_LOG_INFO("Material pointer in nullptr, skipping.");
  361|      0|            continue;
  362|      0|        }
  363|  19.6k|        for (unsigned int a = 0; a < mat->mNumProperties; ++a) {
  ------------------
  |  Branch (363:34): [True: 18.2k, False: 1.38k]
  ------------------
  364|  18.2k|            aiMaterialProperty *prop = mat->mProperties[a];
  365|  18.2k|            if (!::strcmp(prop->mKey.data, "$tex.mapping")) {
  ------------------
  |  Branch (365:17): [True: 0, False: 18.2k]
  ------------------
  366|      0|                aiTextureMapping &mapping = *((aiTextureMapping *)prop->mData);
  367|      0|                if (aiTextureMapping_UV != mapping) {
  ------------------
  |  Branch (367:21): [True: 0, False: 0]
  ------------------
  368|      0|                    if (!DefaultLogger::isNullLogger()) {
  ------------------
  |  Branch (368:25): [True: 0, False: 0]
  ------------------
  369|      0|                        ai_snprintf(buffer, 1024, "Found non-UV mapped texture (%s,%u). Mapping type: %s",
  370|      0|                                aiTextureTypeToString((aiTextureType)prop->mSemantic), prop->mIndex,
  371|      0|                                MappingTypeToString(mapping));
  372|       |
  373|      0|                        ASSIMP_LOG_INFO(buffer);
  374|      0|                    }
  375|       |
  376|      0|                    if (aiTextureMapping_OTHER == mapping)
  ------------------
  |  Branch (376:25): [True: 0, False: 0]
  ------------------
  377|      0|                        continue;
  378|       |
  379|      0|                    MappingInfo info(mapping);
  380|       |
  381|       |                    // Get further properties - currently only the major axis
  382|      0|                    for (unsigned int a2 = 0; a2 < mat->mNumProperties; ++a2) {
  ------------------
  |  Branch (382:47): [True: 0, False: 0]
  ------------------
  383|      0|                        aiMaterialProperty *prop2 = mat->mProperties[a2];
  384|      0|                        if (prop2->mSemantic != prop->mSemantic || prop2->mIndex != prop->mIndex)
  ------------------
  |  Branch (384:29): [True: 0, False: 0]
  |  Branch (384:68): [True: 0, False: 0]
  ------------------
  385|      0|                            continue;
  386|       |
  387|      0|                        if (!::strcmp(prop2->mKey.data, "$tex.mapaxis")) {
  ------------------
  |  Branch (387:29): [True: 0, False: 0]
  ------------------
  388|      0|                            info.axis = *((aiVector3D *)prop2->mData);
  389|      0|                            break;
  390|      0|                        }
  391|      0|                    }
  392|       |
  393|      0|                    unsigned int idx(99999999);
  394|       |
  395|       |                    // Check whether we have this mapping mode already
  396|      0|                    std::list<MappingInfo>::iterator it = std::find(mappingStack.begin(), mappingStack.end(), info);
  397|      0|                    if (mappingStack.end() != it) {
  ------------------
  |  Branch (397:25): [True: 0, False: 0]
  ------------------
  398|      0|                        idx = (*it).uv;
  399|      0|                    } else {
  400|       |                        /*  We have found a non-UV mapped texture. Now
  401|       |                         *   we need to find all meshes using this material
  402|       |                         *   that we can compute UV channels for them.
  403|       |                         */
  404|      0|                        for (unsigned int m = 0; m < pScene->mNumMeshes; ++m) {
  ------------------
  |  Branch (404:50): [True: 0, False: 0]
  ------------------
  405|      0|                            aiMesh *mesh = pScene->mMeshes[m];
  406|      0|                            unsigned int outIdx = 0;
  407|      0|                            if (mesh->mMaterialIndex != i || (outIdx = FindEmptyUVChannel(mesh)) == UINT_MAX ||
  ------------------
  |  Branch (407:33): [True: 0, False: 0]
  |  Branch (407:62): [True: 0, False: 0]
  ------------------
  408|      0|                                    !mesh->mNumVertices) {
  ------------------
  |  Branch (408:37): [True: 0, False: 0]
  ------------------
  409|      0|                                continue;
  410|      0|                            }
  411|       |
  412|       |                            // Allocate output storage
  413|      0|                            aiVector3D *p = mesh->mTextureCoords[outIdx] = new aiVector3D[mesh->mNumVertices];
  414|       |
  415|      0|                            switch (mapping) {
  416|      0|                            case aiTextureMapping_SPHERE:
  ------------------
  |  Branch (416:29): [True: 0, False: 0]
  ------------------
  417|      0|                                ComputeSphereMapping(mesh, info.axis, p);
  418|      0|                                break;
  419|      0|                            case aiTextureMapping_CYLINDER:
  ------------------
  |  Branch (419:29): [True: 0, False: 0]
  ------------------
  420|      0|                                ComputeCylinderMapping(mesh, info.axis, p);
  421|      0|                                break;
  422|      0|                            case aiTextureMapping_PLANE:
  ------------------
  |  Branch (422:29): [True: 0, False: 0]
  ------------------
  423|      0|                                ComputePlaneMapping(mesh, info.axis, p);
  424|      0|                                break;
  425|      0|                            case aiTextureMapping_BOX:
  ------------------
  |  Branch (425:29): [True: 0, False: 0]
  ------------------
  426|      0|                                ComputeBoxMapping(mesh, p);
  427|      0|                                break;
  428|      0|                            default:
  ------------------
  |  Branch (428:29): [True: 0, False: 0]
  ------------------
  429|      0|                                ai_assert(false);
  430|      0|                            }
  431|      0|                            if (m && idx != outIdx) {
  ------------------
  |  Branch (431:33): [True: 0, False: 0]
  |  Branch (431:38): [True: 0, False: 0]
  ------------------
  432|      0|                                ASSIMP_LOG_WARN("UV index mismatch. Not all meshes assigned to "
  433|      0|                                                "this material have equal numbers of UV channels. The UV index stored in  "
  434|      0|                                                "the material structure does therefore not apply for all meshes. ");
  435|      0|                            }
  436|      0|                            idx = outIdx;
  437|      0|                        }
  438|      0|                        info.uv = idx;
  439|      0|                        mappingStack.push_back(info);
  440|      0|                    }
  441|       |
  442|       |                    // Update the material property list
  443|      0|                    mapping = aiTextureMapping_UV;
  444|      0|                    ((aiMaterial *)mat)->AddProperty(&idx, 1, AI_MATKEY_UVWSRC(prop->mSemantic, prop->mIndex));
  445|      0|                }
  446|      0|            }
  447|  18.2k|        }
  448|  1.38k|    }
  449|  1.54k|    ASSIMP_LOG_DEBUG("GenUVCoordsProcess finished");
  450|  1.54k|}

_ZN6Assimp23ComputeUVMappingProcessC2Ev:
   63|  5.13k|    ComputeUVMappingProcess() = default;

_ZNK6Assimp21MakeLeftHandedProcess8IsActiveEj:
   82|  1.54k|bool MakeLeftHandedProcess::IsActive(unsigned int pFlags) const {
   83|  1.54k|    return 0 != (pFlags & aiProcess_MakeLeftHanded);
   84|  1.54k|}
_ZN6Assimp14FlipUVsProcessC2Ev:
  244|  5.13k|FlipUVsProcess::FlipUVsProcess() = default;
_ZN6Assimp14FlipUVsProcessD2Ev:
  248|  5.13k|FlipUVsProcess::~FlipUVsProcess() = default;
_ZNK6Assimp14FlipUVsProcess8IsActiveEj:
  252|  1.54k|bool FlipUVsProcess::IsActive(unsigned int pFlags) const {
  253|  1.54k|    return 0 != (pFlags & aiProcess_FlipUVs);
  254|  1.54k|}
_ZNK6Assimp23FlipWindingOrderProcess8IsActiveEj:
  306|  1.54k|bool FlipWindingOrderProcess::IsActive(unsigned int pFlags) const {
  307|  1.54k|    return 0 != (pFlags & aiProcess_FlipWindingOrder);
  308|  1.54k|}

_ZN6Assimp21MakeLeftHandedProcessC2Ev:
   77|  5.13k|    MakeLeftHandedProcess() = default;
_ZN6Assimp23FlipWindingOrderProcessC2Ev:
  132|  5.13k|    FlipWindingOrderProcess() = default;

_ZN6Assimp13DeboneProcessC2Ev:
   54|  5.13k|DeboneProcess::DeboneProcess() : mNumBones(0), mNumBonesCanDoWithout(0), mThreshold(AI_DEBONE_THRESHOLD), mAllOrNone(false) {}
_ZNK6Assimp13DeboneProcess8IsActiveEj:
   58|  1.50k|bool DeboneProcess::IsActive( unsigned int pFlags) const {
   59|  1.50k|    return (pFlags & aiProcess_Debone) != 0;
   60|  1.50k|}

_ZN6Assimp13DeboneProcessD2Ev:
   72|  5.13k|    ~DeboneProcess() override = default;

_ZNK6Assimp22DropFaceNormalsProcess8IsActiveEj:
   58|  1.50k|bool DropFaceNormalsProcess::IsActive(unsigned int pFlags) const {
   59|  1.50k|    return (pFlags & aiProcess_DropNormals) != 0;
   60|  1.50k|}

_ZN6Assimp22DropFaceNormalsProcessC2Ev:
   57|  5.13k|    DropFaceNormalsProcess() = default;

_ZNK6Assimp20EmbedTexturesProcess8IsActiveEj:
   53|  1.54k|bool EmbedTexturesProcess::IsActive(unsigned int pFlags) const {
   54|  1.54k|    return (pFlags & aiProcess_EmbedTextures) != 0;
   55|  1.54k|}

_ZN6Assimp20EmbedTexturesProcessC2Ev:
   64|  5.13k|    EmbedTexturesProcess() = default;
_ZN6Assimp20EmbedTexturesProcessD2Ev:
   67|  5.13k|    ~EmbedTexturesProcess() override = default;

_ZN6Assimp22FindDegeneratesProcessC2Ev:
   62|  5.13k|        mConfigRemoveDegenerates(false),
   63|  5.13k|        mConfigCheckAreaOfTriangle(false) {
   64|       |    // empty
   65|  5.13k|}
_ZNK6Assimp22FindDegeneratesProcess8IsActiveEj:
   69|  1.54k|bool FindDegeneratesProcess::IsActive(unsigned int pFlags) const {
   70|  1.54k|    return 0 != (pFlags & aiProcess_FindDegenerates);
   71|  1.54k|}
_ZN6Assimp22FindDegeneratesProcess15SetupPropertiesEPKNS_8ImporterE:
   75|  1.54k|void FindDegeneratesProcess::SetupProperties(const Importer *pImp) {
   76|       |    // Get the current value of AI_CONFIG_PP_FD_REMOVE
   77|  1.54k|    mConfigRemoveDegenerates = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_REMOVE, 0));
   78|       |    mConfigCheckAreaOfTriangle = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_CHECKAREA));
   79|  1.54k|}
_ZN6Assimp22FindDegeneratesProcess7ExecuteEP7aiScene:
   83|  1.54k|void FindDegeneratesProcess::Execute(aiScene *pScene) {
   84|  1.54k|    ASSIMP_LOG_DEBUG("FindDegeneratesProcess begin");
   85|  1.54k|    if (nullptr == pScene) {
  ------------------
  |  Branch (85:9): [True: 0, False: 1.54k]
  ------------------
   86|      0|        return;
   87|      0|    }
   88|       |
   89|  1.54k|    std::unordered_map<unsigned int, unsigned int> meshMap;
   90|  1.54k|    meshMap.reserve(pScene->mNumMeshes);
   91|       |
   92|  1.54k|    const unsigned int originalNumMeshes = pScene->mNumMeshes;
   93|  1.54k|    unsigned int targetIndex = 0;
   94|  2.98k|    for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
  ------------------
  |  Branch (94:30): [True: 1.43k, False: 1.54k]
  ------------------
   95|       |        // Do not process point cloud, ExecuteOnMesh works only with faces data
   96|  1.43k|        if ((pScene->mMeshes[i]->mPrimitiveTypes != aiPrimitiveType::aiPrimitiveType_POINT) && ExecuteOnMesh(pScene->mMeshes[i])) {
  ------------------
  |  Branch (96:13): [True: 1.39k, False: 35]
  |  Branch (96:96): [True: 0, False: 1.39k]
  ------------------
   97|      0|            delete pScene->mMeshes[i];
   98|       |            // Not strictly required, but clean:
   99|      0|            pScene->mMeshes[i] = nullptr;
  100|  1.43k|        } else {
  101|  1.43k|            meshMap[i] = targetIndex;
  102|  1.43k|            pScene->mMeshes[targetIndex] = pScene->mMeshes[i];
  103|  1.43k|            ++targetIndex;
  104|  1.43k|        }
  105|  1.43k|    }
  106|  1.54k|    pScene->mNumMeshes = targetIndex;
  107|       |
  108|  1.54k|    if (meshMap.size() < originalNumMeshes) {
  ------------------
  |  Branch (108:9): [True: 0, False: 1.54k]
  ------------------
  109|      0|        updateSceneGraph(pScene->mRootNode, meshMap);
  110|      0|    }
  111|       |
  112|       |    ASSIMP_LOG_DEBUG("FindDegeneratesProcess finished");
  113|  1.54k|}
_ZN6Assimp22FindDegeneratesProcess13ExecuteOnMeshEP6aiMesh:
  134|  1.39k|bool FindDegeneratesProcess::ExecuteOnMesh(aiMesh *mesh) {
  135|  1.39k|    mesh->mPrimitiveTypes = 0;
  136|       |
  137|  1.39k|    std::vector<bool> remove_me;
  138|  1.39k|    if (mConfigRemoveDegenerates) {
  ------------------
  |  Branch (138:9): [True: 0, False: 1.39k]
  ------------------
  139|      0|        remove_me.resize(mesh->mNumFaces, false);
  140|      0|    }
  141|       |
  142|  1.39k|    unsigned int deg = 0, limit;
  143|  24.7k|    for (unsigned int a = 0; a < mesh->mNumFaces; ++a) {
  ------------------
  |  Branch (143:30): [True: 23.3k, False: 1.39k]
  ------------------
  144|  23.3k|        aiFace &face = mesh->mFaces[a];
  145|  23.3k|        bool first = true;
  146|  23.3k|        auto vertex_in_range = [numVertices = mesh->mNumVertices](unsigned int vertex_idx) { return vertex_idx < numVertices; };
  147|       |
  148|       |        // check whether the face contains degenerated entries
  149|  77.9k|        for (unsigned int i = 0; i < face.mNumIndices; ++i) {
  ------------------
  |  Branch (149:34): [True: 54.6k, False: 23.3k]
  ------------------
  150|  54.6k|            if (!std::all_of(face.mIndices, face.mIndices + face.mNumIndices, vertex_in_range))
  ------------------
  |  Branch (150:17): [True: 0, False: 54.6k]
  ------------------
  151|      0|                continue;
  152|       |
  153|       |            // Polygons with more than 4 points are allowed to have double points, that is
  154|       |            // simulating polygons with holes just with concave polygons. However,
  155|       |            // double points may not come directly after another.
  156|  54.6k|            limit = face.mNumIndices;
  157|  54.6k|            if (face.mNumIndices > 4) {
  ------------------
  |  Branch (157:17): [True: 0, False: 54.6k]
  ------------------
  158|      0|                limit = std::min(limit, i + 2);
  159|      0|            }
  160|       |
  161|   107k|            for (unsigned int t = i + 1; t < limit; ++t) {
  ------------------
  |  Branch (161:42): [True: 53.0k, False: 54.6k]
  ------------------
  162|  53.0k|                if (mesh->mVertices[face.mIndices[i]] == mesh->mVertices[face.mIndices[t]]) {
  ------------------
  |  Branch (162:21): [True: 8.84k, False: 44.1k]
  ------------------
  163|       |                    // we have found a matching vertex position
  164|       |                    // remove the corresponding index from the array
  165|  8.84k|                    --face.mNumIndices;
  166|  8.84k|                    --limit;
  167|  11.8k|                    for (unsigned int m = t; m < face.mNumIndices; ++m) {
  ------------------
  |  Branch (167:46): [True: 2.98k, False: 8.84k]
  ------------------
  168|  2.98k|                        face.mIndices[m] = face.mIndices[m + 1];
  169|  2.98k|                    }
  170|  8.84k|                    --t;
  171|       |
  172|       |                    // NOTE: we set the removed vertex index to an unique value
  173|       |                    // to make sure the developer gets notified when his
  174|       |                    // application attempts to access this data.
  175|  8.84k|                    face.mIndices[face.mNumIndices] = 0xdeadbeef;
  176|       |
  177|  8.84k|                    if (first) {
  ------------------
  |  Branch (177:25): [True: 6.78k, False: 2.06k]
  ------------------
  178|  6.78k|                        ++deg;
  179|  6.78k|                        first = false;
  180|  6.78k|                    }
  181|       |
  182|  8.84k|                    if (mConfigRemoveDegenerates) {
  ------------------
  |  Branch (182:25): [True: 0, False: 8.84k]
  ------------------
  183|      0|                        remove_me[a] = true;
  184|      0|                        goto evil_jump_outside; // hrhrhrh ... yeah, this rocks baby!
  185|      0|                    }
  186|  8.84k|                }
  187|  53.0k|            }
  188|       |
  189|  54.6k|            if (mConfigCheckAreaOfTriangle) {
  ------------------
  |  Branch (189:17): [True: 54.6k, False: 0]
  ------------------
  190|  54.6k|                if (face.mNumIndices == 3) {
  ------------------
  |  Branch (190:21): [True: 36.2k, False: 18.4k]
  ------------------
  191|  36.2k|                    ai_real area = GeometryUtils::calculateAreaOfTriangle(face, mesh);
  192|  36.2k|                    if (area < ai_epsilon) {
  ------------------
  |  Branch (192:25): [True: 24.0k, False: 12.1k]
  ------------------
  193|  24.0k|                        if (mConfigRemoveDegenerates) {
  ------------------
  |  Branch (193:29): [True: 0, False: 24.0k]
  ------------------
  194|      0|                            remove_me[a] = true;
  195|      0|                            ++deg;
  196|      0|                            goto evil_jump_outside;
  197|      0|                        }
  198|       |
  199|       |                        // todo: check for index which is corrupt.
  200|  24.0k|                    }
  201|  36.2k|                }
  202|  54.6k|            }
  203|  54.6k|        }
  204|       |
  205|       |        // We need to update the primitive flags array of the mesh.
  206|  23.3k|        switch (face.mNumIndices) {
  207|  3.64k|        case 1u:
  ------------------
  |  Branch (207:9): [True: 3.64k, False: 19.6k]
  ------------------
  208|  3.64k|            mesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
  209|  3.64k|            break;
  210|  7.95k|        case 2u:
  ------------------
  |  Branch (210:9): [True: 7.95k, False: 15.3k]
  ------------------
  211|  7.95k|            mesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
  212|  7.95k|            break;
  213|  11.7k|        case 3u:
  ------------------
  |  Branch (213:9): [True: 11.7k, False: 11.5k]
  ------------------
  214|  11.7k|            mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
  215|  11.7k|            break;
  216|      0|        default:
  ------------------
  |  Branch (216:9): [True: 0, False: 23.3k]
  ------------------
  217|      0|            mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
  218|      0|            break;
  219|  23.3k|        };
  220|  23.3k|    evil_jump_outside:
  221|  23.3k|        continue;
  222|  23.3k|    }
  223|       |
  224|       |    // If AI_CONFIG_PP_FD_REMOVE is true, remove degenerated faces from the import
  225|  1.39k|    if (mConfigRemoveDegenerates && deg) {
  ------------------
  |  Branch (225:9): [True: 0, False: 1.39k]
  |  Branch (225:37): [True: 0, False: 0]
  ------------------
  226|      0|        unsigned int n = 0;
  227|      0|        for (unsigned int a = 0; a < mesh->mNumFaces; ++a) {
  ------------------
  |  Branch (227:34): [True: 0, False: 0]
  ------------------
  228|      0|            aiFace &face_src = mesh->mFaces[a];
  229|      0|            if (!remove_me[a]) {
  ------------------
  |  Branch (229:17): [True: 0, False: 0]
  ------------------
  230|      0|                aiFace &face_dest = mesh->mFaces[n++];
  231|       |
  232|       |                // Do a manual copy, keep the index array
  233|      0|                face_dest.mNumIndices = face_src.mNumIndices;
  234|      0|                face_dest.mIndices = face_src.mIndices;
  235|       |
  236|      0|                if (&face_src != &face_dest) {
  ------------------
  |  Branch (236:21): [True: 0, False: 0]
  ------------------
  237|       |                    // clear source
  238|      0|                    face_src.mNumIndices = 0;
  239|      0|                    face_src.mIndices = nullptr;
  240|      0|                }
  241|      0|            } else {
  242|       |                // Otherwise delete it if we don't need this face
  243|      0|                delete[] face_src.mIndices;
  244|      0|                face_src.mIndices = nullptr;
  245|      0|                face_src.mNumIndices = 0;
  246|      0|            }
  247|      0|        }
  248|       |        // Just leave the rest of the array unreferenced, we don't care for now
  249|      0|        mesh->mNumFaces = n;
  250|      0|        if (!mesh->mNumFaces) {
  ------------------
  |  Branch (250:13): [True: 0, False: 0]
  ------------------
  251|       |            // The whole mesh consists of degenerated faces
  252|       |            // signal upward, that this mesh should be deleted.
  253|      0|            ASSIMP_LOG_VERBOSE_DEBUG("FindDegeneratesProcess removed a mesh full of degenerated primitives");
  254|      0|            return true;
  255|      0|        }
  256|      0|    }
  257|       |
  258|  1.39k|    if (deg && !DefaultLogger::isNullLogger()) {
  ------------------
  |  Branch (258:9): [True: 969, False: 430]
  |  Branch (258:16): [True: 0, False: 969]
  ------------------
  259|       |        ASSIMP_LOG_WARN("Found ", deg, " degenerated primitives");
  260|      0|    }
  261|  1.39k|    return false;
  262|  1.39k|}
FindDegenerates.cpp:_ZZN6Assimp22FindDegeneratesProcess13ExecuteOnMeshEP6aiMeshENK3$_0clEj:
  146|   150k|        auto vertex_in_range = [numVertices = mesh->mNumVertices](unsigned int vertex_idx) { return vertex_idx < numVertices; };

_ZN6Assimp20FindInstancesProcessC2Ev:
   58|  5.13k|:   configSpeedFlag (false)
   59|  5.13k|{}
_ZNK6Assimp20FindInstancesProcess8IsActiveEj:
   64|  1.54k|{
   65|       |    // FindInstances makes absolutely no sense together with PreTransformVertices
   66|       |    // fixme: spawn error message somewhere else?
   67|  1.54k|    return 0 != (pFlags & aiProcess_FindInstances) && 0 == (pFlags & aiProcess_PreTransformVertices);
  ------------------
  |  Branch (67:12): [True: 0, False: 1.54k]
  |  Branch (67:55): [True: 0, False: 0]
  ------------------
   68|  1.54k|}

_ZN6Assimp22FindInvalidDataProcessC2Ev:
   59|  5.13k|        configEpsilon(0.0), mIgnoreTexCoods(false) {
   60|       |    // nothing to do here
   61|  5.13k|}
_ZNK6Assimp22FindInvalidDataProcess8IsActiveEj:
   65|  1.54k|bool FindInvalidDataProcess::IsActive(unsigned int pFlags) const {
   66|  1.54k|    return 0 != (pFlags & aiProcess_FindInvalidData);
   67|  1.54k|}
_ZN6Assimp22FindInvalidDataProcess15SetupPropertiesEPKNS_8ImporterE:
   71|  1.54k|void FindInvalidDataProcess::SetupProperties(const Importer *pImp) {
   72|       |    // Get the current value of AI_CONFIG_PP_FID_ANIM_ACCURACY
   73|  1.54k|    configEpsilon = (0 != pImp->GetPropertyFloat(AI_CONFIG_PP_FID_ANIM_ACCURACY, 0.f));
   74|       |    mIgnoreTexCoods = pImp->GetPropertyBool(AI_CONFIG_PP_FID_IGNORE_TEXTURECOORDS, false);
   75|  1.54k|}
_Z20UpdateMeshReferencesP6aiNodeRKNSt3__16vectorIjNS1_9allocatorIjEEEE:
   79|    486|void UpdateMeshReferences(aiNode *node, const std::vector<unsigned int> &meshMapping) {
   80|    486|    if (node->mNumMeshes) {
  ------------------
  |  Branch (80:9): [True: 256, False: 230]
  ------------------
   81|    256|        unsigned int out = 0;
   82|    768|        for (unsigned int a = 0; a < node->mNumMeshes; ++a) {
  ------------------
  |  Branch (82:34): [True: 512, False: 256]
  ------------------
   83|       |
   84|    512|            unsigned int ref = node->mMeshes[a];
   85|    512|            if (ref >= meshMapping.size())
  ------------------
  |  Branch (85:17): [True: 0, False: 512]
  ------------------
   86|      0|                throw DeadlyImportError("Invalid mesh ref");
   87|       |
   88|    512|            if (UINT_MAX != (ref = meshMapping[ref])) {
  ------------------
  |  Branch (88:17): [True: 287, False: 225]
  ------------------
   89|    287|                node->mMeshes[out++] = ref;
   90|    287|            }
   91|    512|        }
   92|       |        // just let the members that are unused, that's much cheaper
   93|       |        // than a full array realloc'n'copy party ...
   94|    256|        node->mNumMeshes = out;
   95|    256|        if (0 == out) {
  ------------------
  |  Branch (95:13): [True: 42, False: 214]
  ------------------
   96|     42|            delete[] node->mMeshes;
   97|     42|            node->mMeshes = nullptr;
   98|     42|        }
   99|    256|    }
  100|       |    // recursively update all children
  101|    786|    for (unsigned int i = 0; i < node->mNumChildren; ++i) {
  ------------------
  |  Branch (101:30): [True: 300, False: 486]
  ------------------
  102|    300|        UpdateMeshReferences(node->mChildren[i], meshMapping);
  103|    300|    }
  104|    486|}
_ZN6Assimp22FindInvalidDataProcess7ExecuteEP7aiScene:
  108|  1.54k|void FindInvalidDataProcess::Execute(aiScene *pScene) {
  109|  1.54k|    ASSIMP_LOG_DEBUG("FindInvalidDataProcess begin");
  110|       |
  111|  1.54k|    bool out = false;
  112|  1.54k|    std::vector<unsigned int> meshMapping(pScene->mNumMeshes);
  113|  1.54k|    unsigned int real = 0;
  114|       |
  115|       |    // Process meshes
  116|  3.99k|    for (unsigned int a = 0; a < pScene->mNumMeshes; a++) {
  ------------------
  |  Branch (116:30): [True: 2.44k, False: 1.54k]
  ------------------
  117|  2.44k|        int result = ProcessMesh(pScene->mMeshes[a]);
  118|  2.44k|        if (0 == result) {
  ------------------
  |  Branch (118:13): [True: 1.97k, False: 472]
  ------------------
  119|  1.97k|            out = true;
  120|  1.97k|        }
  121|  2.44k|        if (2 == result) {
  ------------------
  |  Branch (121:13): [True: 284, False: 2.16k]
  ------------------
  122|       |            // remove this mesh
  123|    284|            delete pScene->mMeshes[a];
  124|    284|            pScene->mMeshes[a] = nullptr;
  125|       |
  126|    284|            meshMapping[a] = UINT_MAX;
  127|    284|            out = true;
  128|    284|            continue;
  129|    284|        }
  130|       |
  131|  2.16k|        pScene->mMeshes[real] = pScene->mMeshes[a];
  132|  2.16k|        meshMapping[a] = real++;
  133|  2.16k|    }
  134|       |
  135|       |    // Process animations
  136|  1.62k|    for (unsigned int animIdx = 0; animIdx < pScene->mNumAnimations; ++animIdx) {
  ------------------
  |  Branch (136:36): [True: 74, False: 1.54k]
  ------------------
  137|     74|        ProcessAnimation(pScene->mAnimations[animIdx]);
  138|     74|    }
  139|       |
  140|  1.54k|    if (out) {
  ------------------
  |  Branch (140:9): [True: 1.17k, False: 373]
  ------------------
  141|  1.17k|        if (real != pScene->mNumMeshes) {
  ------------------
  |  Branch (141:13): [True: 231, False: 944]
  ------------------
  142|    231|            if (!real) {
  ------------------
  |  Branch (142:17): [True: 45, False: 186]
  ------------------
  143|     45|                throw DeadlyImportError("No meshes remaining");
  144|     45|            }
  145|       |
  146|       |            // we need to remove some meshes.
  147|       |            // therefore we'll also need to remove all references
  148|       |            // to them from the scenegraph
  149|    186|            try {
  150|    186|                UpdateMeshReferences(pScene->mRootNode, meshMapping);
  151|    186|            } catch (const std::exception&) {
  152|       |                // fix the real number of meshes otherwise we'll get double free in the scene destructor
  153|      0|                pScene->mNumMeshes = real;
  154|      0|                throw;
  155|      0|            }
  156|    186|            pScene->mNumMeshes = real;
  157|    186|        }
  158|       |
  159|  1.17k|        ASSIMP_LOG_INFO("FindInvalidDataProcess finished. Found issues ...");
  160|  1.13k|    } else {
  161|       |        ASSIMP_LOG_DEBUG("FindInvalidDataProcess finished. Everything seems to be OK.");
  162|    373|    }
  163|  1.54k|}
_ZN6Assimp22FindInvalidDataProcess16ProcessAnimationEP11aiAnimation:
  265|     74|void FindInvalidDataProcess::ProcessAnimation(aiAnimation *anim) {
  266|       |    // Process all animation channels
  267|    148|    for (unsigned int a = 0; a < anim->mNumChannels; ++a) {
  ------------------
  |  Branch (267:30): [True: 74, False: 74]
  ------------------
  268|     74|        ProcessAnimationChannel(anim->mChannels[a]);
  269|     74|    }
  270|     74|}
_ZN6Assimp22FindInvalidDataProcess23ProcessAnimationChannelEP10aiNodeAnim:
  273|     74|void FindInvalidDataProcess::ProcessAnimationChannel(aiNodeAnim *anim) {
  274|     74|    ai_assert(nullptr != anim);
  275|     74|    if (anim->mNumPositionKeys == 0 && anim->mNumRotationKeys == 0 && anim->mNumScalingKeys == 0) {
  ------------------
  |  Branch (275:9): [True: 11, False: 63]
  |  Branch (275:40): [True: 0, False: 11]
  |  Branch (275:71): [True: 0, False: 0]
  ------------------
  276|      0|        ASSIMP_LOG_ERROR("Invalid node anuimation instance detected.");
  277|       |
  278|      0|        return;
  279|      0|    }
  280|       |
  281|       |    // Check whether all values in a tracks are identical - in this case
  282|       |    // we can remove al keys except one.
  283|       |    // POSITIONS
  284|     74|    int i = 0;
  285|     74|    if (anim->mNumPositionKeys > 1 && AllIdentical(anim->mPositionKeys, anim->mNumPositionKeys, configEpsilon)) {
  ------------------
  |  Branch (285:9): [True: 15, False: 59]
  |  Branch (285:39): [True: 0, False: 15]
  ------------------
  286|      0|        aiVectorKey v = anim->mPositionKeys[0];
  287|       |
  288|       |        // Reallocate ... we need just ONE element, it makes no sense to reuse the array
  289|      0|        delete[] anim->mPositionKeys;
  290|      0|        anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys = 1];
  291|      0|        anim->mPositionKeys[0] = v;
  292|      0|        i = 1;
  293|      0|    }
  294|       |
  295|       |    // ROTATIONS
  296|     74|    if (anim->mNumRotationKeys > 1 && AllIdentical(anim->mRotationKeys, anim->mNumRotationKeys, configEpsilon)) {
  ------------------
  |  Branch (296:9): [True: 53, False: 21]
  |  Branch (296:39): [True: 7, False: 46]
  ------------------
  297|      7|        aiQuatKey v = anim->mRotationKeys[0];
  298|       |
  299|       |        // Reallocate ... we need just ONE element, it makes no sense to reuse the array
  300|      7|        delete[] anim->mRotationKeys;
  301|      7|        anim->mRotationKeys = new aiQuatKey[anim->mNumRotationKeys = 1];
  302|      7|        anim->mRotationKeys[0] = v;
  303|      7|        i = 1;
  304|      7|    }
  305|       |
  306|       |    // SCALINGS
  307|     74|    if (anim->mNumScalingKeys > 1 && AllIdentical(anim->mScalingKeys, anim->mNumScalingKeys, configEpsilon)) {
  ------------------
  |  Branch (307:9): [True: 0, False: 74]
  |  Branch (307:38): [True: 0, False: 0]
  ------------------
  308|      0|        aiVectorKey v = anim->mScalingKeys[0];
  309|       |
  310|       |        // Reallocate ... we need just ONE element, it makes no sense to reuse the array
  311|      0|        delete[] anim->mScalingKeys;
  312|      0|        anim->mScalingKeys = new aiVectorKey[anim->mNumScalingKeys = 1];
  313|      0|        anim->mScalingKeys[0] = v;
  314|      0|        i = 1;
  315|      0|    }
  316|     74|    if (1 == i) {
  ------------------
  |  Branch (316:9): [True: 7, False: 67]
  ------------------
  317|       |        ASSIMP_LOG_WARN("Simplified dummy tracks with just one key");
  318|      7|    }
  319|     74|}
_ZN6Assimp22FindInvalidDataProcess11ProcessMeshEP6aiMesh:
  323|  2.44k|int FindInvalidDataProcess::ProcessMesh(aiMesh *pMesh) {
  324|  2.44k|    bool ret = false;
  325|  2.44k|    std::vector<bool> dirtyMask(pMesh->mNumVertices, pMesh->mNumFaces != 0);
  326|       |
  327|       |    // Ignore elements that are not referenced by vertices.
  328|       |    // (they are, for example, caused by the FindDegenerates step)
  329|  26.3k|    for (unsigned int m = 0; m < pMesh->mNumFaces; ++m) {
  ------------------
  |  Branch (329:30): [True: 23.9k, False: 2.44k]
  ------------------
  330|  23.9k|        const aiFace &f = pMesh->mFaces[m];
  331|       |
  332|  79.2k|        for (unsigned int i = 0; i < f.mNumIndices; ++i) {
  ------------------
  |  Branch (332:34): [True: 55.3k, False: 23.9k]
  ------------------
  333|  55.3k|            dirtyMask[f.mIndices[i]] = false;
  334|  55.3k|        }
  335|  23.9k|    }
  336|       |
  337|       |    // Process vertex positions
  338|  2.44k|    if (pMesh->mVertices && ProcessArray(pMesh->mVertices, pMesh->mNumVertices, "positions", dirtyMask)) {
  ------------------
  |  Branch (338:9): [True: 2.44k, False: 0]
  |  Branch (338:29): [True: 284, False: 2.16k]
  ------------------
  339|    284|        ASSIMP_LOG_ERROR("Deleting mesh: Unable to continue without vertex positions");
  340|       |
  341|    284|        return 2;
  342|    284|    }
  343|       |
  344|       |    // process texture coordinates
  345|  2.16k|    if (!mIgnoreTexCoods) {
  ------------------
  |  Branch (345:9): [True: 2.16k, False: 0]
  ------------------
  346|  2.82k|        for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS && pMesh->mTextureCoords[i]; ++i) {
  ------------------
  |  Branch (346:34): [True: 2.82k, False: 0]
  |  Branch (346:72): [True: 663, False: 2.16k]
  ------------------
  347|    663|            if (ProcessArray(pMesh->mTextureCoords[i], pMesh->mNumVertices, "uvcoords", dirtyMask)) {
  ------------------
  |  Branch (347:17): [True: 38, False: 625]
  ------------------
  348|     38|                pMesh->mNumUVComponents[i] = 0;
  349|       |
  350|       |                // delete all subsequent texture coordinate sets.
  351|    304|                for (unsigned int a = i + 1; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
  ------------------
  |  Branch (351:46): [True: 266, False: 38]
  ------------------
  352|    266|                    delete[] pMesh->mTextureCoords[a];
  353|    266|                    pMesh->mTextureCoords[a] = nullptr;
  354|    266|                    pMesh->mNumUVComponents[a] = 0;
  355|    266|                }
  356|       |
  357|     38|                ret = true;
  358|     38|            }
  359|    663|        }
  360|  2.16k|    }
  361|       |
  362|       |    // -- we don't validate vertex colors, it's difficult to say whether
  363|       |    // they are invalid or not.
  364|       |
  365|       |    // Normals and tangents are undefined for point and line faces.
  366|  2.16k|    if (pMesh->mNormals || pMesh->mTangents) {
  ------------------
  |  Branch (366:9): [True: 1.34k, False: 815]
  |  Branch (366:28): [True: 0, False: 815]
  ------------------
  367|       |
  368|  1.34k|        if (aiPrimitiveType_POINT & pMesh->mPrimitiveTypes ||
  ------------------
  |  Branch (368:13): [True: 246, False: 1.10k]
  ------------------
  369|  1.10k|                aiPrimitiveType_LINE & pMesh->mPrimitiveTypes) {
  ------------------
  |  Branch (369:17): [True: 458, False: 642]
  ------------------
  370|    704|            if (aiPrimitiveType_TRIANGLE & pMesh->mPrimitiveTypes ||
  ------------------
  |  Branch (370:17): [True: 0, False: 704]
  ------------------
  371|    704|                    aiPrimitiveType_POLYGON & pMesh->mPrimitiveTypes) {
  ------------------
  |  Branch (371:21): [True: 0, False: 704]
  ------------------
  372|       |                // We need to update the lookup-table
  373|      0|                for (unsigned int m = 0; m < pMesh->mNumFaces; ++m) {
  ------------------
  |  Branch (373:42): [True: 0, False: 0]
  ------------------
  374|      0|                    const aiFace &f = pMesh->mFaces[m];
  375|       |
  376|      0|                    if (f.mNumIndices < 3) {
  ------------------
  |  Branch (376:25): [True: 0, False: 0]
  ------------------
  377|      0|                        dirtyMask[f.mIndices[0]] = true;
  378|      0|                        if (f.mNumIndices == 2) {
  ------------------
  |  Branch (378:29): [True: 0, False: 0]
  ------------------
  379|      0|                            dirtyMask[f.mIndices[1]] = true;
  380|      0|                        }
  381|      0|                    }
  382|      0|                }
  383|      0|            }
  384|       |            // Normals, tangents and bitangents are undefined for
  385|       |            // the whole mesh (and should not even be there)
  386|    704|            else {
  387|    704|                return ret;
  388|    704|            }
  389|    704|        }
  390|       |
  391|       |        // Process mesh normals
  392|    642|        if (pMesh->mNormals && ProcessArray(pMesh->mNormals, pMesh->mNumVertices,
  ------------------
  |  Branch (392:13): [True: 642, False: 0]
  |  Branch (392:32): [True: 154, False: 488]
  ------------------
  393|    642|                                       "normals", dirtyMask, true, false))
  394|    154|            ret = true;
  395|       |
  396|       |        // Process mesh tangents
  397|    642|        if (pMesh->mTangents && ProcessArray(pMesh->mTangents, pMesh->mNumVertices, "tangents", dirtyMask)) {
  ------------------
  |  Branch (397:13): [True: 0, False: 642]
  |  Branch (397:33): [True: 0, False: 0]
  ------------------
  398|      0|            delete[] pMesh->mBitangents;
  399|      0|            pMesh->mBitangents = nullptr;
  400|      0|            ret = true;
  401|      0|        }
  402|       |
  403|       |        // Process mesh bitangents
  404|    642|        if (pMesh->mBitangents && ProcessArray(pMesh->mBitangents, pMesh->mNumVertices, "bitangents", dirtyMask)) {
  ------------------
  |  Branch (404:13): [True: 0, False: 642]
  |  Branch (404:35): [True: 0, False: 0]
  ------------------
  405|      0|            delete[] pMesh->mTangents;
  406|      0|            pMesh->mTangents = nullptr;
  407|      0|            ret = true;
  408|      0|        }
  409|    642|    }
  410|  1.45k|    return ret ? 1 : 0;
  ------------------
  |  Branch (410:12): [True: 172, False: 1.28k]
  ------------------
  411|  2.16k|}
_Z12AllIdenticalI11aiVectorKeyEbPT_jf:
  242|     15|inline bool AllIdentical(T *in, unsigned int num, ai_real epsilon) {
  243|     15|    if (num <= 1) {
  ------------------
  |  Branch (243:9): [True: 0, False: 15]
  ------------------
  244|      0|        return true;
  245|      0|    }
  246|       |
  247|     15|    if (fabs(epsilon) > 0.f) {
  ------------------
  |  Branch (247:9): [True: 0, False: 15]
  ------------------
  248|      0|        for (unsigned int i = 0; i < num - 1; ++i) {
  ------------------
  |  Branch (248:34): [True: 0, False: 0]
  ------------------
  249|      0|            if (!EpsilonCompare(in[i], in[i + 1], epsilon)) {
  ------------------
  |  Branch (249:17): [True: 0, False: 0]
  ------------------
  250|      0|                return false;
  251|      0|            }
  252|      0|        }
  253|     15|    } else {
  254|     17|        for (unsigned int i = 0; i < num - 1; ++i) {
  ------------------
  |  Branch (254:34): [True: 17, False: 0]
  ------------------
  255|     17|            if (in[i] != in[i + 1]) {
  ------------------
  |  Branch (255:17): [True: 15, False: 2]
  ------------------
  256|     15|                return false;
  257|     15|            }
  258|     17|        }
  259|     15|    }
  260|      0|    return true;
  261|     15|}
_Z12AllIdenticalI9aiQuatKeyEbPT_jf:
  242|     53|inline bool AllIdentical(T *in, unsigned int num, ai_real epsilon) {
  243|     53|    if (num <= 1) {
  ------------------
  |  Branch (243:9): [True: 0, False: 53]
  ------------------
  244|      0|        return true;
  245|      0|    }
  246|       |
  247|     53|    if (fabs(epsilon) > 0.f) {
  ------------------
  |  Branch (247:9): [True: 0, False: 53]
  ------------------
  248|      0|        for (unsigned int i = 0; i < num - 1; ++i) {
  ------------------
  |  Branch (248:34): [True: 0, False: 0]
  ------------------
  249|      0|            if (!EpsilonCompare(in[i], in[i + 1], epsilon)) {
  ------------------
  |  Branch (249:17): [True: 0, False: 0]
  ------------------
  250|      0|                return false;
  251|      0|            }
  252|      0|        }
  253|     53|    } else {
  254|    131|        for (unsigned int i = 0; i < num - 1; ++i) {
  ------------------
  |  Branch (254:34): [True: 124, False: 7]
  ------------------
  255|    124|            if (in[i] != in[i + 1]) {
  ------------------
  |  Branch (255:17): [True: 46, False: 78]
  ------------------
  256|     46|                return false;
  257|     46|            }
  258|    124|        }
  259|     53|    }
  260|      7|    return true;
  261|     53|}
_Z12ProcessArrayI10aiVector3tIfEEbRPT_jPKcRKNSt3__16vectorIbNS7_9allocatorIbEEEEbb:
  203|  3.75k|        const std::vector<bool> &dirtyMask, bool mayBeIdentical = false, bool mayBeZero = true) {
  204|  3.75k|    const char *err = ValidateArrayContents(in, num, dirtyMask, mayBeIdentical, mayBeZero);
  205|  3.75k|    if (err) {
  ------------------
  |  Branch (205:9): [True: 476, False: 3.27k]
  ------------------
  206|    476|        ASSIMP_LOG_ERROR("FindInvalidDataProcess fails on mesh ", name, ": ", err);
  207|    476|        delete[] in;
  208|    476|        in = nullptr;
  209|    476|        return true;
  210|    476|    }
  211|  3.27k|    return false;
  212|  3.75k|}
_Z21ValidateArrayContentsI10aiVector3tIfEEPKcPKT_jRKNSt3__16vectorIbNS7_9allocatorIbEEEEbb:
  175|  3.75k|        const std::vector<bool> &dirtyMask, bool mayBeIdentical, bool mayBeZero) {
  176|  3.75k|    bool b = false;
  177|  3.75k|    unsigned int cnt = 0;
  178|  69.5k|    for (unsigned int i = 0; i < size; ++i) {
  ------------------
  |  Branch (178:30): [True: 66.0k, False: 3.44k]
  ------------------
  179|       |
  180|  66.0k|        if (dirtyMask.size() && dirtyMask[i]) {
  ------------------
  |  Branch (180:13): [True: 66.0k, False: 0]
  |  Branch (180:13): [True: 568, False: 65.5k]
  |  Branch (180:33): [True: 568, False: 65.5k]
  ------------------
  181|    568|            continue;
  182|    568|        }
  183|  65.5k|        ++cnt;
  184|       |
  185|  65.5k|        const aiVector3D &v = arr[i];
  186|  65.5k|        if (is_special_float(v.x) || is_special_float(v.y) || is_special_float(v.z)) {
  ------------------
  |  Branch (186:13): [True: 84, False: 65.4k]
  |  Branch (186:38): [True: 47, False: 65.3k]
  |  Branch (186:63): [True: 82, False: 65.3k]
  ------------------
  187|    213|            return "INF/NAN was found in a vector component";
  188|    213|        }
  189|  65.3k|        if (!mayBeZero && !v.x && !v.y && !v.z) {
  ------------------
  |  Branch (189:13): [True: 7.78k, False: 57.5k]
  |  Branch (189:27): [True: 2.94k, False: 4.84k]
  |  Branch (189:35): [True: 1.18k, False: 1.76k]
  |  Branch (189:43): [True: 90, False: 1.09k]
  ------------------
  190|     90|            return "Found zero-length vector";
  191|     90|        }
  192|  65.2k|        if (i && v != arr[i - 1]) b = true;
  ------------------
  |  Branch (192:13): [True: 61.6k, False: 3.56k]
  |  Branch (192:18): [True: 47.7k, False: 13.8k]
  ------------------
  193|  65.2k|    }
  194|  3.44k|    if (cnt > 1 && !b && !mayBeIdentical) {
  ------------------
  |  Branch (194:9): [True: 3.14k, False: 299]
  |  Branch (194:20): [True: 319, False: 2.82k]
  |  Branch (194:26): [True: 173, False: 146]
  ------------------
  195|    173|        return "All vectors are identical";
  196|    173|    }
  197|  3.27k|    return nullptr;
  198|  3.44k|}

_ZNK6Assimp25FixInfacingNormalsProcess8IsActiveEj:
   61|  1.50k|bool FixInfacingNormalsProcess::IsActive( unsigned int pFlags) const {
   62|  1.50k|    return (pFlags & aiProcess_FixInfacingNormals) != 0;
   63|  1.50k|}

_ZN6Assimp25FixInfacingNormalsProcessC2Ev:
   62|  5.13k|    FixInfacingNormalsProcess() = default;

_ZNK6Assimp23GenBoundingBoxesProcess8IsActiveEj:
   51|  1.50k|bool GenBoundingBoxesProcess::IsActive(unsigned int pFlags) const {
   52|  1.50k|    return 0 != ( pFlags & aiProcess_GenBoundingBoxes );
   53|  1.50k|}

_ZN6Assimp23GenBoundingBoxesProcessC2Ev:
   65|  5.13k|    GenBoundingBoxesProcess() = default;

_ZNK6Assimp21GenFaceNormalsProcess8IsActiveEj:
   61|  1.50k|bool GenFaceNormalsProcess::IsActive(unsigned int pFlags) const {
   62|  1.50k|    force_ = (pFlags & aiProcess_ForceGenNormals) != 0;
   63|  1.50k|    flippedWindingOrder_ = (pFlags & aiProcess_FlipWindingOrder) != 0;
   64|  1.50k|    leftHanded_ = (pFlags & aiProcess_MakeLeftHanded) != 0;
   65|  1.50k|    return (pFlags & aiProcess_GenNormals) != 0;
   66|  1.50k|}

_ZN6Assimp21GenFaceNormalsProcessC2Ev:
   59|  5.13k|    GenFaceNormalsProcess() = default;

_ZN6Assimp23GenVertexNormalsProcessC2Ev:
   57|  5.13k|        configMaxAngle(AI_DEG_TO_RAD(175.f)) {
   58|       |    // empty
   59|  5.13k|}
_ZNK6Assimp23GenVertexNormalsProcess8IsActiveEj:
   63|  1.50k|bool GenVertexNormalsProcess::IsActive(unsigned int pFlags) const {
   64|  1.50k|    force_ = (pFlags & aiProcess_ForceGenNormals) != 0;
   65|  1.50k|    flippedWindingOrder_ = (pFlags & aiProcess_FlipWindingOrder) != 0;
   66|  1.50k|    leftHanded_ = (pFlags & aiProcess_MakeLeftHanded) != 0;
   67|  1.50k|    return (pFlags & aiProcess_GenSmoothNormals) != 0;
   68|  1.50k|}
_ZN6Assimp23GenVertexNormalsProcess15SetupPropertiesEPKNS_8ImporterE:
   72|  1.50k|void GenVertexNormalsProcess::SetupProperties(const Importer *pImp) {
   73|       |    // Get the current value of the AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE property
   74|  1.50k|    configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE, (ai_real)175.0);
   75|       |    configMaxAngle = AI_DEG_TO_RAD(std::max(std::min(configMaxAngle, (ai_real)175.0), (ai_real)0.0));
   76|  1.50k|}
_ZN6Assimp23GenVertexNormalsProcess7ExecuteEP7aiScene:
   80|  1.50k|void GenVertexNormalsProcess::Execute(aiScene *pScene) {
   81|  1.50k|    ASSIMP_LOG_DEBUG("GenVertexNormalsProcess begin");
   82|       |
   83|  1.50k|    if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) {
  ------------------
  |  Branch (83:9): [True: 0, False: 1.50k]
  ------------------
   84|      0|        throw DeadlyImportError("Post-processing order mismatch: expecting pseudo-indexed (\"verbose\") vertices here");
   85|      0|    }
   86|       |
   87|  1.50k|    bool bHas = false;
   88|  3.66k|    for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) {
  ------------------
  |  Branch (88:30): [True: 2.16k, False: 1.50k]
  ------------------
   89|  2.16k|        if (GenMeshVertexNormals(pScene->mMeshes[a], a))
  ------------------
  |  Branch (89:13): [True: 443, False: 1.71k]
  ------------------
   90|    443|            bHas = true;
   91|  2.16k|    }
   92|       |
   93|  1.50k|    if (bHas) {
  ------------------
  |  Branch (93:9): [True: 436, False: 1.06k]
  ------------------
   94|    436|        ASSIMP_LOG_INFO("GenVertexNormalsProcess finished. "
   95|    436|                        "Vertex normals have been calculated");
   96|  1.06k|    } else {
   97|       |        ASSIMP_LOG_DEBUG("GenVertexNormalsProcess finished. "
   98|  1.06k|                         "Normals are already there");
   99|  1.06k|    }
  100|  1.50k|}
_ZN6Assimp23GenVertexNormalsProcess20GenMeshVertexNormalsEP6aiMeshj:
  104|  2.16k|bool GenVertexNormalsProcess::GenMeshVertexNormals(aiMesh *pMesh, unsigned int meshIndex) {
  105|  2.16k|    if (nullptr != pMesh->mNormals) {
  ------------------
  |  Branch (105:9): [True: 1.19k, False: 969]
  ------------------
  106|  1.19k|        if (!force_) {
  ------------------
  |  Branch (106:13): [True: 1.19k, False: 0]
  ------------------
  107|  1.19k|            return false;
  108|  1.19k|        }
  109|      0|        delete[] pMesh->mNormals;
  110|      0|        pMesh->mNormals = nullptr;
  111|      0|    }
  112|       |
  113|       |    // If the mesh consists of lines and/or points but not of
  114|       |    // triangles or higher-order polygons the normal vectors
  115|       |    // are undefined.
  116|    969|    if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON))) {
  ------------------
  |  Branch (116:9): [True: 526, False: 443]
  ------------------
  117|    526|        ASSIMP_LOG_INFO("Normal vectors are undefined for line and point meshes");
  118|    526|        return false;
  119|    526|    }
  120|       |
  121|       |    // Allocate the array to hold the output normals
  122|    443|    const float qnan = std::numeric_limits<ai_real>::quiet_NaN();
  123|    443|    pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
  124|       |
  125|       |    // Compute per-face normals but store them per-vertex
  126|  9.32k|    for (unsigned int a = 0; a < pMesh->mNumFaces; a++) {
  ------------------
  |  Branch (126:30): [True: 8.88k, False: 443]
  ------------------
  127|  8.88k|        const aiFace &face = pMesh->mFaces[a];
  128|  8.88k|        if (face.mNumIndices < 3) {
  ------------------
  |  Branch (128:13): [True: 0, False: 8.88k]
  ------------------
  129|       |            // either a point or a line -> no normal vector
  130|      0|            for (unsigned int i = 0; i < face.mNumIndices; ++i) {
  ------------------
  |  Branch (130:38): [True: 0, False: 0]
  ------------------
  131|      0|                pMesh->mNormals[face.mIndices[i]] = aiVector3D(qnan);
  132|      0|            }
  133|       |
  134|      0|            continue;
  135|      0|        }
  136|       |
  137|  8.88k|        const aiVector3D *pV1 = &pMesh->mVertices[face.mIndices[0]];
  138|  8.88k|        const aiVector3D *pV2 = &pMesh->mVertices[face.mIndices[1]];
  139|  8.88k|        const aiVector3D *pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices - 1]];
  140|       |        // Boolean XOR - if either but not both of these flags is set, then the winding order has
  141|       |        // changed and the cross product to calculate the normal needs to be reversed
  142|  8.88k|        if (flippedWindingOrder_ != leftHanded_) {
  ------------------
  |  Branch (142:13): [True: 0, False: 8.88k]
  ------------------
  143|      0|            std::swap(pV2, pV3);
  144|      0|        }
  145|  8.88k|        const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).NormalizeSafe();
  146|       |
  147|  35.5k|        for (unsigned int i = 0; i < face.mNumIndices; ++i) {
  ------------------
  |  Branch (147:34): [True: 26.6k, False: 8.88k]
  ------------------
  148|  26.6k|            pMesh->mNormals[face.mIndices[i]] = vNor;
  149|  26.6k|        }
  150|  8.88k|    }
  151|       |
  152|       |    // Set up a SpatialSort to quickly find all vertices close to a given position
  153|       |    // check whether we can reuse the SpatialSort of a previous step.
  154|    443|    SpatialSort *vertexFinder = nullptr;
  155|    443|    SpatialSort _vertexFinder;
  156|    443|    ai_real posEpsilon = ai_real(1e-5);
  157|    443|    if (shared) {
  ------------------
  |  Branch (157:9): [True: 443, False: 0]
  ------------------
  158|    443|        std::vector<std::pair<SpatialSort, ai_real>> *avf;
  159|    443|        shared->GetProperty(AI_SPP_SPATIAL_SORT, avf);
  ------------------
  |  |  166|    443|#define AI_SPP_SPATIAL_SORT "$Spat"
  ------------------
  160|    443|        if (avf) {
  ------------------
  |  Branch (160:13): [True: 443, False: 0]
  ------------------
  161|    443|            std::pair<SpatialSort, ai_real> &blubb = avf->operator[](meshIndex);
  162|    443|            vertexFinder = &blubb.first;
  163|    443|            posEpsilon = blubb.second;
  164|    443|        }
  165|    443|    }
  166|    443|    if (!vertexFinder) {
  ------------------
  |  Branch (166:9): [True: 0, False: 443]
  ------------------
  167|      0|        _vertexFinder.Fill(pMesh->mVertices, pMesh->mNumVertices, sizeof(aiVector3D));
  168|      0|        vertexFinder = &_vertexFinder;
  169|      0|        posEpsilon = ComputePositionEpsilon(pMesh);
  170|      0|    }
  171|    443|    std::vector<unsigned int> verticesFound;
  172|    443|    aiVector3D *pcNew = new aiVector3D[pMesh->mNumVertices];
  173|       |
  174|    443|    if (configMaxAngle >= AI_DEG_TO_RAD(175.f)) {
  ------------------
  |  Branch (174:9): [True: 443, False: 0]
  ------------------
  175|       |        // There is no angle limit. Thus all vertices with positions close
  176|       |        // to each other will receive the same vertex normal. This allows us
  177|       |        // to optimize the whole algorithm a little bit ...
  178|    443|        std::vector<bool> abHad(pMesh->mNumVertices, false);
  179|  25.9k|        for (unsigned int i = 0; i < pMesh->mNumVertices; ++i) {
  ------------------
  |  Branch (179:34): [True: 25.4k, False: 443]
  ------------------
  180|  25.4k|            if (abHad[i]) {
  ------------------
  |  Branch (180:17): [True: 5.11k, False: 20.3k]
  ------------------
  181|  5.11k|                continue;
  182|  5.11k|            }
  183|       |
  184|       |            // Get all vertices that share this one ...
  185|  20.3k|            vertexFinder->FindPositions(pMesh->mVertices[i], posEpsilon, verticesFound);
  186|       |
  187|  20.3k|            aiVector3D pcNor;
  188|  27.4k|            for (unsigned int a = 0; a < verticesFound.size(); ++a) {
  ------------------
  |  Branch (188:38): [True: 7.12k, False: 20.3k]
  ------------------
  189|  7.12k|                const aiVector3D &v = pMesh->mNormals[verticesFound[a]];
  190|  7.12k|                if (is_not_qnan(v.x)) pcNor += v;
  ------------------
  |  Branch (190:21): [True: 6.38k, False: 737]
  ------------------
  191|  7.12k|            }
  192|  20.3k|            pcNor.NormalizeSafe();
  193|       |
  194|       |            // Write the smoothed normal back to all affected normals
  195|  27.4k|            for (unsigned int a = 0; a < verticesFound.size(); ++a) {
  ------------------
  |  Branch (195:38): [True: 7.12k, False: 20.3k]
  ------------------
  196|  7.12k|                unsigned int vidx = verticesFound[a];
  197|  7.12k|                pcNew[vidx] = pcNor;
  198|  7.12k|                abHad[vidx] = true;
  199|  7.12k|            }
  200|  20.3k|        }
  201|    443|    }
  202|       |    // Slower code path if a smooth angle is set. There are many ways to achieve
  203|       |    // the effect, this one is the most straightforward one.
  204|      0|    else {
  205|      0|        const ai_real fLimit = std::cos(configMaxAngle);
  206|      0|        for (unsigned int i = 0; i < pMesh->mNumVertices; ++i) {
  ------------------
  |  Branch (206:34): [True: 0, False: 0]
  ------------------
  207|       |            // Get all vertices that share this one ...
  208|      0|            vertexFinder->FindPositions(pMesh->mVertices[i], posEpsilon, verticesFound);
  209|       |
  210|      0|            aiVector3D vr = pMesh->mNormals[i];
  211|       |
  212|      0|            aiVector3D pcNor;
  213|      0|            for (unsigned int a = 0; a < verticesFound.size(); ++a) {
  ------------------
  |  Branch (213:38): [True: 0, False: 0]
  ------------------
  214|      0|                aiVector3D v = pMesh->mNormals[verticesFound[a]];
  215|       |
  216|       |                // Check whether the angle between the two normals is not too large.
  217|       |                // Skip the angle check on our own normal to avoid false negatives
  218|       |                // (v*v is not guaranteed to be 1.0 for all unit vectors v)
  219|      0|                if (is_not_qnan(v.x) && (verticesFound[a] == i || (v * vr >= fLimit)))
  ------------------
  |  Branch (219:21): [True: 0, False: 0]
  |  Branch (219:42): [True: 0, False: 0]
  |  Branch (219:67): [True: 0, False: 0]
  ------------------
  220|      0|                    pcNor += v;
  221|      0|            }
  222|      0|            pcNew[i] = pcNor.NormalizeSafe();
  223|      0|        }
  224|      0|    }
  225|       |
  226|    443|    delete[] pMesh->mNormals;
  227|    443|    pMesh->mNormals = pcNew;
  228|       |
  229|    443|    return true;
  230|    969|}

_ZN6Assimp27ImproveCacheLocalityProcessC2Ev:
   65|  5.13k|        mConfigCacheDepth(PP_ICL_PTCACHE_SIZE) {
   66|       |    // empty
   67|  5.13k|}
_ZNK6Assimp27ImproveCacheLocalityProcess8IsActiveEj:
   71|  1.50k|bool ImproveCacheLocalityProcess::IsActive(unsigned int pFlags) const {
   72|  1.50k|    return (pFlags & aiProcess_ImproveCacheLocality) != 0;
   73|  1.50k|}
_ZN6Assimp27ImproveCacheLocalityProcess15SetupPropertiesEPKNS_8ImporterE:
   77|  1.50k|void ImproveCacheLocalityProcess::SetupProperties(const Importer *pImp) {
   78|       |    // AI_CONFIG_PP_ICL_PTCACHE_SIZE controls the target cache size for the optimizer
   79|  1.50k|    mConfigCacheDepth = pImp->GetPropertyInteger(AI_CONFIG_PP_ICL_PTCACHE_SIZE, PP_ICL_PTCACHE_SIZE);
   80|  1.50k|}
_ZN6Assimp27ImproveCacheLocalityProcess7ExecuteEP7aiScene:
   84|  1.50k|void ImproveCacheLocalityProcess::Execute(aiScene *pScene) {
   85|  1.50k|    if (!pScene->mNumMeshes) {
  ------------------
  |  Branch (85:9): [True: 326, False: 1.17k]
  ------------------
   86|    326|        ASSIMP_LOG_DEBUG("ImproveCacheLocalityProcess skipped; there are no meshes");
   87|    326|        return;
   88|    326|    }
   89|       |
   90|  1.50k|    ASSIMP_LOG_DEBUG("ImproveCacheLocalityProcess begin");
   91|       |
   92|  1.17k|    float out = 0.f;
   93|  1.17k|    unsigned int numf = 0, numm = 0;
   94|  3.33k|    for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) {
  ------------------
  |  Branch (94:30): [True: 2.16k, False: 1.17k]
  ------------------
   95|  2.16k|        const float res = ProcessMesh(pScene->mMeshes[a], a);
   96|  2.16k|        if (res) {
  ------------------
  |  Branch (96:13): [True: 0, False: 2.16k]
  ------------------
   97|      0|            numf += pScene->mMeshes[a]->mNumFaces;
   98|      0|            out += res;
   99|      0|            ++numm;
  100|      0|        }
  101|  2.16k|    }
  102|  1.17k|    if (!DefaultLogger::isNullLogger()) {
  ------------------
  |  Branch (102:9): [True: 0, False: 1.17k]
  ------------------
  103|      0|        if (numf > 0) {
  ------------------
  |  Branch (103:13): [True: 0, False: 0]
  ------------------
  104|      0|            ASSIMP_LOG_INFO("Cache relevant are ", numm, " meshes (", numf, " faces). Average output ACMR is ", out / numf);
  105|      0|        }
  106|       |        ASSIMP_LOG_DEBUG("ImproveCacheLocalityProcess finished. ");
  107|      0|    }
  108|  1.17k|}
_ZN6Assimp27ImproveCacheLocalityProcess11ProcessMeshEP6aiMeshj:
  157|  2.16k|ai_real ImproveCacheLocalityProcess::ProcessMesh(aiMesh *pMesh, unsigned int meshNum) {
  158|       |    // TODO: rewrite this to use std::vector or boost::shared_array
  159|  2.16k|    ai_assert(nullptr != pMesh);
  160|       |
  161|       |    // Check whether the input data is valid
  162|       |    // - there must be vertices and faces
  163|       |    // - all faces must be triangulated or we can't operate on them
  164|  2.16k|    if (!pMesh->HasFaces() || !pMesh->HasPositions())
  ------------------
  |  Branch (164:9): [True: 0, False: 2.16k]
  |  Branch (164:31): [True: 0, False: 2.16k]
  ------------------
  165|      0|        return static_cast<ai_real>(0.f);
  166|       |
  167|  2.16k|    if (pMesh->mPrimitiveTypes != aiPrimitiveType_TRIANGLE) {
  ------------------
  |  Branch (167:9): [True: 1.23k, False: 931]
  ------------------
  168|  1.23k|        ASSIMP_LOG_ERROR("This algorithm works on triangle meshes only");
  169|  1.23k|        return static_cast<ai_real>(0.f);
  170|  1.23k|    }
  171|       |
  172|    931|    if (pMesh->mNumVertices <= mConfigCacheDepth) {
  ------------------
  |  Branch (172:9): [True: 560, False: 371]
  ------------------
  173|    560|        return static_cast<ai_real>(0.f);
  174|    560|    }
  175|       |
  176|    371|    ai_real fACMR = 3.f;
  177|    371|    const aiFace *const pcEnd = pMesh->mFaces + pMesh->mNumFaces;
  178|       |
  179|       |    // Input ACMR is for logging purposes only
  180|    371|    if (!DefaultLogger::isNullLogger()) {
  ------------------
  |  Branch (180:9): [True: 0, False: 371]
  ------------------
  181|      0|        fACMR = calculateInputACMR(pMesh, pcEnd, mConfigCacheDepth, meshNum);
  182|      0|    }
  183|       |
  184|       |    // first we need to build a vertex-triangle adjacency list
  185|    371|    VertexTriangleAdjacency adj(pMesh->mFaces, pMesh->mNumFaces, pMesh->mNumVertices, true);
  186|       |
  187|       |    // build a list to store per-vertex caching time stamps
  188|    371|    std::vector<unsigned int> piCachingStamps;
  189|    371|    piCachingStamps.resize(pMesh->mNumVertices);
  190|    371|    memset(&piCachingStamps[0], 0x0, pMesh->mNumVertices * sizeof(unsigned int));
  191|       |
  192|       |    // allocate an empty output index buffer. We store the output indices in one large array.
  193|       |    // Since the number of triangles won't change the input faces can be reused. This is how
  194|       |    // we save thousands of redundant mini allocations for aiFace::mIndices
  195|    371|    const unsigned int iIdxCnt = pMesh->mNumFaces * 3;
  196|    371|    std::vector<unsigned int> piIBOutput;
  197|    371|    piIBOutput.resize(iIdxCnt);
  198|    371|    std::vector<unsigned int>::iterator piCSIter = piIBOutput.begin();
  199|       |
  200|       |    // allocate the flag array to hold the information
  201|       |    // whether a face has already been emitted or not
  202|    371|    std::vector<bool> abEmitted(pMesh->mNumFaces, false);
  203|       |
  204|       |    // dead-end vertex index stack
  205|    371|    std::stack<unsigned int, std::vector<unsigned int>> sDeadEndVStack;
  206|       |
  207|       |    // create a copy of the piNumTriPtr buffer
  208|    371|    unsigned int *const piNumTriPtr = adj.mLiveTriangles;
  209|    371|    const std::vector<unsigned int> piNumTriPtrNoModify(piNumTriPtr, piNumTriPtr + pMesh->mNumVertices);
  210|       |
  211|       |    // get the largest number of referenced triangles and allocate the "candidate buffer"
  212|    371|    unsigned int iMaxRefTris = 0;
  213|    371|    {
  214|    371|        const unsigned int *piCur = adj.mLiveTriangles;
  215|    371|        const unsigned int *const piCurEnd = adj.mLiveTriangles + pMesh->mNumVertices;
  216|  9.91k|        for (; piCur != piCurEnd; ++piCur) {
  ------------------
  |  Branch (216:16): [True: 9.54k, False: 371]
  ------------------
  217|  9.54k|            iMaxRefTris = std::max(iMaxRefTris, *piCur);
  218|  9.54k|        }
  219|    371|    }
  220|    371|    ai_assert(iMaxRefTris > 0);
  221|    371|    std::vector<unsigned int> piCandidates;
  222|    371|    piCandidates.resize(iMaxRefTris * 3);
  223|    371|    unsigned int iCacheMisses = 0;
  224|       |
  225|       |    // ...................................................................................
  226|       |    /** PSEUDOCODE for the algorithm
  227|       |
  228|       |        A = Build-Adjacency(I) Vertex-triangle adjacency
  229|       |        L = Get-Triangle-Counts(A) Per-vertex live triangle counts
  230|       |        C = Zero(Vertex-Count(I)) Per-vertex caching time stamps
  231|       |        D = Empty-Stack() Dead-end vertex stack
  232|       |        E = False(Triangle-Count(I)) Per triangle emitted flag
  233|       |        O = Empty-Index-Buffer() Empty output buffer
  234|       |        f = 0 Arbitrary starting vertex
  235|       |        s = k+1, i = 1 Time stamp and cursor
  236|       |        while f >= 0 For all valid fanning vertices
  237|       |            N = Empty-Set() 1-ring of next candidates
  238|       |            for each Triangle t in Neighbors(A, f)
  239|       |                if !Emitted(E,t)
  240|       |                    for each Vertex v in t
  241|       |                        Append(O,v) Output vertex
  242|       |                        Push(D,v) Add to dead-end stack
  243|       |                        Insert(N,v) Register as candidate
  244|       |                        L[v] = L[v]-1 Decrease live triangle count
  245|       |                        if s-C[v] > k If not in cache
  246|       |                            C[v] = s Set time stamp
  247|       |                            s = s+1 Increment time stamp
  248|       |                    E[t] = true Flag triangle as emitted
  249|       |            Select next fanning vertex
  250|       |            f = Get-Next-Vertex(I,i,k,N,C,s,L,D)
  251|       |        return O
  252|       |        */
  253|       |    // ...................................................................................
  254|       |
  255|    371|    int ivdx = 0;
  256|    371|    int ics = 1;
  257|    371|    int iStampCnt = mConfigCacheDepth + 1;
  258|  5.02k|    while (ivdx >= 0) {
  ------------------
  |  Branch (258:12): [True: 4.65k, False: 371]
  ------------------
  259|       |
  260|  4.65k|        unsigned int icnt = piNumTriPtrNoModify[ivdx];
  261|  4.65k|        unsigned int *piList = adj.GetAdjacentTriangles(ivdx);
  262|  4.65k|        std::vector<unsigned int>::iterator piCurCandidate = piCandidates.begin();
  263|       |
  264|       |        // get all triangles in the neighborhood
  265|  24.5k|        for (unsigned int tri = 0; tri < icnt; ++tri) {
  ------------------
  |  Branch (265:36): [True: 19.9k, False: 4.65k]
  ------------------
  266|       |
  267|       |            // if they have not yet been emitted, add them to the output IB
  268|  19.9k|            const unsigned int fidx = *piList++;
  269|  19.9k|            if (!abEmitted[fidx]) {
  ------------------
  |  Branch (269:17): [True: 9.86k, False: 10.0k]
  ------------------
  270|       |
  271|       |                // so iterate through all vertices of the current triangle
  272|  9.86k|                const aiFace *pcFace = &pMesh->mFaces[fidx];
  273|  9.86k|                const unsigned nind = pcFace->mNumIndices;
  274|  39.4k|                for (unsigned ind = 0; ind < nind; ind++) {
  ------------------
  |  Branch (274:40): [True: 29.6k, False: 9.86k]
  ------------------
  275|  29.6k|                    unsigned dp = pcFace->mIndices[ind];
  276|       |
  277|       |                    // the current vertex won't have any free triangles after this step
  278|  29.6k|                    if (ivdx != (int)dp) {
  ------------------
  |  Branch (278:25): [True: 19.7k, False: 9.86k]
  ------------------
  279|       |                        // append the vertex to the dead-end stack
  280|  19.7k|                        sDeadEndVStack.push(dp);
  281|       |
  282|       |                        // register as candidate for the next step
  283|  19.7k|                        *piCurCandidate++ = dp;
  284|       |
  285|       |                        // decrease the per-vertex triangle counts
  286|  19.7k|                        piNumTriPtr[dp]--;
  287|  19.7k|                    }
  288|       |
  289|       |                    // append the vertex to the output index buffer
  290|  29.6k|                    *piCSIter++ = dp;
  291|       |
  292|       |                    // if the vertex is not yet in cache, set its cache count
  293|  29.6k|                    if (iStampCnt - piCachingStamps[dp] > mConfigCacheDepth) {
  ------------------
  |  Branch (293:25): [True: 11.2k, False: 18.3k]
  ------------------
  294|  11.2k|                        piCachingStamps[dp] = iStampCnt++;
  295|  11.2k|                        ++iCacheMisses;
  296|  11.2k|                    }
  297|  29.6k|                }
  298|       |                // flag triangle as emitted
  299|  9.86k|                abEmitted[fidx] = true;
  300|  9.86k|            }
  301|  19.9k|        }
  302|       |
  303|       |        // the vertex has now no living adjacent triangles anymore
  304|  4.65k|        piNumTriPtr[ivdx] = 0;
  305|       |
  306|       |        // get next fanning vertex
  307|  4.65k|        ivdx = -1;
  308|  4.65k|        int max_priority = -1;
  309|  24.3k|        for (std::vector<unsigned int>::iterator piCur = piCandidates.begin(); piCur != piCurCandidate; ++piCur) {
  ------------------
  |  Branch (309:80): [True: 19.7k, False: 4.65k]
  ------------------
  310|  19.7k|            const unsigned int dp = *piCur;
  311|       |
  312|       |            // must have live triangles
  313|  19.7k|            if (piNumTriPtr[dp] > 0) {
  ------------------
  |  Branch (313:17): [True: 13.0k, False: 6.72k]
  ------------------
  314|  13.0k|                int priority = 0;
  315|       |
  316|       |                // will the vertex be in cache, even after fanning occurs?
  317|  13.0k|                unsigned int tmp;
  318|  13.0k|                if ((tmp = iStampCnt - piCachingStamps[dp]) + 2 * piNumTriPtr[dp] <= mConfigCacheDepth) {
  ------------------
  |  Branch (318:21): [True: 7.95k, False: 5.06k]
  ------------------
  319|  7.95k|                    priority = tmp;
  320|  7.95k|                }
  321|       |
  322|       |                // keep best candidate
  323|  13.0k|                if (priority > max_priority) {
  ------------------
  |  Branch (323:21): [True: 4.10k, False: 8.90k]
  ------------------
  324|  4.10k|                    max_priority = priority;
  325|  4.10k|                    ivdx = dp;
  326|  4.10k|                }
  327|  13.0k|            }
  328|  19.7k|        }
  329|       |        // did we reach a dead end?
  330|  4.65k|        if (-1 == ivdx) {
  ------------------
  |  Branch (330:13): [True: 1.32k, False: 3.33k]
  ------------------
  331|       |            // need to get a non-local vertex for which we have a good chance that it is still
  332|       |            // in the cache ...
  333|  20.9k|            while (!sDeadEndVStack.empty()) {
  ------------------
  |  Branch (333:20): [True: 19.7k, False: 1.18k]
  ------------------
  334|  19.7k|                unsigned int iCachedIdx = sDeadEndVStack.top();
  335|  19.7k|                sDeadEndVStack.pop();
  336|  19.7k|                if (piNumTriPtr[iCachedIdx] > 0) {
  ------------------
  |  Branch (336:21): [True: 139, False: 19.5k]
  ------------------
  337|    139|                    ivdx = iCachedIdx;
  338|    139|                    break;
  339|    139|                }
  340|  19.7k|            }
  341|       |
  342|  1.32k|            if (-1 == ivdx) {
  ------------------
  |  Branch (342:17): [True: 1.18k, False: 139]
  ------------------
  343|       |                // well, there isn't such a vertex. Simply get the next vertex in input order and
  344|       |                // hope it is not too bad ...
  345|  9.54k|                while (ics < (int)pMesh->mNumVertices) {
  ------------------
  |  Branch (345:24): [True: 9.17k, False: 371]
  ------------------
  346|  9.17k|                    ++ics;
  347|  9.17k|                    if (piNumTriPtr[ics] > 0) {
  ------------------
  |  Branch (347:25): [True: 810, False: 8.36k]
  ------------------
  348|    810|                        ivdx = ics;
  349|    810|                        break;
  350|    810|                    }
  351|  9.17k|                }
  352|  1.18k|            }
  353|  1.32k|        }
  354|  4.65k|    }
  355|    371|    ai_real fACMR2 = 0.0f;
  356|    371|    if (!DefaultLogger::isNullLogger()) {
  ------------------
  |  Branch (356:9): [True: 0, False: 371]
  ------------------
  357|      0|        fACMR2 = static_cast<ai_real>(iCacheMisses / pMesh->mNumFaces);
  358|      0|        const ai_real averageACMR = ((fACMR - fACMR2) / fACMR) * 100.f;
  359|       |        // very intense verbose logging ... prepare for much text if there are many meshes
  360|      0|        if (DefaultLogger::get()->getLogSeverity() == Logger::VERBOSE) {
  ------------------
  |  Branch (360:13): [True: 0, False: 0]
  ------------------
  361|      0|            ASSIMP_LOG_VERBOSE_DEBUG("Mesh ", meshNum, "| ACMR in: ", fACMR, " out: ", fACMR2, " | average ACMR ", averageACMR);
  362|      0|        }
  363|      0|        fACMR2 *= pMesh->mNumFaces;
  364|      0|    }
  365|       |
  366|       |    // sort the output index buffer back to the input array
  367|    371|    piCSIter = piIBOutput.begin();
  368|  10.2k|    for (aiFace *pcFace = pMesh->mFaces; pcFace != pcEnd; ++pcFace) {
  ------------------
  |  Branch (368:42): [True: 9.86k, False: 371]
  ------------------
  369|  9.86k|        unsigned nind = pcFace->mNumIndices;
  370|  9.86k|        unsigned *ind = pcFace->mIndices;
  371|  9.86k|        if (nind > 0)
  ------------------
  |  Branch (371:13): [True: 9.86k, False: 0]
  ------------------
  372|  9.86k|            ind[0] = *piCSIter++;
  373|  9.86k|        if (nind > 1)
  ------------------
  |  Branch (373:13): [True: 9.86k, False: 0]
  ------------------
  374|  9.86k|            ind[1] = *piCSIter++;
  375|  9.86k|        if (nind > 2)
  ------------------
  |  Branch (375:13): [True: 9.86k, False: 0]
  ------------------
  376|  9.86k|            ind[2] = *piCSIter++;
  377|  9.86k|    }
  378|       |
  379|    371|    return fACMR2;
  380|    931|}

_ZNK6Assimp19JoinVerticesProcess8IsActiveEj:
   63|  1.50k|bool JoinVerticesProcess::IsActive( unsigned int pFlags) const {
   64|  1.50k|    return (pFlags & aiProcess_JoinIdenticalVertices) != 0;
   65|  1.50k|}
_ZN6Assimp19JoinVerticesProcess7ExecuteEP7aiScene:
   68|  1.50k|void JoinVerticesProcess::Execute( aiScene* pScene) {
   69|  1.50k|    ASSIMP_LOG_DEBUG("JoinVerticesProcess begin");
   70|       |
   71|       |    // get the total number of vertices BEFORE the step is executed
   72|  1.50k|    int iNumOldVertices = 0;
   73|  1.50k|    if (!DefaultLogger::isNullLogger()) {
  ------------------
  |  Branch (73:9): [True: 0, False: 1.50k]
  ------------------
   74|      0|        for( unsigned int a = 0; a < pScene->mNumMeshes; a++)   {
  ------------------
  |  Branch (74:34): [True: 0, False: 0]
  ------------------
   75|      0|            iNumOldVertices +=  pScene->mMeshes[a]->mNumVertices;
   76|      0|        }
   77|      0|    }
   78|       |
   79|       |    // execute the step
   80|  1.50k|    int iNumVertices = 0;
   81|  3.66k|    for( unsigned int a = 0; a < pScene->mNumMeshes; a++) {
  ------------------
  |  Branch (81:30): [True: 2.16k, False: 1.50k]
  ------------------
   82|  2.16k|        iNumVertices += ProcessMesh( pScene->mMeshes[a],a);
   83|  2.16k|    }
   84|       |
   85|  1.50k|    pScene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
   86|       |
   87|       |    // if logging is active, print detailed statistics
   88|  1.50k|    if (!DefaultLogger::isNullLogger()) {
  ------------------
  |  Branch (88:9): [True: 0, False: 1.50k]
  ------------------
   89|      0|        if (iNumOldVertices == iNumVertices) {
  ------------------
  |  Branch (89:13): [True: 0, False: 0]
  ------------------
   90|      0|            ASSIMP_LOG_DEBUG("JoinVerticesProcess finished ");
   91|      0|            return;
   92|      0|        }
   93|       |
   94|       |        // Show statistics
   95|      0|        ASSIMP_LOG_INFO("JoinVerticesProcess finished | Verts in: ", iNumOldVertices,
   96|      0|            " out: ", iNumVertices, " | ~",
   97|      0|            ((iNumOldVertices - iNumVertices) / (float)iNumOldVertices) * 100.f );
   98|      0|    }
   99|  1.50k|}
_ZN6Assimp19JoinVerticesProcess11ProcessMeshEP6aiMeshj:
  225|  2.16k|int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) {
  226|  2.16k|    static_assert( AI_MAX_NUMBER_OF_COLOR_SETS    == 8, "AI_MAX_NUMBER_OF_COLOR_SETS    == 8");
  227|  2.16k|	static_assert( AI_MAX_NUMBER_OF_TEXTURECOORDS == 8, "AI_MAX_NUMBER_OF_TEXTURECOORDS == 8");
  228|       |
  229|       |    // Return early if we don't have any positions
  230|  2.16k|    if (!pMesh->HasPositions() || !pMesh->HasFaces()) {
  ------------------
  |  Branch (230:9): [True: 0, False: 2.16k]
  |  Branch (230:35): [True: 0, False: 2.16k]
  ------------------
  231|      0|        return 0;
  232|      0|    }
  233|       |
  234|       |    // We should care only about used vertices, not all of them
  235|       |    // (this can happen due to original file vertices buffer being used by
  236|       |    // multiple meshes)
  237|  2.16k|    std::vector<bool> usedVertexIndicesMask;
  238|  2.16k|    usedVertexIndicesMask.resize(pMesh->mNumVertices, false);
  239|  23.8k|    for (unsigned int a = 0; a < pMesh->mNumFaces; a++) {
  ------------------
  |  Branch (239:30): [True: 21.6k, False: 2.16k]
  ------------------
  240|  21.6k|        aiFace& face = pMesh->mFaces[a];
  241|  73.4k|        for (unsigned int b = 0; b < face.mNumIndices; b++) {
  ------------------
  |  Branch (241:34): [True: 51.8k, False: 21.6k]
  ------------------
  242|  51.8k|            usedVertexIndicesMask[face.mIndices[b]] = true;
  243|  51.8k|        }
  244|  21.6k|    }
  245|       |
  246|       |    // We'll never have more vertices afterwards.
  247|  2.16k|    std::vector<int> uniqueVertices;
  248|       |
  249|       |    // For each vertex the index of the vertex it was replaced by.
  250|       |    // Since the maximal number of vertices is 2^31-1, the most significand bit can be used to mark
  251|       |    //  whether a new vertex was created for the index (true) or if it was replaced by an existing
  252|       |    //  unique vertex (false). This saves an additional std::vector<bool> and greatly enhances
  253|       |    //  branching performance.
  254|  2.16k|    static_assert(AI_MAX_VERTICES == 0x7fffffff, "AI_MAX_VERTICES == 0x7fffffff");
  255|  2.16k|    std::vector<unsigned int> replaceIndex( pMesh->mNumVertices, 0xffffffff);
  256|       |
  257|       |    // Run an optimized code path if we don't have multiple UVs or vertex colors.
  258|       |    // This should yield false in more than 99% of all imports ...
  259|  2.16k|    const bool hasAnimMeshes = pMesh->mNumAnimMeshes > 0;
  260|       |
  261|       |    // We'll never have more vertices afterwards.
  262|  2.16k|    std::vector<std::vector<int>> uniqueAnimatedVertices;
  263|  2.16k|    if (hasAnimMeshes) {
  ------------------
  |  Branch (263:9): [True: 0, False: 2.16k]
  ------------------
  264|      0|        uniqueAnimatedVertices.resize(pMesh->mNumAnimMeshes);
  265|      0|        for (unsigned int animMeshIndex = 0; animMeshIndex < pMesh->mNumAnimMeshes; animMeshIndex++) {
  ------------------
  |  Branch (265:46): [True: 0, False: 0]
  ------------------
  266|      0|            uniqueAnimatedVertices[animMeshIndex].reserve(pMesh->mNumVertices);
  267|      0|        }
  268|      0|    }
  269|       |    // a map that maps a vertex to its new index
  270|  2.16k|    std::unordered_map<Vertex, int, HashVertex, CompareVerticesAlmostEqual> vertex2Index = {};
  271|       |    // we can not end up with more vertices than we started with
  272|       |    // Now check each vertex if it brings something new to the table
  273|  2.16k|    int newIndex = 0;
  274|  51.1k|    for( unsigned int a = 0; a < pMesh->mNumVertices; a++)  {
  ------------------
  |  Branch (274:30): [True: 49.0k, False: 2.16k]
  ------------------
  275|       |        // if the vertex is unused Do nothing
  276|  49.0k|        if (!usedVertexIndicesMask[a]) {
  ------------------
  |  Branch (276:13): [True: 296, False: 48.7k]
  ------------------
  277|    296|            continue;
  278|    296|        }
  279|       |        // collect the vertex data
  280|  48.7k|        Vertex v(pMesh,a);
  281|       |        // is the vertex already in the map?
  282|  48.7k|        auto it = vertex2Index.find(v);
  283|       |        // if the vertex is not in the map then it is a new vertex add it.
  284|  48.7k|        if (it == vertex2Index.end()) {
  ------------------
  |  Branch (284:13): [True: 19.0k, False: 29.6k]
  ------------------
  285|       |            // this is a new vertex give it a new index
  286|  19.0k|            vertex2Index.emplace(v, newIndex);
  287|       |            // keep track of its index and increment 1
  288|  19.0k|            replaceIndex[a] = newIndex++;
  289|       |            // add the vertex to the unique vertices
  290|  19.0k|            uniqueVertices.push_back(a);
  291|  19.0k|            if (hasAnimMeshes) {
  ------------------
  |  Branch (291:17): [True: 0, False: 19.0k]
  ------------------
  292|      0|                for (unsigned int animMeshIndex = 0; animMeshIndex < pMesh->mNumAnimMeshes; animMeshIndex++) {
  ------------------
  |  Branch (292:54): [True: 0, False: 0]
  ------------------
  293|      0|                    uniqueAnimatedVertices[animMeshIndex].emplace_back(a);
  294|      0|                }
  295|      0|            }
  296|  29.6k|        } else{
  297|       |            // if the vertex is already there just find the replace index that is appropriate to it
  298|       |			// mark it with JOINED_VERTICES_MARK
  299|  29.6k|            replaceIndex[a] = it->second | JOINED_VERTICES_MARK;
  300|  29.6k|        }
  301|  48.7k|    }
  302|       |
  303|  2.16k|    if (!DefaultLogger::isNullLogger() && DefaultLogger::get()->getLogSeverity() == Logger::VERBOSE)    {
  ------------------
  |  Branch (303:9): [True: 0, False: 2.16k]
  |  Branch (303:43): [True: 0, False: 0]
  ------------------
  304|      0|        ASSIMP_LOG_VERBOSE_DEBUG(
  ------------------
  |  Branch (304:9): [True: 0, False: 0]
  ------------------
  305|      0|            "Mesh ",meshIndex,
  306|      0|            " (",
  307|      0|            (pMesh->mName.length ? pMesh->mName.data : "unnamed"),
  308|      0|            ") | Verts in: ",pMesh->mNumVertices,
  309|      0|            " out: ",
  310|      0|            uniqueVertices.size(),
  311|      0|            " | ~",
  312|      0|            ((pMesh->mNumVertices - uniqueVertices.size()) / (float)pMesh->mNumVertices) * 100.f,
  313|      0|            "%"
  314|      0|        );
  315|      0|    }
  316|       |
  317|  2.16k|    updateXMeshVertices(pMesh, uniqueVertices);
  318|  2.16k|    if (hasAnimMeshes) {
  ------------------
  |  Branch (318:9): [True: 0, False: 2.16k]
  ------------------
  319|      0|        for (unsigned int animMeshIndex = 0; animMeshIndex < pMesh->mNumAnimMeshes; animMeshIndex++) {
  ------------------
  |  Branch (319:46): [True: 0, False: 0]
  ------------------
  320|      0|            updateXMeshVertices(pMesh->mAnimMeshes[animMeshIndex], uniqueAnimatedVertices[animMeshIndex]);
  321|      0|        }
  322|      0|    }
  323|       |
  324|       |    // adjust the indices in all faces
  325|  23.8k|    for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
  ------------------
  |  Branch (325:30): [True: 21.6k, False: 2.16k]
  ------------------
  326|  21.6k|        aiFace& face = pMesh->mFaces[a];
  327|  73.4k|        for( unsigned int b = 0; b < face.mNumIndices; b++) {
  ------------------
  |  Branch (327:34): [True: 51.8k, False: 21.6k]
  ------------------
  328|  51.8k|            face.mIndices[b] = replaceIndex[face.mIndices[b]] & ~JOINED_VERTICES_MARK;
  329|  51.8k|        }
  330|  21.6k|    }
  331|       |
  332|       |    // adjust bone vertex weights.
  333|  4.21k|    for( int a = 0; a < (int)pMesh->mNumBones; a++) {
  ------------------
  |  Branch (333:21): [True: 2.05k, False: 2.16k]
  ------------------
  334|  2.05k|        aiBone* bone = pMesh->mBones[a];
  335|  2.05k|        std::vector<aiVertexWeight> newWeights;
  336|  2.05k|        newWeights.reserve( bone->mNumWeights);
  337|       |
  338|  2.05k|        if (nullptr != bone->mWeights) {
  ------------------
  |  Branch (338:13): [True: 2.05k, False: 0]
  ------------------
  339|  7.67k|            for ( unsigned int b = 0; b < bone->mNumWeights; b++ ) {
  ------------------
  |  Branch (339:39): [True: 5.62k, False: 2.05k]
  ------------------
  340|  5.62k|                const aiVertexWeight& ow = bone->mWeights[ b ];
  341|       |                // if the vertex is a unique one, translate it
  342|       |				// filter out joined vertices by JOINED_VERTICES_MARK.
  343|  5.62k|                if ( !( replaceIndex[ ow.mVertexId ] & JOINED_VERTICES_MARK ) ) {
  ------------------
  |  Branch (343:22): [True: 4.68k, False: 934]
  ------------------
  344|  4.68k|                    aiVertexWeight nw;
  345|  4.68k|                    nw.mVertexId = replaceIndex[ ow.mVertexId ];
  346|  4.68k|                    nw.mWeight = ow.mWeight;
  347|  4.68k|                    newWeights.push_back( nw );
  348|  4.68k|                }
  349|  5.62k|            }
  350|  2.05k|        } else {
  351|      0|            ASSIMP_LOG_ERROR( "X-Export: aiBone shall contain weights, but pointer to them is nullptr." );
  352|      0|        }
  353|       |
  354|  2.05k|        if (newWeights.size() > 0) {
  ------------------
  |  Branch (354:13): [True: 2.00k, False: 55]
  ------------------
  355|       |            // kill the old and replace them with the translated weights
  356|  2.00k|            delete [] bone->mWeights;
  357|  2.00k|            bone->mNumWeights = (unsigned int)newWeights.size();
  358|       |
  359|  2.00k|            bone->mWeights = new aiVertexWeight[bone->mNumWeights];
  360|  2.00k|            memcpy( bone->mWeights, &newWeights[0], bone->mNumWeights * sizeof( aiVertexWeight));
  361|  2.00k|        }
  362|  2.05k|    }
  363|  2.16k|    return pMesh->mNumVertices;
  364|  2.16k|}
JoinVerticesProcess.cpp:_ZNK12_GLOBAL__N_110HashVertexclERKN6Assimp6VertexE:
  151|  65.6k|    size_t operator () (const Vertex & v) const {
  152|  65.6k|        size_t hash = 0;
  153|       |
  154|  65.6k|        hash_combine(hash, v.position.x);
  155|  65.6k|        hash_combine(hash, v.position.y);
  156|  65.6k|        hash_combine(hash, v.position.z);
  157|       |
  158|  65.6k|        return hash;
  159|  65.6k|    }
JoinVerticesProcess.cpp:_ZNK12_GLOBAL__N_110HashVertex12hash_combineERmRKf:
  146|   196k|    inline void hash_combine(std::size_t& seed, const ai_real& v) const {
  147|   196k|        std::hash<ai_real> hasher;
  148|   196k|        seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
  149|   196k|    }
JoinVerticesProcess.cpp:_ZNK12_GLOBAL__N_126CompareVerticesAlmostEqualclERKN6Assimp6VertexES4_:
  104|  36.4k|    bool operator () (const Vertex & a, const Vertex & b) const {
  105|  36.4k|        static const float epsilon = 1e-5f;
  106|  36.4k|        static const float squareEpsilon = epsilon * epsilon;
  107|       |
  108|  36.4k|        if ((a.position - b.position).SquareLength() > squareEpsilon) {
  ------------------
  |  Branch (108:13): [True: 0, False: 36.4k]
  ------------------
  109|      0|            return false;
  110|      0|        }
  111|       |
  112|       |        // We just test the other attributes even if they're not present in the mesh.
  113|       |        // In this case they're initialized to 0 so the comparison succeeds.
  114|       |        // By this method the non-present attributes are effectively ignored in the comparison.
  115|       |
  116|  36.4k|        if ((a.normal - b.normal).SquareLength() > squareEpsilon) {
  ------------------
  |  Branch (116:13): [True: 2.98k, False: 33.5k]
  ------------------
  117|  2.98k|            return false;
  118|  2.98k|        }
  119|       |
  120|  33.5k|        if ((a.tangent - b.tangent).SquareLength() > squareEpsilon) {
  ------------------
  |  Branch (120:13): [True: 2.52k, False: 30.9k]
  ------------------
  121|  2.52k|            return false;
  122|  2.52k|        }
  123|       |
  124|  30.9k|        if ((a.bitangent - b.bitangent).SquareLength() > squareEpsilon) {
  ------------------
  |  Branch (124:13): [True: 420, False: 30.5k]
  ------------------
  125|    420|            return false;
  126|    420|        }
  127|       |
  128|   268k|        for (uint32_t i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; i ++) {
  ------------------
  |  Branch (128:30): [True: 238k, False: 29.7k]
  ------------------
  129|   238k|            if ((a.texcoords[i] - b.texcoords[i]).SquareLength() > squareEpsilon) {
  ------------------
  |  Branch (129:17): [True: 822, False: 238k]
  ------------------
  130|    822|                return false;
  131|    822|            }
  132|   238k|        }
  133|       |
  134|   267k|        for (uint32_t i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; i ++) {
  ------------------
  |  Branch (134:30): [True: 237k, False: 29.6k]
  ------------------
  135|   237k|            if (GetColorDifference(a.colors[i], b.colors[i]) > squareEpsilon) {
  ------------------
  |  Branch (135:17): [True: 93, False: 237k]
  ------------------
  136|     93|                return false;
  137|     93|            }
  138|   237k|        }
  139|       |
  140|       |        // If reached this point, they are ~equal
  141|  29.6k|        return true;
  142|  29.7k|    }
JoinVerticesProcess.cpp:_ZN12_GLOBAL__N_119updateXMeshVerticesI6aiMeshEEvPT_RNSt3__16vectorIiNS4_9allocatorIiEEEE:
  163|  2.16k|void updateXMeshVertices(XMesh *pMesh, std::vector<int> &uniqueVertices) {
  164|       |    // replace vertex data with the unique data sets
  165|  2.16k|    pMesh->mNumVertices = (unsigned int)uniqueVertices.size();
  166|       |
  167|       |    // ----------------------------------------------------------------------------
  168|       |    // NOTE - we're *not* calling Vertex::SortBack() because it would check for
  169|       |    // presence of every single vertex component once PER VERTEX. And our CPU
  170|       |    // dislikes branches, even if they're easily predictable.
  171|       |    // ----------------------------------------------------------------------------
  172|       |
  173|       |    // Position, if present (check made for aiAnimMesh)
  174|  2.16k|    if (pMesh->mVertices) {
  ------------------
  |  Branch (174:9): [True: 2.16k, False: 0]
  ------------------
  175|  2.16k|        std::unique_ptr<aiVector3D[]> oldVertices(pMesh->mVertices);
  176|  2.16k|        pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
  177|  21.2k|        for (unsigned int a = 0; a < pMesh->mNumVertices; a++)
  ------------------
  |  Branch (177:34): [True: 19.0k, False: 2.16k]
  ------------------
  178|  19.0k|            pMesh->mVertices[a] = oldVertices[uniqueVertices[a]];
  179|  2.16k|    }
  180|       |
  181|       |    // Normals, if present
  182|  2.16k|    if (pMesh->mNormals) {
  ------------------
  |  Branch (182:9): [True: 1.63k, False: 526]
  ------------------
  183|  1.63k|        std::unique_ptr<aiVector3D[]> oldNormals(pMesh->mNormals);
  184|  1.63k|        pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
  185|  16.7k|        for (unsigned int a = 0; a < pMesh->mNumVertices; a++)
  ------------------
  |  Branch (185:34): [True: 15.0k, False: 1.63k]
  ------------------
  186|  15.0k|            pMesh->mNormals[a] = oldNormals[uniqueVertices[a]];
  187|  1.63k|    }
  188|       |    // Tangents, if present
  189|  2.16k|    if (pMesh->mTangents) {
  ------------------
  |  Branch (189:9): [True: 361, False: 1.80k]
  ------------------
  190|    361|        std::unique_ptr<aiVector3D[]> oldTangents(pMesh->mTangents);
  191|    361|        pMesh->mTangents = new aiVector3D[pMesh->mNumVertices];
  192|  4.83k|        for (unsigned int a = 0; a < pMesh->mNumVertices; a++)
  ------------------
  |  Branch (192:34): [True: 4.47k, False: 361]
  ------------------
  193|  4.47k|            pMesh->mTangents[a] = oldTangents[uniqueVertices[a]];
  194|    361|    }
  195|       |    // Bitangents as well
  196|  2.16k|    if (pMesh->mBitangents) {
  ------------------
  |  Branch (196:9): [True: 361, False: 1.80k]
  ------------------
  197|    361|        std::unique_ptr<aiVector3D[]> oldBitangents(pMesh->mBitangents);
  198|    361|        pMesh->mBitangents = new aiVector3D[pMesh->mNumVertices];
  199|  4.83k|        for (unsigned int a = 0; a < pMesh->mNumVertices; a++)
  ------------------
  |  Branch (199:34): [True: 4.47k, False: 361]
  ------------------
  200|  4.47k|            pMesh->mBitangents[a] = oldBitangents[uniqueVertices[a]];
  201|    361|    }
  202|       |    // Vertex colors
  203|  2.36k|    for (unsigned int a = 0; pMesh->HasVertexColors(a); a++) {
  ------------------
  |  Branch (203:30): [True: 202, False: 2.16k]
  ------------------
  204|    202|        std::unique_ptr<aiColor4D[]> oldColors(pMesh->mColors[a]);
  205|    202|        pMesh->mColors[a] = new aiColor4D[pMesh->mNumVertices];
  206|    957|        for (unsigned int b = 0; b < pMesh->mNumVertices; b++)
  ------------------
  |  Branch (206:34): [True: 755, False: 202]
  ------------------
  207|    755|            pMesh->mColors[a][b] = oldColors[uniqueVertices[b]];
  208|    202|    }
  209|       |    // Texture coords
  210|  2.78k|    for (unsigned int a = 0; pMesh->HasTextureCoords(a); a++) {
  ------------------
  |  Branch (210:30): [True: 625, False: 2.16k]
  ------------------
  211|    625|        std::unique_ptr<aiVector3D[]> oldTextureCoords(pMesh->mTextureCoords[a]);
  212|    625|        pMesh->mTextureCoords[a] = new aiVector3D[pMesh->mNumVertices];
  213|  5.93k|        for (unsigned int b = 0; b < pMesh->mNumVertices; b++)
  ------------------
  |  Branch (213:34): [True: 5.31k, False: 625]
  ------------------
  214|  5.31k|            pMesh->mTextureCoords[a][b] = oldTextureCoords[uniqueVertices[b]];
  215|    625|    }
  216|  2.16k|}

_ZN6Assimp19JoinVerticesProcessC2Ev:
   67|  5.13k|    JoinVerticesProcess() = default;

_ZN6Assimp23LimitBoneWeightsProcessC2Ev:
   57|  5.13k|        mMaxWeights(AI_LMW_MAX_WEIGHTS), mRemoveEmptyBones(true) {
   58|       |    // empty
   59|  5.13k|}
_ZNK6Assimp23LimitBoneWeightsProcess8IsActiveEj:
   63|  1.50k|bool LimitBoneWeightsProcess::IsActive( unsigned int pFlags) const {
   64|  1.50k|    return (pFlags & aiProcess_LimitBoneWeights) != 0;
   65|  1.50k|}
_ZN6Assimp23LimitBoneWeightsProcess7ExecuteEP7aiScene:
   69|  1.50k|void LimitBoneWeightsProcess::Execute( aiScene* pScene) {
   70|  1.50k|    ai_assert(pScene != nullptr);
   71|       |
   72|  1.50k|    ASSIMP_LOG_DEBUG("LimitBoneWeightsProcess begin");
   73|       |
   74|  3.66k|    for (unsigned int m = 0; m < pScene->mNumMeshes; ++m) {
  ------------------
  |  Branch (74:30): [True: 2.16k, False: 1.50k]
  ------------------
   75|  2.16k|        ProcessMesh(pScene->mMeshes[m]);
   76|  2.16k|    }
   77|       |
   78|       |    ASSIMP_LOG_DEBUG("LimitBoneWeightsProcess end");
   79|  1.50k|}
_ZN6Assimp23LimitBoneWeightsProcess15SetupPropertiesEPKNS_8ImporterE:
   83|  1.50k|void LimitBoneWeightsProcess::SetupProperties(const Importer* pImp) {
   84|  1.50k|    this->mMaxWeights = pImp->GetPropertyInteger(AI_CONFIG_PP_LBW_MAX_WEIGHTS,AI_LMW_MAX_WEIGHTS);
   85|       |    this->mRemoveEmptyBones = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, 1) != 0;
   86|  1.50k|}
_ZN6Assimp23LimitBoneWeightsProcess11ProcessMeshEP6aiMesh:
  107|  2.16k|void LimitBoneWeightsProcess::ProcessMesh(aiMesh* pMesh) {
  108|  2.16k|    if (!pMesh->HasBones())
  ------------------
  |  Branch (108:9): [True: 1.82k, False: 339]
  ------------------
  109|  1.82k|        return;
  110|       |
  111|       |    // collect all bone weights per vertex
  112|    339|    typedef SmallVector<Weight,8> VertexWeightArray;
  113|    339|    typedef std::vector<VertexWeightArray> WeightsPerVertex;
  114|    339|    WeightsPerVertex vertexWeights(pMesh->mNumVertices);
  115|    339|    size_t maxVertexWeights = 0;
  116|       |
  117|  2.39k|    for (unsigned int b = 0; b < pMesh->mNumBones; ++b) {
  ------------------
  |  Branch (117:30): [True: 2.05k, False: 339]
  ------------------
  118|  2.05k|        const aiBone* bone = pMesh->mBones[b];
  119|  6.81k|        for (unsigned int w = 0; w < bone->mNumWeights; ++w) {
  ------------------
  |  Branch (119:34): [True: 4.75k, False: 2.05k]
  ------------------
  120|  4.75k|            const aiVertexWeight& vw = bone->mWeights[w];
  121|       |
  122|  4.75k|            if (vertexWeights.size() <= vw.mVertexId)
  ------------------
  |  Branch (122:17): [True: 38, False: 4.71k]
  ------------------
  123|     38|                continue;
  124|       |
  125|  4.71k|            vertexWeights[vw.mVertexId].push_back(Weight(b, vw.mWeight));
  126|  4.71k|            maxVertexWeights = std::max(maxVertexWeights, vertexWeights[vw.mVertexId].size());
  127|  4.71k|        }
  128|  2.05k|    }
  129|       |
  130|    339|    if (maxVertexWeights <= mMaxWeights)
  ------------------
  |  Branch (130:9): [True: 144, False: 195]
  ------------------
  131|    144|        return;
  132|       |
  133|    195|    unsigned int removed = 0, old_bones = pMesh->mNumBones;
  134|       |
  135|       |    // now cut the weight count if it exceeds the maximum
  136|    830|    for (WeightsPerVertex::iterator vit = vertexWeights.begin(); vit != vertexWeights.end(); ++vit) {
  ------------------
  |  Branch (136:66): [True: 635, False: 195]
  ------------------
  137|    635|        if (vit->size() <= mMaxWeights)
  ------------------
  |  Branch (137:13): [True: 133, False: 502]
  ------------------
  138|    133|            continue;
  139|       |
  140|       |        // more than the defined maximum -> first sort by weight in descending order. That's
  141|       |        // why we defined the < operator in such a weird way.
  142|    502|        std::sort(vit->begin(), vit->end());
  143|       |
  144|       |        // now kill everything beyond the maximum count
  145|    502|        unsigned int m = static_cast<unsigned int>(vit->size());
  146|    502|        vit->resize(mMaxWeights);
  147|    502|        removed += static_cast<unsigned int>(m - vit->size());
  148|       |
  149|       |        // and renormalize the weights
  150|    502|        float sum = 0.0f;
  151|  2.51k|        for(const Weight* it = vit->begin(); it != vit->end(); ++it) {
  ------------------
  |  Branch (151:46): [True: 2.00k, False: 502]
  ------------------
  152|  2.00k|            sum += it->mWeight;
  153|  2.00k|        }
  154|    502|        if (0.0f != sum) {
  ------------------
  |  Branch (154:13): [True: 489, False: 13]
  ------------------
  155|    489|            const float invSum = 1.0f / sum;
  156|  2.44k|            for(Weight* it = vit->begin(); it != vit->end(); ++it) {
  ------------------
  |  Branch (156:44): [True: 1.95k, False: 489]
  ------------------
  157|  1.95k|                it->mWeight *= invSum;
  158|  1.95k|            }
  159|    489|        }
  160|    502|    }
  161|       |
  162|       |    // clear weight count for all bone
  163|  1.97k|    for (unsigned int a = 0; a < pMesh->mNumBones; ++a) {
  ------------------
  |  Branch (163:30): [True: 1.77k, False: 195]
  ------------------
  164|  1.77k|        pMesh->mBones[a]->mNumWeights = 0;
  165|  1.77k|    }
  166|       |
  167|       |    // rebuild the vertex weight array for all bones
  168|    830|    for (unsigned int a = 0; a < vertexWeights.size(); ++a) {
  ------------------
  |  Branch (168:30): [True: 635, False: 195]
  ------------------
  169|    635|        const VertexWeightArray& vw = vertexWeights[a];
  170|  2.98k|        for (const Weight* it = vw.begin(); it != vw.end(); ++it) {
  ------------------
  |  Branch (170:45): [True: 2.34k, False: 635]
  ------------------
  171|  2.34k|            aiBone* bone = pMesh->mBones[it->mBone];
  172|  2.34k|            bone->mWeights[bone->mNumWeights++] = aiVertexWeight(a, it->mWeight);
  173|  2.34k|        }
  174|    635|    }
  175|       |
  176|       |    // remove empty bones
  177|    195|    if (mRemoveEmptyBones) {
  ------------------
  |  Branch (177:9): [True: 195, False: 0]
  ------------------
  178|    195|        pMesh->mNumBones = removeEmptyBones(pMesh);
  179|    195|    }
  180|       |
  181|    195|    if (!DefaultLogger::isNullLogger()) {
  ------------------
  |  Branch (181:9): [True: 0, False: 195]
  ------------------
  182|       |        ASSIMP_LOG_INFO("Removed ", removed, " weights. Input bones: ", old_bones, ". Output bones: ", pMesh->mNumBones);
  183|      0|    }
  184|    195|}
LimitBoneWeightsProcess.cpp:_ZN6AssimpL16removeEmptyBonesEP6aiMesh:
   89|    195|static unsigned int removeEmptyBones(aiMesh *pMesh) {
   90|    195|    ai_assert(pMesh != nullptr);
   91|       |
   92|    195|    unsigned int writeBone = 0;
   93|  1.97k|    for (unsigned int readBone = 0; readBone< pMesh->mNumBones; ++readBone) {
  ------------------
  |  Branch (93:37): [True: 1.77k, False: 195]
  ------------------
   94|  1.77k|        aiBone* bone = pMesh->mBones[readBone];
   95|  1.77k|        if (bone->mNumWeights > 0) {
  ------------------
  |  Branch (95:13): [True: 922, False: 856]
  ------------------
   96|    922|            pMesh->mBones[writeBone++] = bone;
   97|    922|        } else {
   98|    856|            delete bone;
   99|    856|        }
  100|  1.77k|    }
  101|       |
  102|    195|    return writeBone;
  103|    195|}

_ZN6Assimp23LimitBoneWeightsProcess6WeightC2Ev:
  116|  11.6k|        : mBone(0)
  117|  11.6k|        , mWeight(0.0f) {
  118|       |            // empty
  119|  11.6k|        }
_ZN6Assimp23LimitBoneWeightsProcess6WeightC2Ejf:
  122|  4.71k|        : mBone(pBone)
  123|  4.71k|        , mWeight(pWeight) {
  124|       |            // empty
  125|  4.71k|        }
_ZNK6Assimp23LimitBoneWeightsProcess6WeightltERKS1_:
  128|  6.39k|        bool operator < (const Weight& pWeight) const {
  129|  6.39k|            return mWeight > pWeight.mWeight;
  130|  6.39k|        }

_ZN6Assimp20OptimizeGraphProcessC2Ev:
   77|  5.13k|		count_merged() {
   78|       |	// empty
   79|  5.13k|}
_ZNK6Assimp20OptimizeGraphProcess8IsActiveEj:
   83|  1.54k|bool OptimizeGraphProcess::IsActive(unsigned int pFlags) const {
   84|  1.54k|	return (0 != (pFlags & aiProcess_OptimizeGraph));
   85|  1.54k|}

_ZN6Assimp20OptimizeGraphProcessD2Ev:
   76|  5.13k|    ~OptimizeGraphProcess() override = default;

_ZN6Assimp21OptimizeMeshesProcessC2Ev:
   66|  5.13k|    , pts(false)
   67|  5.13k|    , max_verts( NotSet )
   68|  5.13k|    , max_faces( NotSet ) {
   69|       |    // empty
   70|  5.13k|}
_ZNK6Assimp21OptimizeMeshesProcess8IsActiveEj:
   75|  1.50k|{
   76|       |    // Our behaviour needs to be different if the SortByPType or SplitLargeMeshes
   77|       |    // steps are active. Thus we need to query their flags here and store the
   78|       |    // information, although we're breaking const-correctness.
   79|       |    // That's a serious design flaw, consider redesign.
   80|  1.50k|    if( 0 != (pFlags & aiProcess_OptimizeMeshes) ) {
  ------------------
  |  Branch (80:9): [True: 0, False: 1.50k]
  ------------------
   81|      0|        pts = (0 != (pFlags & aiProcess_SortByPType));
   82|      0|        max_verts = ( 0 != ( pFlags & aiProcess_SplitLargeMeshes ) ) ? DeadBeef : max_verts;
  ------------------
  |  Branch (82:21): [True: 0, False: 0]
  ------------------
   83|      0|        return true;
   84|      0|    }
   85|  1.50k|    return false;
   86|  1.50k|}

_ZN6Assimp21OptimizeMeshesProcessD2Ev:
   73|  5.13k|    ~OptimizeMeshesProcess() override = default;

_ZN6Assimp20PretransformVerticesC2Ev:
   90|  5.13k|		mConfigKeepHierarchy(false),
   91|  5.13k|		mConfigNormalize(false),
   92|  5.13k|		mConfigTransform(false),
   93|  5.13k|		mConfigTransformation(),
   94|  5.13k|		mConfigPointCloud(false) {}
_ZNK6Assimp20PretransformVertices8IsActiveEj:
   98|  1.54k|bool PretransformVertices::IsActive(unsigned int pFlags) const {
   99|  1.54k|	return (pFlags & aiProcess_PreTransformVertices) != 0;
  100|  1.54k|}

_ZN6Assimp22ComputePositionEpsilonEPK6aiMesh:
  136|  2.16k|ai_real ComputePositionEpsilon(const aiMesh *pMesh) {
  137|  2.16k|    const ai_real epsilon = ai_real(1e-4);
  138|       |
  139|       |    // calculate the position bounds so we have a reliable epsilon to check position differences against
  140|  2.16k|    aiVector3D minVec, maxVec;
  141|  2.16k|    ArrayBounds(pMesh->mVertices, pMesh->mNumVertices, minVec, maxVec);
  142|  2.16k|    return (maxVec - minVec).Length() * epsilon;
  143|  2.16k|}
_ZN6Assimp28ComputeVertexBoneWeightTableEPK6aiMesh:
  199|    817|VertexWeightTable *ComputeVertexBoneWeightTable(const aiMesh *pMesh) {
  200|    817|    if (!pMesh || !pMesh->mNumVertices || !pMesh->mNumBones) {
  ------------------
  |  Branch (200:9): [True: 0, False: 817]
  |  Branch (200:19): [True: 0, False: 817]
  |  Branch (200:43): [True: 673, False: 144]
  ------------------
  201|    673|        return nullptr;
  202|    673|    }
  203|       |
  204|    144|    VertexWeightTable *avPerVertexWeights = new VertexWeightTable[pMesh->mNumVertices];
  205|    991|    for (unsigned int i = 0; i < pMesh->mNumBones; ++i) {
  ------------------
  |  Branch (205:30): [True: 847, False: 144]
  ------------------
  206|       |
  207|    847|        aiBone *bone = pMesh->mBones[i];
  208|  3.04k|        for (unsigned int a = 0; a < bone->mNumWeights; ++a) {
  ------------------
  |  Branch (208:34): [True: 2.19k, False: 847]
  ------------------
  209|  2.19k|            const aiVertexWeight &weight = bone->mWeights[a];
  210|  2.19k|            avPerVertexWeights[weight.mVertexId].emplace_back(i, weight.mWeight);
  211|  2.19k|        }
  212|    847|    }
  213|    144|    return avPerVertexWeights;
  214|    817|}

_ZNK6Assimp25ComputeSpatialSortProcess8IsActiveEj:
  337|  1.50k|    bool IsActive(unsigned int pFlags) const {
  338|  1.50k|        return nullptr != shared && 0 != (pFlags & (aiProcess_CalcTangentSpace |
  ------------------
  |  Branch (338:16): [True: 1.50k, False: 0]
  |  Branch (338:37): [True: 1.50k, False: 0]
  ------------------
  339|  1.50k|                                                           aiProcess_GenNormals | aiProcess_JoinIdenticalVertices));
  340|  1.50k|    }
_ZN6Assimp25ComputeSpatialSortProcess7ExecuteEP7aiScene:
  342|  1.50k|    void Execute(aiScene *pScene) {
  343|  1.50k|        typedef std::pair<SpatialSort, ai_real> _Type;
  344|  1.50k|        ASSIMP_LOG_DEBUG("Generate spatially-sorted vertex cache");
  345|       |
  346|  1.50k|        std::vector<_Type> *p = new std::vector<_Type>(pScene->mNumMeshes);
  347|  1.50k|        std::vector<_Type>::iterator it = p->begin();
  348|       |
  349|  3.66k|        for (unsigned int i = 0; i < pScene->mNumMeshes; ++i, ++it) {
  ------------------
  |  Branch (349:34): [True: 2.16k, False: 1.50k]
  ------------------
  350|  2.16k|            aiMesh *mesh = pScene->mMeshes[i];
  351|  2.16k|            _Type &blubb = *it;
  352|  2.16k|            blubb.first.Fill(mesh->mVertices, mesh->mNumVertices, sizeof(aiVector3D));
  353|  2.16k|            blubb.second = ComputePositionEpsilon(mesh);
  354|  2.16k|        }
  355|       |
  356|  1.50k|        shared->AddProperty(AI_SPP_SPATIAL_SORT, p);
  ------------------
  |  |  166|  1.50k|#define AI_SPP_SPATIAL_SORT "$Spat"
  ------------------
  357|  1.50k|    }
_ZNK6Assimp25DestroySpatialSortProcess8IsActiveEj:
  363|  1.50k|    bool IsActive(unsigned int pFlags) const {
  364|  1.50k|        return nullptr != shared && 0 != (pFlags & (aiProcess_CalcTangentSpace |
  ------------------
  |  Branch (364:16): [True: 1.50k, False: 0]
  |  Branch (364:37): [True: 1.50k, False: 0]
  ------------------
  365|  1.50k|                                                        aiProcess_GenNormals | aiProcess_JoinIdenticalVertices));
  366|  1.50k|    }
_ZN6Assimp25DestroySpatialSortProcess7ExecuteEP7aiScene:
  368|  1.50k|    void Execute(aiScene * /*pScene*/) {
  369|  1.50k|        shared->RemoveProperty(AI_SPP_SPATIAL_SORT);
  ------------------
  |  |  166|  1.50k|#define AI_SPP_SPATIAL_SORT "$Spat"
  ------------------
  370|  1.50k|    }
_ZN6Assimp18GetColorDifferenceERK9aiColor4tIfES3_:
  250|   237k|inline ai_real GetColorDifference(const aiColor4D &pColor1, const aiColor4D &pColor2) {
  251|   237k|    const aiColor4D c(pColor1.r - pColor2.r, pColor1.g - pColor2.g, pColor1.b - pColor2.b, pColor1.a - pColor2.a);
  252|   237k|    return c.r * c.r + c.g * c.g + c.b * c.b + c.a * c.a;
  253|   237k|}
_ZSt3minIfE10aiVector3tIT_ERKS2_S4_:
   67|  49.0k|inline ::aiVector3t<TReal> min(const ::aiVector3t<TReal> &a, const ::aiVector3t<TReal> &b) {
   68|  49.0k|    return ::aiVector3t<TReal>(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z));
   69|  49.0k|}
_ZSt3maxIfE10aiVector3tIT_ERKS2_S4_:
   73|  49.0k|inline ::aiVector3t<TReal> max(const ::aiVector3t<TReal> &a, const ::aiVector3t<TReal> &b) {
   74|  49.0k|    return ::aiVector3t<TReal>(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z));
   75|  49.0k|}
_ZN6Assimp13MinMaxChooserI10aiVector3tIfEEclERS2_S4_:
  177|  2.16k|    void operator()(aiVector3t<T> &min, aiVector3t<T> &max) {
  178|  2.16k|        max = aiVector3t<T>(-1e10f, -1e10f, -1e10f);
  179|  2.16k|        min = aiVector3t<T>(1e10f, 1e10f, 1e10f);
  180|  2.16k|    }
_ZN6Assimp11ArrayBoundsI10aiVector3tIfEEEvPKT_jRS3_S6_:
  236|  2.16k|inline void ArrayBounds(const T *in, unsigned int size, T &min, T &max) {
  237|  2.16k|    MinMaxChooser<T>()(min, max);
  238|  51.1k|    for (unsigned int i = 0; i < size; ++i) {
  ------------------
  |  Branch (238:30): [True: 49.0k, False: 2.16k]
  ------------------
  239|  49.0k|        min = std::min(in[i], min);
  240|  49.0k|        max = std::max(in[i], max);
  241|  49.0k|    }
  242|  2.16k|}

_ZN6Assimp26RemoveRedundantMatsProcessC2Ev:
   57|  5.13k|RemoveRedundantMatsProcess::RemoveRedundantMatsProcess() : mConfigFixedMaterials() {}
_ZNK6Assimp26RemoveRedundantMatsProcess8IsActiveEj:
   61|  1.54k|bool RemoveRedundantMatsProcess::IsActive( unsigned int pFlags) const {
   62|  1.54k|    return (pFlags & aiProcess_RemoveRedundantMaterials) != 0;
   63|  1.54k|}
_ZN6Assimp26RemoveRedundantMatsProcess15SetupPropertiesEPKNS_8ImporterE:
   67|  1.54k|void RemoveRedundantMatsProcess::SetupProperties(const Importer* pImp) {
   68|       |    // Get value of AI_CONFIG_PP_RRM_EXCLUDE_LIST
   69|       |    mConfigFixedMaterials = pImp->GetPropertyString(AI_CONFIG_PP_RRM_EXCLUDE_LIST,"");
   70|  1.54k|}
_ZN6Assimp26RemoveRedundantMatsProcess7ExecuteEP7aiScene:
   74|  1.54k|void RemoveRedundantMatsProcess::Execute( aiScene* pScene) {
   75|  1.54k|    ASSIMP_LOG_DEBUG("RemoveRedundantMatsProcess begin");
   76|       |
   77|  1.54k|    unsigned int redundantRemoved = 0, unreferencedRemoved = 0;
   78|  1.54k|    if (pScene->mNumMaterials == 0) {
  ------------------
  |  Branch (78:9): [True: 0, False: 1.54k]
  ------------------
   79|      0|        return;
   80|      0|    }
   81|       |
   82|       |    // Find out which materials are referenced by meshes
   83|  1.54k|    std::vector<bool> abReferenced(pScene->mNumMaterials,false);
   84|  2.98k|    for (unsigned int i = 0;i < pScene->mNumMeshes;++i) {
  ------------------
  |  Branch (84:29): [True: 1.43k, False: 1.54k]
  ------------------
   85|  1.43k|        abReferenced[pScene->mMeshes[i]->mMaterialIndex] = true;
   86|  1.43k|    }
   87|       |
   88|       |    // If a list of materials to be excluded was given, match the list with
   89|       |    // our imported materials and 'salt' all positive matches to ensure that
   90|       |    // we get unique hashes later.
   91|  1.54k|    if (mConfigFixedMaterials.length()) {
  ------------------
  |  Branch (91:9): [True: 0, False: 1.54k]
  ------------------
   92|      0|        std::list<std::string> strings;
   93|      0|        ConvertListToStrings(mConfigFixedMaterials,strings);
   94|       |
   95|      0|        for (unsigned int i = 0; i < pScene->mNumMaterials;++i) {
  ------------------
  |  Branch (95:34): [True: 0, False: 0]
  ------------------
   96|      0|            aiMaterial* mat = pScene->mMaterials[i];
   97|      0|            ai_assert(mat != nullptr);
   98|      0|            aiString name;
   99|      0|            mat->Get(AI_MATKEY_NAME,name);
  100|       |
  101|      0|            if (name.length != 0) {
  ------------------
  |  Branch (101:17): [True: 0, False: 0]
  ------------------
  102|      0|                std::list<std::string>::const_iterator it = std::find(strings.begin(), strings.end(), name.data);
  103|      0|                if (it != strings.end()) {
  ------------------
  |  Branch (103:21): [True: 0, False: 0]
  ------------------
  104|       |                    // Our brilliant 'salt': A single material property with ~ as first
  105|       |                    // character to mark it as internal and temporary.
  106|      0|                    const int dummy = 1;
  107|      0|                    ((aiMaterial*)mat)->AddProperty(&dummy,1,"~RRM.UniqueMaterial",0,0);
  108|       |
  109|       |                    // Keep this material even if no mesh references it
  110|      0|                    abReferenced[i] = true;
  111|      0|                    ASSIMP_LOG_VERBOSE_DEBUG( "Found positive match in exclusion list: \'", name.data, "\'");
  112|      0|                }
  113|      0|            }
  114|      0|        }
  115|      0|    }
  116|       |
  117|       |    // TODO: re-implement this algorithm to work in-place
  118|  1.54k|    unsigned int *aiMappingTable = new unsigned int[pScene->mNumMaterials];
  119|  4.16k|    for ( unsigned int i=0; i<pScene->mNumMaterials; i++ ) {
  ------------------
  |  Branch (119:29): [True: 2.62k, False: 1.54k]
  ------------------
  120|  2.62k|        aiMappingTable[ i ] = 0;
  121|  2.62k|    }
  122|  1.54k|    unsigned int iNewNum = 0;
  123|       |
  124|       |    // Iterate through all materials and calculate a hash for them
  125|       |    // store all hashes in a list and so a quick search whether
  126|       |    // we do already have a specific hash. This allows us to
  127|       |    // determine which materials are identical.
  128|  1.54k|    uint32_t *aiHashes = new uint32_t[ pScene->mNumMaterials ];
  129|  4.16k|    for (unsigned int i = 0; i < pScene->mNumMaterials;++i) {
  ------------------
  |  Branch (129:30): [True: 2.62k, False: 1.54k]
  ------------------
  130|       |        // No mesh is referencing this material, remove it.
  131|  2.62k|        if (!abReferenced[i]) {
  ------------------
  |  Branch (131:13): [True: 1.22k, False: 1.40k]
  ------------------
  132|  1.22k|            ++unreferencedRemoved;
  133|  1.22k|            delete pScene->mMaterials[i];
  134|  1.22k|            pScene->mMaterials[i] = nullptr;
  135|  1.22k|            continue;
  136|  1.22k|        }
  137|       |
  138|       |        // Check all previously mapped materials for a matching hash.
  139|       |        // On a match we can delete this material and just make it ref to the same index.
  140|  1.40k|        uint32_t me = aiHashes[i] = ComputeMaterialHash(pScene->mMaterials[i]);
  141|  1.73k|        for (unsigned int a = 0; a < i;++a) {
  ------------------
  |  Branch (141:34): [True: 357, False: 1.38k]
  ------------------
  142|    357|            if (abReferenced[a] && me == aiHashes[a]) {
  ------------------
  |  Branch (142:17): [True: 357, False: 0]
  |  Branch (142:17): [True: 20, False: 337]
  |  Branch (142:36): [True: 20, False: 337]
  ------------------
  143|     20|                ++redundantRemoved;
  144|     20|                me = 0;
  145|     20|                aiMappingTable[i] = aiMappingTable[a];
  146|     20|                delete pScene->mMaterials[i];
  147|     20|                pScene->mMaterials[i] = nullptr;
  148|     20|                break;
  149|     20|            }
  150|    357|        }
  151|       |        // This is a new material that is referenced, add to the map.
  152|  1.40k|        if (me) {
  ------------------
  |  Branch (152:13): [True: 1.38k, False: 20]
  ------------------
  153|  1.38k|            aiMappingTable[i] = iNewNum++;
  154|  1.38k|        }
  155|  1.40k|    }
  156|       |    // If the new material count differs from the original,
  157|       |    // we need to rebuild the material list and remap mesh material indexes.
  158|  1.54k|    if (iNewNum < 1) {
  ------------------
  |  Branch (158:9): [True: 326, False: 1.22k]
  ------------------
  159|    326|        delete [] aiMappingTable;
  160|    326|        delete [] aiHashes;
  161|    326|        pScene->mNumMaterials = 0;
  162|    326|        return;
  163|    326|    }
  164|  1.22k|    if (iNewNum != pScene->mNumMaterials) {
  ------------------
  |  Branch (164:9): [True: 905, False: 317]
  ------------------
  165|    905|        ai_assert(iNewNum > 0);
  166|    905|        aiMaterial** ppcMaterials = new aiMaterial*[iNewNum];
  167|    905|        ::memset(ppcMaterials,0,sizeof(void*)*iNewNum);
  168|  2.81k|        for (unsigned int p = 0; p < pScene->mNumMaterials;++p) {
  ------------------
  |  Branch (168:34): [True: 1.91k, False: 905]
  ------------------
  169|       |            // if the material is not referenced ... remove it
  170|  1.91k|            if (!abReferenced[p]) {
  ------------------
  |  Branch (170:17): [True: 894, False: 1.02k]
  ------------------
  171|    894|                continue;
  172|    894|            }
  173|       |
  174|       |            // generate new names for modified materials that had no names
  175|  1.02k|            const unsigned int idx = aiMappingTable[p];
  176|  1.02k|            if (ppcMaterials[idx]) {
  ------------------
  |  Branch (176:17): [True: 20, False: 1.00k]
  ------------------
  177|     20|                aiString sz;
  178|     20|                if( ppcMaterials[idx]->Get(AI_MATKEY_NAME, sz) != AI_SUCCESS ) {
  ------------------
  |  Branch (178:21): [True: 8, False: 12]
  ------------------
  179|      8|                    sz.length = ::ai_snprintf(sz.data, AI_MAXLEN,"JoinedMaterial_#%u",p);
  180|      8|                    ((aiMaterial*)ppcMaterials[idx])->AddProperty(&sz,AI_MATKEY_NAME);
  181|      8|                }
  182|  1.00k|            } else {
  183|  1.00k|                ppcMaterials[idx] = pScene->mMaterials[p];
  184|  1.00k|            }
  185|  1.02k|        }
  186|       |        // update all material indices
  187|  1.94k|        for (unsigned int p = 0; p < pScene->mNumMeshes;++p) {
  ------------------
  |  Branch (187:34): [True: 1.04k, False: 905]
  ------------------
  188|  1.04k|            aiMesh* mesh = pScene->mMeshes[p];
  189|  1.04k|            ai_assert(nullptr != mesh);
  190|  1.04k|            mesh->mMaterialIndex = aiMappingTable[mesh->mMaterialIndex];
  191|  1.04k|        }
  192|       |        // delete the old material list
  193|    905|        delete[] pScene->mMaterials;
  194|    905|        pScene->mMaterials = ppcMaterials;
  195|    905|        pScene->mNumMaterials = iNewNum;
  196|    905|    }
  197|       |    // delete temporary storage
  198|  1.22k|    delete[] aiHashes;
  199|  1.22k|    delete[] aiMappingTable;
  200|       |
  201|  1.22k|    if (redundantRemoved == 0 && unreferencedRemoved == 0) {
  ------------------
  |  Branch (201:9): [True: 1.20k, False: 16]
  |  Branch (201:34): [True: 317, False: 889]
  ------------------
  202|    317|        ASSIMP_LOG_DEBUG("RemoveRedundantMatsProcess finished ");
  203|    905|    } else {
  204|       |        ASSIMP_LOG_INFO("RemoveRedundantMatsProcess finished. Removed ", redundantRemoved, " redundant and ",
  205|    905|            unreferencedRemoved, " unused materials.");
  206|    905|    }
  207|  1.22k|}

_ZN6Assimp26RemoveRedundantMatsProcessD2Ev:
   64|  5.13k|    ~RemoveRedundantMatsProcess() override = default;

_ZN6Assimp15RemoveVCProcessC2Ev:
   55|  5.13k|        configDeleteFlags(), mScene() {}
_ZNK6Assimp15RemoveVCProcess8IsActiveEj:
   59|  1.54k|bool RemoveVCProcess::IsActive(unsigned int pFlags) const {
   60|  1.54k|    return (pFlags & aiProcess_RemoveComponent) != 0;
   61|  1.54k|}

_ZN6Assimp12ScaleProcessC2Ev:
   50|  5.13k|ScaleProcess::ScaleProcess() : BaseProcess(), mScale( AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT ) {
   51|       |    // empty
   52|  5.13k|}
_ZNK6Assimp12ScaleProcess8IsActiveEj:
   65|  1.54k|bool ScaleProcess::IsActive( unsigned int pFlags ) const {
   66|  1.54k|    return ( pFlags & aiProcess_GlobalScale ) != 0;
   67|  1.54k|}

_ZN6Assimp18SortByPTypeProcessC2Ev:
   55|  5.13k|SortByPTypeProcess::SortByPTypeProcess() : mConfigRemoveMeshes(0) {}
_ZNK6Assimp18SortByPTypeProcess8IsActiveEj:
   59|  1.54k|bool SortByPTypeProcess::IsActive(unsigned int pFlags) const {
   60|  1.54k|    return (pFlags & aiProcess_SortByPType) != 0;
   61|  1.54k|}
_ZN6Assimp18SortByPTypeProcess15SetupPropertiesEPKNS_8ImporterE:
   64|  1.54k|void SortByPTypeProcess::SetupProperties(const Importer *pImp) {
   65|       |    mConfigRemoveMeshes = pImp->GetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, 0);
   66|  1.54k|}
_Z11UpdateNodesRKNSt3__16vectorIjNS_9allocatorIjEEEEP6aiNode:
   77|  3.22k|void UpdateNodes(const std::vector<unsigned int> &replaceMeshIndex, aiNode *node) {
   78|  3.22k|    ai_assert(node != nullptr);
   79|       |
   80|  3.22k|    if (node->mNumMeshes) {
  ------------------
  |  Branch (80:9): [True: 937, False: 2.28k]
  ------------------
   81|    937|        unsigned int newSize = 0;
   82|  1.87k|        for (unsigned int m = 0; m < node->mNumMeshes; ++m) {
  ------------------
  |  Branch (82:34): [True: 937, False: 937]
  ------------------
   83|    937|            unsigned int add = node->mMeshes[m] << 2;
   84|  4.68k|            for (unsigned int i = 0; i < 4; ++i) {
  ------------------
  |  Branch (84:38): [True: 3.74k, False: 937]
  ------------------
   85|  3.74k|                if (UINT_MAX != replaceMeshIndex[add + i]) {
  ------------------
  |  Branch (85:21): [True: 1.96k, False: 1.78k]
  ------------------
   86|  1.96k|                    ++newSize;
   87|  1.96k|                }
   88|  3.74k|            }
   89|    937|        }
   90|    937|        if (newSize == 0) {
  ------------------
  |  Branch (90:13): [True: 0, False: 937]
  ------------------
   91|      0|            clearMeshesInNode(node);
   92|      0|            return;
   93|      0|        }
   94|       |
   95|       |        // Try to reuse the old array if possible
   96|    937|        unsigned int *newMeshes = (newSize > node->mNumMeshes ? new unsigned int[newSize] : node->mMeshes);
  ------------------
  |  Branch (96:36): [True: 827, False: 110]
  ------------------
   97|  1.87k|        for (unsigned int m = 0; m < node->mNumMeshes; ++m) {
  ------------------
  |  Branch (97:34): [True: 937, False: 937]
  ------------------
   98|    937|            unsigned int add = node->mMeshes[m] << 2;
   99|  4.68k|            for (unsigned int i = 0; i < 4; ++i) {
  ------------------
  |  Branch (99:38): [True: 3.74k, False: 937]
  ------------------
  100|  3.74k|                if (UINT_MAX != replaceMeshIndex[add + i]) {
  ------------------
  |  Branch (100:21): [True: 1.96k, False: 1.78k]
  ------------------
  101|  1.96k|                    *newMeshes++ = replaceMeshIndex[add + i];
  102|  1.96k|                }
  103|  3.74k|            }
  104|    937|        }
  105|    937|        if (newSize > node->mNumMeshes) {
  ------------------
  |  Branch (105:13): [True: 827, False: 110]
  ------------------
  106|    827|            clearMeshesInNode(node);
  107|    827|        }
  108|    937|        node->mMeshes = newMeshes - (node->mNumMeshes = newSize);
  109|    937|    }
  110|       |
  111|       |    // call all subnodes recursively
  112|  5.64k|    for (unsigned int m = 0; m < node->mNumChildren; ++m) {
  ------------------
  |  Branch (112:30): [True: 2.42k, False: 3.22k]
  ------------------
  113|  2.42k|        UpdateNodes(replaceMeshIndex, node->mChildren[m]);
  114|  2.42k|    }
  115|  3.22k|}
_ZN6Assimp18SortByPTypeProcess7ExecuteEP7aiScene:
  119|  1.54k|void SortByPTypeProcess::Execute(aiScene *pScene) {
  120|  1.54k|    if (0 == pScene->mNumMeshes) {
  ------------------
  |  Branch (120:9): [True: 326, False: 1.22k]
  ------------------
  121|    326|        ASSIMP_LOG_DEBUG("SortByPTypeProcess skipped, there are no meshes");
  122|    326|        return;
  123|    326|    }
  124|       |
  125|  1.54k|    ASSIMP_LOG_DEBUG("SortByPTypeProcess begin");
  126|       |
  127|  1.22k|    unsigned int aiNumMeshesPerPType[4] = { 0, 0, 0, 0 };
  128|       |
  129|  1.22k|    std::vector<aiMesh *> outMeshes;
  130|  1.22k|    outMeshes.reserve(static_cast<size_t>(pScene->mNumMeshes) << 1u);
  131|       |
  132|  1.22k|    bool bAnyChanges = false;
  133|       |
  134|  1.22k|    std::vector<unsigned int> replaceMeshIndex(pScene->mNumMeshes * 4, UINT_MAX);
  135|  1.22k|    std::vector<unsigned int>::iterator meshIdx = replaceMeshIndex.begin();
  136|  2.65k|    for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
  ------------------
  |  Branch (136:30): [True: 1.43k, False: 1.22k]
  ------------------
  137|  1.43k|        aiMesh *const mesh = pScene->mMeshes[i];
  138|  1.43k|        if (mesh->mPrimitiveTypes == 0) {
  ------------------
  |  Branch (138:13): [True: 0, False: 1.43k]
  ------------------
  139|      0|            for (size_t idx = 0; idx < outMeshes.size(); ++idx) {
  ------------------
  |  Branch (139:34): [True: 0, False: 0]
  ------------------
  140|      0|                delete outMeshes[idx];
  141|      0|            }
  142|      0|            throw DeadlyImportError("Mesh with invalid primitive type: ", mesh->mName.C_Str());
  143|      0|        }
  144|       |
  145|       |        // if there's just one primitive type in the mesh there's nothing to do for us
  146|  1.43k|        unsigned int num = 0;
  147|  1.43k|        if (mesh->mPrimitiveTypes & aiPrimitiveType_POINT) {
  ------------------
  |  Branch (147:13): [True: 595, False: 839]
  ------------------
  148|    595|            ++aiNumMeshesPerPType[0];
  149|    595|            ++num;
  150|    595|        }
  151|  1.43k|        if (mesh->mPrimitiveTypes & aiPrimitiveType_LINE) {
  ------------------
  |  Branch (151:13): [True: 859, False: 575]
  ------------------
  152|    859|            ++aiNumMeshesPerPType[1];
  153|    859|            ++num;
  154|    859|        }
  155|  1.43k|        if (mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE) {
  ------------------
  |  Branch (155:13): [True: 991, False: 443]
  ------------------
  156|    991|            ++aiNumMeshesPerPType[2];
  157|    991|            ++num;
  158|    991|        }
  159|  1.43k|        if (mesh->mPrimitiveTypes & aiPrimitiveType_POLYGON) {
  ------------------
  |  Branch (159:13): [True: 0, False: 1.43k]
  ------------------
  160|      0|            ++aiNumMeshesPerPType[3];
  161|      0|            ++num;
  162|      0|        }
  163|       |
  164|  1.43k|        if (1 == num) {
  ------------------
  |  Branch (164:13): [True: 617, False: 817]
  ------------------
  165|    617|            if (!(mConfigRemoveMeshes & mesh->mPrimitiveTypes)) {
  ------------------
  |  Branch (165:17): [True: 617, False: 0]
  ------------------
  166|    617|                *meshIdx = static_cast<unsigned int>(outMeshes.size());
  167|    617|                outMeshes.emplace_back(mesh);
  168|    617|                pScene->mMeshes[i] = nullptr; // Indicate ownership transfer
  169|    617|            } else {
  170|      0|                delete mesh;
  171|      0|                pScene->mMeshes[i] = nullptr;
  172|      0|                bAnyChanges = true;
  173|      0|            }
  174|       |
  175|    617|            meshIdx += 4;
  176|    617|            continue;
  177|    617|        }
  178|    817|        bAnyChanges = true;
  179|       |
  180|       |        // reuse our current mesh arrays for the submesh
  181|       |        // with the largest number of primitives
  182|    817|        unsigned int aiNumPerPType[4] = { 0, 0, 0, 0 };
  183|    817|        aiFace *pFirstFace = mesh->mFaces;
  184|    817|        if (pFirstFace == nullptr) {
  ------------------
  |  Branch (184:13): [True: 0, False: 817]
  ------------------
  185|      0|            continue;
  186|      0|        }
  187|       |
  188|    817|        aiFace *const pLastFace = pFirstFace + mesh->mNumFaces;
  189|       |
  190|    817|        unsigned int numPolyVerts = 0;
  191|  20.8k|        for (; pFirstFace != pLastFace; ++pFirstFace) {
  ------------------
  |  Branch (191:16): [True: 20.0k, False: 817]
  ------------------
  192|  20.0k|            if (pFirstFace->mNumIndices >= 1 && pFirstFace->mNumIndices <= 3)
  ------------------
  |  Branch (192:17): [True: 20.0k, False: 0]
  |  Branch (192:49): [True: 20.0k, False: 0]
  ------------------
  193|  20.0k|                ++aiNumPerPType[pFirstFace->mNumIndices - 1];
  194|      0|            else {
  195|      0|                ++aiNumPerPType[3];
  196|      0|                numPolyVerts += pFirstFace->mNumIndices;
  197|      0|            }
  198|  20.0k|            if (pFirstFace->mNumIndices == 0) {
  ------------------
  |  Branch (198:17): [True: 0, False: 20.0k]
  ------------------
  199|      0|                ASSIMP_LOG_WARN("Face with 0 indices treated as polygon");
  200|      0|            }
  201|  20.0k|        }
  202|       |
  203|    817|        VertexWeightTable *avw = ComputeVertexBoneWeightTable(mesh);
  204|  4.08k|        for (unsigned int real = 0; real < 4; ++real, ++meshIdx) {
  ------------------
  |  Branch (204:37): [True: 3.26k, False: 817]
  ------------------
  205|  3.26k|            if (!aiNumPerPType[real] || mConfigRemoveMeshes & (1u << real)) {
  ------------------
  |  Branch (205:17): [True: 1.44k, False: 1.82k]
  |  Branch (205:41): [True: 0, False: 1.82k]
  ------------------
  206|  1.44k|                continue;
  207|  1.44k|            }
  208|       |
  209|  1.82k|            *meshIdx = (unsigned int)outMeshes.size();
  210|  1.82k|            outMeshes.push_back(new aiMesh());
  211|  1.82k|            aiMesh *out = outMeshes.back();
  212|       |
  213|       |            // the name carries the adjacency information between the meshes
  214|  1.82k|            out->mName = mesh->mName;
  215|       |
  216|       |            // copy data members
  217|  1.82k|            out->mPrimitiveTypes = 1u << real;
  218|  1.82k|            out->mMaterialIndex = mesh->mMaterialIndex;
  219|       |
  220|       |            // allocate output storage
  221|  1.82k|            out->mNumFaces = aiNumPerPType[real];
  222|  1.82k|            aiFace *outFaces = out->mFaces = new aiFace[out->mNumFaces];
  223|       |
  224|  1.82k|            out->mNumVertices = (3 == real ? numPolyVerts : out->mNumFaces * (real + 1));
  ------------------
  |  Branch (224:34): [True: 0, False: 1.82k]
  ------------------
  225|       |
  226|  1.82k|            aiVector3D *vert(nullptr), *nor(nullptr), *tan(nullptr), *bit(nullptr);
  227|  1.82k|            aiVector3D *uv[AI_MAX_NUMBER_OF_TEXTURECOORDS];
  228|  1.82k|            aiColor4D *cols[AI_MAX_NUMBER_OF_COLOR_SETS];
  229|       |
  230|  1.82k|            if (mesh->mVertices) {
  ------------------
  |  Branch (230:17): [True: 1.82k, False: 0]
  ------------------
  231|  1.82k|                vert = out->mVertices = new aiVector3D[out->mNumVertices];
  232|  1.82k|            }
  233|       |
  234|  1.82k|            if (mesh->mNormals) {
  ------------------
  |  Branch (234:17): [True: 1.00k, False: 827]
  ------------------
  235|  1.00k|                nor = out->mNormals = new aiVector3D[out->mNumVertices];
  236|  1.00k|            }
  237|       |
  238|  1.82k|            if (mesh->mTangents) {
  ------------------
  |  Branch (238:17): [True: 0, False: 1.82k]
  ------------------
  239|      0|                tan = out->mTangents = new aiVector3D[out->mNumVertices];
  240|      0|                bit = out->mBitangents = new aiVector3D[out->mNumVertices];
  241|      0|            }
  242|       |
  243|  16.4k|            for (unsigned int j = 0; j < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++j) {
  ------------------
  |  Branch (243:38): [True: 14.6k, False: 1.82k]
  ------------------
  244|  14.6k|                uv[j] = nullptr;
  245|  14.6k|                if (mesh->mTextureCoords[j]) {
  ------------------
  |  Branch (245:21): [True: 449, False: 14.1k]
  ------------------
  246|    449|                    uv[j] = out->mTextureCoords[j] = new aiVector3D[out->mNumVertices];
  247|    449|                }
  248|       |
  249|  14.6k|                out->mNumUVComponents[j] = mesh->mNumUVComponents[j];
  250|  14.6k|            }
  251|       |
  252|  16.4k|            for (unsigned int j = 0; j < AI_MAX_NUMBER_OF_COLOR_SETS; ++j) {
  ------------------
  |  Branch (252:38): [True: 14.6k, False: 1.82k]
  ------------------
  253|  14.6k|                cols[j] = nullptr;
  254|  14.6k|                if (mesh->mColors[j]) {
  ------------------
  |  Branch (254:21): [True: 153, False: 14.4k]
  ------------------
  255|    153|                    cols[j] = out->mColors[j] = new aiColor4D[out->mNumVertices];
  256|    153|                }
  257|  14.6k|            }
  258|       |
  259|  1.82k|            if (mesh->mNumAnimMeshes > 0 && mesh->mAnimMeshes) {
  ------------------
  |  Branch (259:17): [True: 0, False: 1.82k]
  |  Branch (259:45): [True: 0, False: 0]
  ------------------
  260|      0|                out->mNumAnimMeshes = mesh->mNumAnimMeshes;
  261|      0|                out->mAnimMeshes = new aiAnimMesh *[out->mNumAnimMeshes];
  262|      0|            }
  263|       |
  264|  1.82k|            for (unsigned int j = 0; j < mesh->mNumAnimMeshes; ++j) {
  ------------------
  |  Branch (264:38): [True: 0, False: 1.82k]
  ------------------
  265|      0|                aiAnimMesh *animMesh = mesh->mAnimMeshes[j];
  266|      0|                aiAnimMesh *outAnimMesh = out->mAnimMeshes[j] = new aiAnimMesh;
  267|      0|                outAnimMesh->mNumVertices = out->mNumVertices;
  268|      0|                if (animMesh->mVertices)
  ------------------
  |  Branch (268:21): [True: 0, False: 0]
  ------------------
  269|      0|                    outAnimMesh->mVertices = new aiVector3D[out->mNumVertices];
  270|      0|                else
  271|      0|                    outAnimMesh->mVertices = nullptr;
  272|      0|                if (animMesh->mNormals)
  ------------------
  |  Branch (272:21): [True: 0, False: 0]
  ------------------
  273|      0|                    outAnimMesh->mNormals = new aiVector3D[out->mNumVertices];
  274|      0|                else
  275|      0|                    outAnimMesh->mNormals = nullptr;
  276|      0|                if (animMesh->mTangents)
  ------------------
  |  Branch (276:21): [True: 0, False: 0]
  ------------------
  277|      0|                    outAnimMesh->mTangents = new aiVector3D[out->mNumVertices];
  278|      0|                else
  279|      0|                    outAnimMesh->mTangents = nullptr;
  280|      0|                if (animMesh->mBitangents)
  ------------------
  |  Branch (280:21): [True: 0, False: 0]
  ------------------
  281|      0|                    outAnimMesh->mBitangents = new aiVector3D[out->mNumVertices];
  282|      0|                else
  283|      0|                    outAnimMesh->mBitangents = nullptr;
  284|      0|                for (int jj = 0; jj < AI_MAX_NUMBER_OF_COLOR_SETS; ++jj) {
  ------------------
  |  Branch (284:34): [True: 0, False: 0]
  ------------------
  285|      0|                    if (animMesh->mColors[jj])
  ------------------
  |  Branch (285:25): [True: 0, False: 0]
  ------------------
  286|      0|                        outAnimMesh->mColors[jj] = new aiColor4D[out->mNumVertices];
  287|      0|                    else
  288|      0|                        outAnimMesh->mColors[jj] = nullptr;
  289|      0|                }
  290|      0|                for (int jj = 0; jj < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++jj) {
  ------------------
  |  Branch (290:34): [True: 0, False: 0]
  ------------------
  291|      0|                    if (animMesh->mTextureCoords[jj])
  ------------------
  |  Branch (291:25): [True: 0, False: 0]
  ------------------
  292|      0|                        outAnimMesh->mTextureCoords[jj] = new aiVector3D[out->mNumVertices];
  293|      0|                    else
  294|      0|                        outAnimMesh->mTextureCoords[jj] = nullptr;
  295|      0|                }
  296|      0|            }
  297|       |
  298|  1.82k|            typedef std::vector<aiVertexWeight> TempBoneInfo;
  299|  1.82k|            std::vector<TempBoneInfo> tempBones(mesh->mNumBones);
  300|       |
  301|       |            // try to guess how much storage we'll need
  302|  3.56k|            for (unsigned int q = 0; q < mesh->mNumBones; ++q) {
  ------------------
  |  Branch (302:38): [True: 1.73k, False: 1.82k]
  ------------------
  303|  1.73k|                tempBones[q].reserve(mesh->mBones[q]->mNumWeights / (num - 1));
  304|  1.73k|            }
  305|       |
  306|  1.82k|            unsigned int outIdx = 0;
  307|  1.82k|            unsigned int amIdx = 0; // AnimMesh index
  308|  46.0k|            for (unsigned int m = 0; m < mesh->mNumFaces; ++m) {
  ------------------
  |  Branch (308:38): [True: 44.1k, False: 1.82k]
  ------------------
  309|  44.1k|                aiFace &in = mesh->mFaces[m];
  310|  44.1k|                if ((real == 3 && in.mNumIndices <= 3) || (real != 3 && in.mNumIndices != real + 1)) {
  ------------------
  |  Branch (310:22): [True: 0, False: 44.1k]
  |  Branch (310:35): [True: 0, False: 0]
  |  Branch (310:60): [True: 44.1k, False: 0]
  |  Branch (310:73): [True: 24.1k, False: 20.0k]
  ------------------
  311|  24.1k|                    continue;
  312|  24.1k|                }
  313|       |
  314|  20.0k|                outFaces->mNumIndices = in.mNumIndices;
  315|  20.0k|                outFaces->mIndices = in.mIndices;
  316|       |
  317|  66.8k|                for (unsigned int q = 0; q < in.mNumIndices; ++q) {
  ------------------
  |  Branch (317:42): [True: 46.7k, False: 20.0k]
  ------------------
  318|  46.7k|                    unsigned int idx = in.mIndices[q];
  319|       |
  320|       |                    // process all bones of this index
  321|  46.7k|                    if (avw) {
  ------------------
  |  Branch (321:25): [True: 1.47k, False: 45.2k]
  ------------------
  322|  1.47k|                        VertexWeightTable &tbl = avw[idx];
  323|  1.47k|                        for (VertexWeightTable::const_iterator it = tbl.begin(), end = tbl.end();
  324|  5.95k|                                it != end; ++it) {
  ------------------
  |  Branch (324:33): [True: 4.47k, False: 1.47k]
  ------------------
  325|  4.47k|                            tempBones[(*it).first].emplace_back(outIdx, (*it).second);
  326|  4.47k|                        }
  327|  1.47k|                    }
  328|       |
  329|  46.7k|                    if (vert) {
  ------------------
  |  Branch (329:25): [True: 46.7k, False: 0]
  ------------------
  330|  46.7k|                        *vert++ = mesh->mVertices[idx];
  331|  46.7k|                    }
  332|  46.7k|                    if (nor)
  ------------------
  |  Branch (332:25): [True: 13.1k, False: 33.5k]
  ------------------
  333|  13.1k|                        *nor++ = mesh->mNormals[idx];
  334|  46.7k|                    if (tan) {
  ------------------
  |  Branch (334:25): [True: 0, False: 46.7k]
  ------------------
  335|      0|                        *tan++ = mesh->mTangents[idx];
  336|      0|                        *bit++ = mesh->mBitangents[idx];
  337|      0|                    }
  338|       |
  339|  52.0k|                    for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++pp) {
  ------------------
  |  Branch (339:47): [True: 52.0k, False: 0]
  ------------------
  340|  52.0k|                        if (!uv[pp])
  ------------------
  |  Branch (340:29): [True: 46.7k, False: 5.30k]
  ------------------
  341|  46.7k|                            break;
  342|  5.30k|                        *uv[pp]++ = mesh->mTextureCoords[pp][idx];
  343|  5.30k|                    }
  344|       |
  345|  47.5k|                    for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_COLOR_SETS; ++pp) {
  ------------------
  |  Branch (345:47): [True: 47.5k, False: 0]
  ------------------
  346|  47.5k|                        if (!cols[pp])
  ------------------
  |  Branch (346:29): [True: 46.7k, False: 810]
  ------------------
  347|  46.7k|                            break;
  348|    810|                        *cols[pp]++ = mesh->mColors[pp][idx];
  349|    810|                    }
  350|       |
  351|  46.7k|                    unsigned int pp = 0;
  352|  46.7k|                    for (; pp < mesh->mNumAnimMeshes; ++pp) {
  ------------------
  |  Branch (352:28): [True: 0, False: 46.7k]
  ------------------
  353|      0|                        aiAnimMesh *animMesh = mesh->mAnimMeshes[pp];
  354|      0|                        aiAnimMesh *outAnimMesh = out->mAnimMeshes[pp];
  355|      0|                        if (animMesh->mVertices)
  ------------------
  |  Branch (355:29): [True: 0, False: 0]
  ------------------
  356|      0|                            outAnimMesh->mVertices[amIdx] = animMesh->mVertices[idx];
  357|      0|                        if (animMesh->mNormals)
  ------------------
  |  Branch (357:29): [True: 0, False: 0]
  ------------------
  358|      0|                            outAnimMesh->mNormals[amIdx] = animMesh->mNormals[idx];
  359|      0|                        if (animMesh->mTangents)
  ------------------
  |  Branch (359:29): [True: 0, False: 0]
  ------------------
  360|      0|                            outAnimMesh->mTangents[amIdx] = animMesh->mTangents[idx];
  361|      0|                        if (animMesh->mBitangents)
  ------------------
  |  Branch (361:29): [True: 0, False: 0]
  ------------------
  362|      0|                            outAnimMesh->mBitangents[amIdx] = animMesh->mBitangents[idx];
  363|      0|                        for (int jj = 0; jj < AI_MAX_NUMBER_OF_COLOR_SETS; ++jj) {
  ------------------
  |  Branch (363:42): [True: 0, False: 0]
  ------------------
  364|      0|                            if (animMesh->mColors[jj])
  ------------------
  |  Branch (364:33): [True: 0, False: 0]
  ------------------
  365|      0|                                outAnimMesh->mColors[jj][amIdx] = animMesh->mColors[jj][idx];
  366|      0|                        }
  367|      0|                        for (int jj = 0; jj < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++jj) {
  ------------------
  |  Branch (367:42): [True: 0, False: 0]
  ------------------
  368|      0|                            if (animMesh->mTextureCoords[jj])
  ------------------
  |  Branch (368:33): [True: 0, False: 0]
  ------------------
  369|      0|                                outAnimMesh->mTextureCoords[jj][amIdx] = animMesh->mTextureCoords[jj][idx];
  370|      0|                        }
  371|      0|                    }
  372|  46.7k|                    if (pp == mesh->mNumAnimMeshes)
  ------------------
  |  Branch (372:25): [True: 46.7k, False: 0]
  ------------------
  373|  46.7k|                        ++amIdx;
  374|       |
  375|  46.7k|                    in.mIndices[q] = outIdx++;
  376|  46.7k|                }
  377|       |
  378|  20.0k|                in.mIndices = nullptr;
  379|  20.0k|                ++outFaces;
  380|  20.0k|            }
  381|  1.82k|            ai_assert(outFaces == out->mFaces + out->mNumFaces);
  382|       |
  383|       |            // now generate output bones
  384|  3.56k|            for (unsigned int q = 0; q < mesh->mNumBones; ++q) {
  ------------------
  |  Branch (384:38): [True: 1.73k, False: 1.82k]
  ------------------
  385|  1.73k|                if (!tempBones[q].empty()) {
  ------------------
  |  Branch (385:21): [True: 1.55k, False: 184]
  ------------------
  386|  1.55k|                    ++out->mNumBones;
  387|  1.55k|                }
  388|  1.73k|            }
  389|       |
  390|  1.82k|            if (out->mNumBones) {
  ------------------
  |  Branch (390:17): [True: 302, False: 1.52k]
  ------------------
  391|    302|                out->mBones = new aiBone *[out->mNumBones];
  392|  2.01k|                for (unsigned int q = 0, boneIdx = 0; q < mesh->mNumBones; ++q) {
  ------------------
  |  Branch (392:55): [True: 1.71k, False: 302]
  ------------------
  393|  1.71k|                    TempBoneInfo &in = tempBones[q];
  394|  1.71k|                    if (in.empty()) {
  ------------------
  |  Branch (394:25): [True: 159, False: 1.55k]
  ------------------
  395|    159|                        continue;
  396|    159|                    }
  397|       |
  398|  1.55k|                    aiBone *srcBone = mesh->mBones[q];
  399|  1.55k|                    aiBone *bone = out->mBones[boneIdx] = new aiBone();
  400|       |
  401|  1.55k|                    bone->mName = srcBone->mName;
  402|  1.55k|                    bone->mOffsetMatrix = srcBone->mOffsetMatrix;
  403|       |
  404|  1.55k|                    bone->mNumWeights = (unsigned int)in.size();
  405|  1.55k|                    bone->mWeights = new aiVertexWeight[bone->mNumWeights];
  406|       |
  407|  1.55k|                    ::memcpy(bone->mWeights, &in[0], bone->mNumWeights * sizeof(aiVertexWeight));
  408|       |
  409|  1.55k|                    ++boneIdx;
  410|  1.55k|                }
  411|    302|            }
  412|  1.82k|        }
  413|       |
  414|       |        // delete the per-vertex bone weights table
  415|    817|        delete[] avw;
  416|       |
  417|       |        // delete the input mesh
  418|    817|        delete mesh;
  419|       |
  420|       |        // avoid invalid pointer
  421|    817|        pScene->mMeshes[i] = nullptr;
  422|    817|    }
  423|       |
  424|  1.22k|    if (outMeshes.empty()) {
  ------------------
  |  Branch (424:9): [True: 0, False: 1.22k]
  ------------------
  425|       |        // This should not occur
  426|      0|        throw DeadlyImportError("No meshes remaining");
  427|      0|    }
  428|       |
  429|       |    // If we added at least one mesh process all nodes in the node
  430|       |    // graph and update their respective mesh indices.
  431|  1.22k|    if (bAnyChanges) {
  ------------------
  |  Branch (431:9): [True: 798, False: 424]
  ------------------
  432|    798|        UpdateNodes(replaceMeshIndex, pScene->mRootNode);
  433|    798|    }
  434|       |
  435|  1.22k|    if (outMeshes.size() != pScene->mNumMeshes) {
  ------------------
  |  Branch (435:9): [True: 798, False: 424]
  ------------------
  436|    798|        delete[] pScene->mMeshes;
  437|    798|        pScene->mNumMeshes = (unsigned int)outMeshes.size();
  438|    798|        pScene->mMeshes = new aiMesh *[pScene->mNumMeshes];
  439|    798|    }
  440|  1.22k|    ::memcpy(pScene->mMeshes, &outMeshes[0], pScene->mNumMeshes * sizeof(void *));
  441|       |
  442|  1.22k|    if (!DefaultLogger::isNullLogger()) {
  ------------------
  |  Branch (442:9): [True: 0, False: 1.22k]
  ------------------
  443|      0|        char buffer[1024];
  444|      0|        ::ai_snprintf(buffer, 1024, "Points: %u%s, Lines: %u%s, Triangles: %u%s, Polygons: %u%s (Meshes, X = removed)",
  445|      0|                aiNumMeshesPerPType[0], ((mConfigRemoveMeshes & aiPrimitiveType_POINT) ? "X" : ""),
  ------------------
  |  Branch (445:42): [True: 0, False: 0]
  ------------------
  446|      0|                aiNumMeshesPerPType[1], ((mConfigRemoveMeshes & aiPrimitiveType_LINE) ? "X" : ""),
  ------------------
  |  Branch (446:42): [True: 0, False: 0]
  ------------------
  447|      0|                aiNumMeshesPerPType[2], ((mConfigRemoveMeshes & aiPrimitiveType_TRIANGLE) ? "X" : ""),
  ------------------
  |  Branch (447:42): [True: 0, False: 0]
  ------------------
  448|      0|                aiNumMeshesPerPType[3], ((mConfigRemoveMeshes & aiPrimitiveType_POLYGON) ? "X" : ""));
  ------------------
  |  Branch (448:42): [True: 0, False: 0]
  ------------------
  449|      0|        ASSIMP_LOG_INFO(buffer);
  450|       |        ASSIMP_LOG_DEBUG("SortByPTypeProcess finished");
  451|      0|    }
  452|  1.22k|}
SortByPTypeProcess.cpp:_ZL17clearMeshesInNodeP6aiNode:
   69|    827|static void clearMeshesInNode(aiNode *node) {
   70|    827|    delete[] node->mMeshes;
   71|    827|    node->mNumMeshes = 0;
   72|    827|    node->mMeshes = nullptr;
   73|    827|}

_ZN6Assimp23SplitByBoneCountProcessC2Ev:
   60|  5.13k|SplitByBoneCountProcess::SplitByBoneCountProcess() : mMaxBoneCount(AI_SBBC_DEFAULT_MAX_BONES) {}
_ZNK6Assimp23SplitByBoneCountProcess8IsActiveEj:
   64|  1.50k|bool SplitByBoneCountProcess::IsActive( unsigned int pFlags) const {
   65|  1.50k|    return !!(pFlags & aiProcess_SplitByBoneCount);
   66|  1.50k|}

_ZN6Assimp23SplitByBoneCountProcessD2Ev:
   66|  5.13k|    ~SplitByBoneCountProcess() override = default;

_ZN6Assimp32SplitLargeMeshesProcess_TriangleC2Ev:
   51|  5.13k|SplitLargeMeshesProcess_Triangle::SplitLargeMeshesProcess_Triangle() {
   52|       |    LIMIT = AI_SLM_DEFAULT_MAX_TRIANGLES;
   53|  5.13k|}
_ZNK6Assimp32SplitLargeMeshesProcess_Triangle8IsActiveEj:
   57|  1.50k|bool SplitLargeMeshesProcess_Triangle::IsActive( unsigned int pFlags) const {
   58|  1.50k|    return (pFlags & aiProcess_SplitLargeMeshes) != 0;
   59|  1.50k|}
_ZN6Assimp32SplitLargeMeshesProcess_Triangle7ExecuteEP7aiScene:
   63|  1.50k|void SplitLargeMeshesProcess_Triangle::Execute( aiScene* pScene) {
   64|  1.50k|    if (0xffffffff == this->LIMIT || nullptr == pScene ) {
  ------------------
  |  Branch (64:9): [True: 0, False: 1.50k]
  |  Branch (64:38): [True: 0, False: 1.50k]
  ------------------
   65|      0|        return;
   66|      0|    }
   67|       |
   68|  1.50k|    ASSIMP_LOG_DEBUG("SplitLargeMeshesProcess_Triangle begin");
   69|  1.50k|    std::vector<std::pair<aiMesh*, unsigned int> > avList;
   70|       |
   71|  3.66k|    for( unsigned int a = 0; a < pScene->mNumMeshes; ++a) {
  ------------------
  |  Branch (71:30): [True: 2.16k, False: 1.50k]
  ------------------
   72|  2.16k|        this->SplitMesh(a, pScene->mMeshes[a],avList);
   73|  2.16k|    }
   74|       |
   75|  1.50k|    if (avList.size() == pScene->mNumMeshes) {
  ------------------
  |  Branch (75:9): [True: 1.50k, False: 0]
  ------------------
   76|  1.50k|        ASSIMP_LOG_DEBUG("SplitLargeMeshesProcess_Triangle finished. There was nothing to do");
   77|  1.50k|    }
   78|       |
   79|       |    // it seems something has been split. rebuild the mesh list
   80|  1.50k|    delete[] pScene->mMeshes;
   81|  1.50k|    pScene->mNumMeshes = (unsigned int)avList.size();
   82|  1.50k|    pScene->mMeshes = new aiMesh*[avList.size()];
   83|       |
   84|  3.66k|    for (unsigned int i = 0; i < avList.size();++i) {
  ------------------
  |  Branch (84:30): [True: 2.16k, False: 1.50k]
  ------------------
   85|  2.16k|        pScene->mMeshes[i] = avList[i].first;
   86|  2.16k|    }
   87|       |
   88|       |    // now we need to update all nodes
   89|  1.50k|    this->UpdateNode(pScene->mRootNode,avList);
   90|       |    ASSIMP_LOG_INFO("SplitLargeMeshesProcess_Triangle finished. Meshes have been split");
   91|  1.50k|}
_ZN6Assimp32SplitLargeMeshesProcess_Triangle15SetupPropertiesEPKNS_8ImporterE:
   95|  1.50k|void SplitLargeMeshesProcess_Triangle::SetupProperties( const Importer* pImp) {
   96|       |    // get the current value of the split property
   97|  1.50k|    this->LIMIT = pImp->GetPropertyInteger(AI_CONFIG_PP_SLM_TRIANGLE_LIMIT,AI_SLM_DEFAULT_MAX_TRIANGLES);
   98|  1.50k|}
_ZN6Assimp32SplitLargeMeshesProcess_Triangle10UpdateNodeEP6aiNodeRKNSt3__16vectorINS3_4pairIP6aiMeshjEENS3_9allocatorIS8_EEEE:
  102|  5.98k|void SplitLargeMeshesProcess_Triangle::UpdateNode(aiNode* pcNode, const std::vector<std::pair<aiMesh*, unsigned int> >& avList) {
  103|  5.98k|    if (pcNode == nullptr) {
  ------------------
  |  Branch (103:9): [True: 0, False: 5.98k]
  ------------------
  104|      0|        ASSIMP_LOG_WARN("UpdateNode skipped, nullptr detected.");
  105|      0|        return;
  106|      0|    }
  107|       |
  108|       |    // for every index in out list build a new entry
  109|  5.98k|    std::vector<unsigned int> aiEntries;
  110|  5.98k|    aiEntries.reserve(pcNode->mNumMeshes + 1);
  111|  8.25k|    for (unsigned int i = 0; i < pcNode->mNumMeshes;++i) {
  ------------------
  |  Branch (111:30): [True: 2.27k, False: 5.98k]
  ------------------
  112|  7.79k|        for (unsigned int a = 0; a < avList.size();++a) {
  ------------------
  |  Branch (112:34): [True: 5.52k, False: 2.27k]
  ------------------
  113|  5.52k|            if (avList[a].second == pcNode->mMeshes[i]) {
  ------------------
  |  Branch (113:17): [True: 2.27k, False: 3.25k]
  ------------------
  114|  2.27k|                aiEntries.push_back(a);
  115|  2.27k|            }
  116|  5.52k|        }
  117|  2.27k|    }
  118|       |
  119|       |    // now build the new list
  120|  5.98k|    delete[] pcNode->mMeshes;
  121|  5.98k|    pcNode->mNumMeshes = (unsigned int)aiEntries.size();
  122|  5.98k|    pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes];
  123|       |
  124|  8.25k|    for (unsigned int b = 0; b < pcNode->mNumMeshes;++b) {
  ------------------
  |  Branch (124:30): [True: 2.27k, False: 5.98k]
  ------------------
  125|  2.27k|        pcNode->mMeshes[b] = aiEntries[b];
  126|  2.27k|    }
  127|       |
  128|       |    // recursively update all other nodes
  129|  10.4k|    for (unsigned int i = 0; i < pcNode->mNumChildren;++i) {
  ------------------
  |  Branch (129:30): [True: 4.48k, False: 5.98k]
  ------------------
  130|  4.48k|        UpdateNode ( pcNode->mChildren[i], avList );
  131|  4.48k|    }
  132|  5.98k|}
_ZN6Assimp32SplitLargeMeshesProcess_Triangle9SplitMeshEjP6aiMeshRNSt3__16vectorINS3_4pairIS2_jEENS3_9allocatorIS6_EEEE:
  139|  2.16k|        std::vector<std::pair<aiMesh*, unsigned int> >& avList) {
  140|  2.16k|    if (pMesh->mNumFaces > SplitLargeMeshesProcess_Triangle::LIMIT) {
  ------------------
  |  Branch (140:9): [True: 0, False: 2.16k]
  ------------------
  141|      0|        ASSIMP_LOG_INFO("Mesh exceeds the triangle limit. It will be split ...");
  142|       |
  143|       |        // we need to split this mesh into sub meshes
  144|       |        // determine the size of a submesh
  145|      0|        const unsigned int iSubMeshes = (pMesh->mNumFaces / LIMIT) + 1;
  146|       |
  147|      0|        const unsigned int iOutFaceNum = pMesh->mNumFaces / iSubMeshes;
  148|      0|        const unsigned int iOutVertexNum = iOutFaceNum * 3;
  149|       |
  150|       |        // now generate all submeshes
  151|      0|        for (unsigned int i = 0; i < iSubMeshes;++i) {
  ------------------
  |  Branch (151:34): [True: 0, False: 0]
  ------------------
  152|      0|            aiMesh* pcMesh          = new aiMesh;
  153|      0|            pcMesh->mNumFaces       = iOutFaceNum;
  154|      0|            pcMesh->mMaterialIndex  = pMesh->mMaterialIndex;
  155|       |
  156|       |            // the name carries the adjacency information between the meshes
  157|      0|            pcMesh->mName = pMesh->mName;
  158|       |
  159|      0|            if (i == iSubMeshes-1) {
  ------------------
  |  Branch (159:17): [True: 0, False: 0]
  ------------------
  160|      0|                pcMesh->mNumFaces = iOutFaceNum + (
  161|      0|                    pMesh->mNumFaces - iOutFaceNum * iSubMeshes);
  162|      0|            }
  163|       |            // copy the list of faces
  164|      0|            pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
  165|       |
  166|      0|            const unsigned int iBase = iOutFaceNum * i;
  167|       |
  168|       |            // get the total number of indices
  169|      0|            unsigned int iCnt = 0;
  170|      0|            for (unsigned int p = iBase; p < pcMesh->mNumFaces + iBase;++p) {
  ------------------
  |  Branch (170:42): [True: 0, False: 0]
  ------------------
  171|      0|                iCnt += pMesh->mFaces[p].mNumIndices;
  172|      0|            }
  173|      0|            pcMesh->mNumVertices = iCnt;
  174|       |
  175|       |            // allocate storage
  176|      0|            if (pMesh->mVertices != nullptr) {
  ------------------
  |  Branch (176:17): [True: 0, False: 0]
  ------------------
  177|      0|                pcMesh->mVertices = new aiVector3D[iCnt];
  178|      0|            }
  179|       |
  180|      0|            if (pMesh->HasNormals()) {
  ------------------
  |  Branch (180:17): [True: 0, False: 0]
  ------------------
  181|      0|                pcMesh->mNormals = new aiVector3D[iCnt];
  182|      0|            }
  183|       |
  184|      0|            if (pMesh->HasTangentsAndBitangents()) {
  ------------------
  |  Branch (184:17): [True: 0, False: 0]
  ------------------
  185|      0|                pcMesh->mTangents = new aiVector3D[iCnt];
  186|      0|                pcMesh->mBitangents = new aiVector3D[iCnt];
  187|      0|            }
  188|       |
  189|       |            // texture coordinates
  190|      0|            for (unsigned int c = 0;  c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) {
  ------------------
  |  Branch (190:39): [True: 0, False: 0]
  ------------------
  191|      0|                pcMesh->mNumUVComponents[c] = pMesh->mNumUVComponents[c];
  192|      0|                if (pMesh->HasTextureCoords( c)) {
  ------------------
  |  Branch (192:21): [True: 0, False: 0]
  ------------------
  193|      0|                    pcMesh->mTextureCoords[c] = new aiVector3D[iCnt];
  194|      0|                }
  195|      0|            }
  196|       |
  197|       |            // vertex colors
  198|      0|            for (unsigned int c = 0;  c < AI_MAX_NUMBER_OF_COLOR_SETS;++c) {
  ------------------
  |  Branch (198:39): [True: 0, False: 0]
  ------------------
  199|      0|                if (pMesh->HasVertexColors( c)) {
  ------------------
  |  Branch (199:21): [True: 0, False: 0]
  ------------------
  200|      0|                    pcMesh->mColors[c] = new aiColor4D[iCnt];
  201|      0|                }
  202|      0|            }
  203|       |
  204|      0|            if (pMesh->HasBones()) {
  ------------------
  |  Branch (204:17): [True: 0, False: 0]
  ------------------
  205|       |                // assume the number of bones won't change in most cases
  206|      0|                pcMesh->mBones = new aiBone*[pMesh->mNumBones];
  207|       |
  208|       |                // iterate through all bones of the mesh and find those which
  209|       |                // need to be copied to the split mesh
  210|      0|                std::vector<aiVertexWeight> avTempWeights;
  211|      0|                for (unsigned int p = 0; p < pcMesh->mNumBones;++p) {
  ------------------
  |  Branch (211:42): [True: 0, False: 0]
  ------------------
  212|      0|                    aiBone* const bone = pcMesh->mBones[p];
  213|      0|                    avTempWeights.clear();
  214|      0|                    avTempWeights.reserve(bone->mNumWeights / iSubMeshes);
  215|       |
  216|      0|                    for (unsigned int q = 0; q < bone->mNumWeights;++q) {
  ------------------
  |  Branch (216:46): [True: 0, False: 0]
  ------------------
  217|      0|                        aiVertexWeight& weight = bone->mWeights[q];
  218|      0|                        if(weight.mVertexId >= iBase && weight.mVertexId < iBase + iOutVertexNum) {
  ------------------
  |  Branch (218:28): [True: 0, False: 0]
  |  Branch (218:57): [True: 0, False: 0]
  ------------------
  219|      0|                            avTempWeights.push_back(weight);
  220|      0|                            weight = avTempWeights.back();
  221|      0|                            weight.mVertexId -= iBase;
  222|      0|                        }
  223|      0|                    }
  224|       |
  225|      0|                    if (!avTempWeights.empty()) {
  ------------------
  |  Branch (225:25): [True: 0, False: 0]
  ------------------
  226|       |                        // we'll need this bone. Copy it ...
  227|      0|                        aiBone* pc = new aiBone();
  228|      0|                        pcMesh->mBones[pcMesh->mNumBones++] = pc;
  229|      0|                        pc->mName = aiString(bone->mName);
  230|      0|                        pc->mNumWeights = (unsigned int)avTempWeights.size();
  231|      0|                        pc->mOffsetMatrix = bone->mOffsetMatrix;
  232|       |
  233|       |                        // no need to reallocate the array for the last submesh.
  234|       |                        // Here we can reuse the (large) source array, although
  235|       |                        // we'll waste some memory
  236|      0|                        if (iSubMeshes-1 == i) {
  ------------------
  |  Branch (236:29): [True: 0, False: 0]
  ------------------
  237|      0|                            pc->mWeights = bone->mWeights;
  238|      0|                            bone->mWeights = nullptr;
  239|      0|                        } else {
  240|      0|                            pc->mWeights = new aiVertexWeight[pc->mNumWeights];
  241|      0|                        }
  242|       |
  243|       |                        // copy the weights
  244|      0|                        ::memcpy(pc->mWeights,&avTempWeights[0],sizeof(aiVertexWeight)*pc->mNumWeights);
  245|      0|                    }
  246|      0|                }
  247|      0|            }
  248|       |
  249|       |            // (we will also need to copy the array of indices)
  250|      0|            unsigned int iCurrent = 0;
  251|      0|            for (unsigned int p = 0; p < pcMesh->mNumFaces;++p) {
  ------------------
  |  Branch (251:38): [True: 0, False: 0]
  ------------------
  252|      0|                pcMesh->mFaces[p].mNumIndices = 3;
  253|       |                // allocate a new array
  254|      0|                const unsigned int iTemp = p + iBase;
  255|      0|                const unsigned int iNumIndices = pMesh->mFaces[iTemp].mNumIndices;
  256|       |
  257|       |                // setup face type and number of indices
  258|      0|                pcMesh->mFaces[p].mNumIndices = iNumIndices;
  259|      0|                unsigned int* pi = pMesh->mFaces[iTemp].mIndices;
  260|      0|                unsigned int* piOut = pcMesh->mFaces[p].mIndices = new unsigned int[iNumIndices];
  261|       |
  262|       |                // need to update the output primitive types
  263|      0|                switch (iNumIndices) {
  264|      0|                case 1:
  ------------------
  |  Branch (264:17): [True: 0, False: 0]
  ------------------
  265|      0|                    pcMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
  266|      0|                    break;
  267|      0|                case 2:
  ------------------
  |  Branch (267:17): [True: 0, False: 0]
  ------------------
  268|      0|                    pcMesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
  269|      0|                    break;
  270|      0|                case 3:
  ------------------
  |  Branch (270:17): [True: 0, False: 0]
  ------------------
  271|      0|                    pcMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
  272|      0|                    break;
  273|      0|                default:
  ------------------
  |  Branch (273:17): [True: 0, False: 0]
  ------------------
  274|      0|                    pcMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
  275|      0|                }
  276|       |
  277|       |                // and copy the contents of the old array, offset by current base
  278|      0|                for (unsigned int v = 0; v < iNumIndices;++v) {
  ------------------
  |  Branch (278:42): [True: 0, False: 0]
  ------------------
  279|      0|                    unsigned int iIndex = pi[v];
  280|      0|                    unsigned int iIndexOut = iCurrent++;
  281|      0|                    piOut[v] = iIndexOut;
  282|       |
  283|       |                    // copy positions
  284|      0|                    if (pMesh->mVertices != nullptr) {
  ------------------
  |  Branch (284:25): [True: 0, False: 0]
  ------------------
  285|      0|                        pcMesh->mVertices[iIndexOut] = pMesh->mVertices[iIndex];
  286|      0|                    }
  287|       |
  288|       |                    // copy normals
  289|      0|                    if (pMesh->HasNormals()) {
  ------------------
  |  Branch (289:25): [True: 0, False: 0]
  ------------------
  290|      0|                        pcMesh->mNormals[iIndexOut] = pMesh->mNormals[iIndex];
  291|      0|                    }
  292|       |
  293|       |                    // copy tangents/bitangents
  294|      0|                    if (pMesh->HasTangentsAndBitangents()) {
  ------------------
  |  Branch (294:25): [True: 0, False: 0]
  ------------------
  295|      0|                        pcMesh->mTangents[iIndexOut] = pMesh->mTangents[iIndex];
  296|      0|                        pcMesh->mBitangents[iIndexOut] = pMesh->mBitangents[iIndex];
  297|      0|                    }
  298|       |
  299|       |                    // texture coordinates
  300|      0|                    for (unsigned int c = 0;  c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) {
  ------------------
  |  Branch (300:47): [True: 0, False: 0]
  ------------------
  301|      0|                        if (pMesh->HasTextureCoords( c ) ) {
  ------------------
  |  Branch (301:29): [True: 0, False: 0]
  ------------------
  302|      0|                            pcMesh->mTextureCoords[c][iIndexOut] = pMesh->mTextureCoords[c][iIndex];
  303|      0|                        }
  304|      0|                    }
  305|       |                    // vertex colors
  306|      0|                    for (unsigned int c = 0;  c < AI_MAX_NUMBER_OF_COLOR_SETS;++c) {
  ------------------
  |  Branch (306:47): [True: 0, False: 0]
  ------------------
  307|      0|                        if (pMesh->HasVertexColors( c)) {
  ------------------
  |  Branch (307:29): [True: 0, False: 0]
  ------------------
  308|      0|                            pcMesh->mColors[c][iIndexOut] = pMesh->mColors[c][iIndex];
  309|      0|                        }
  310|      0|                    }
  311|      0|                }
  312|      0|            }
  313|       |
  314|       |            // add the newly created mesh to the list
  315|      0|            avList.emplace_back(pcMesh,a);
  316|      0|        }
  317|       |
  318|       |        // now delete the old mesh data
  319|      0|        delete pMesh;
  320|  2.16k|    } else {
  321|  2.16k|        avList.emplace_back(pMesh,a);
  322|  2.16k|    }
  323|  2.16k|}
_ZN6Assimp30SplitLargeMeshesProcess_VertexC2Ev:
  326|  5.13k|SplitLargeMeshesProcess_Vertex::SplitLargeMeshesProcess_Vertex() {
  327|       |    LIMIT = AI_SLM_DEFAULT_MAX_VERTICES;
  328|  5.13k|}
_ZNK6Assimp30SplitLargeMeshesProcess_Vertex8IsActiveEj:
  332|  1.50k|bool SplitLargeMeshesProcess_Vertex::IsActive( unsigned int pFlags) const {
  333|  1.50k|    return (pFlags & aiProcess_SplitLargeMeshes) != 0;
  334|  1.50k|}
_ZN6Assimp30SplitLargeMeshesProcess_Vertex7ExecuteEP7aiScene:
  338|  1.50k|void SplitLargeMeshesProcess_Vertex::Execute( aiScene* pScene) {
  339|  1.50k|    if (0xffffffff == this->LIMIT || nullptr == pScene ) {
  ------------------
  |  Branch (339:9): [True: 0, False: 1.50k]
  |  Branch (339:38): [True: 0, False: 1.50k]
  ------------------
  340|      0|        return;
  341|      0|    }
  342|       |
  343|  1.50k|    ASSIMP_LOG_DEBUG("SplitLargeMeshesProcess_Vertex begin");
  344|       |
  345|  1.50k|    std::vector<std::pair<aiMesh*, unsigned int> > avList;
  346|       |
  347|       |    //Check for point cloud first,
  348|       |    //Do not process point cloud, splitMesh works only with faces data
  349|  2.86k|    for (unsigned int a = 0; a < pScene->mNumMeshes; a++) {
  ------------------
  |  Branch (349:30): [True: 1.76k, False: 1.09k]
  ------------------
  350|  1.76k|        if ( pScene->mMeshes[a]->mPrimitiveTypes == aiPrimitiveType_POINT ) {
  ------------------
  |  Branch (350:14): [True: 408, False: 1.36k]
  ------------------
  351|    408|            return;
  352|    408|        }
  353|  1.76k|    }
  354|       |
  355|  2.45k|    for( unsigned int a = 0; a < pScene->mNumMeshes; ++a ) {
  ------------------
  |  Branch (355:30): [True: 1.35k, False: 1.09k]
  ------------------
  356|  1.35k|        this->SplitMesh(a, pScene->mMeshes[a], avList);
  357|  1.35k|    }
  358|       |
  359|  1.09k|    if (avList.size() != pScene->mNumMeshes) {
  ------------------
  |  Branch (359:9): [True: 0, False: 1.09k]
  ------------------
  360|       |        // it seems something has been split. rebuild the mesh list
  361|      0|        delete[] pScene->mMeshes;
  362|      0|        pScene->mNumMeshes = (unsigned int)avList.size();
  363|      0|        pScene->mMeshes = new aiMesh*[avList.size()];
  364|       |
  365|      0|        for (unsigned int i = 0; i < avList.size();++i) {
  ------------------
  |  Branch (365:34): [True: 0, False: 0]
  ------------------
  366|      0|            pScene->mMeshes[i] = avList[i].first;
  367|      0|        }
  368|       |
  369|       |        // now we need to update all nodes
  370|      0|        SplitLargeMeshesProcess_Triangle::UpdateNode(pScene->mRootNode,avList);
  371|      0|        ASSIMP_LOG_INFO("SplitLargeMeshesProcess_Vertex finished. Meshes have been split");
  372|  1.09k|    } else {
  373|       |        ASSIMP_LOG_DEBUG("SplitLargeMeshesProcess_Vertex finished. There was nothing to do");
  374|  1.09k|    }
  375|  1.09k|}
_ZN6Assimp30SplitLargeMeshesProcess_Vertex15SetupPropertiesEPKNS_8ImporterE:
  379|  1.50k|void SplitLargeMeshesProcess_Vertex::SetupProperties( const Importer* pImp) {
  380|  1.50k|    this->LIMIT = pImp->GetPropertyInteger(AI_CONFIG_PP_SLM_VERTEX_LIMIT,AI_SLM_DEFAULT_MAX_VERTICES);
  381|  1.50k|}
_ZN6Assimp30SplitLargeMeshesProcess_Vertex9SplitMeshEjP6aiMeshRNSt3__16vectorINS3_4pairIS2_jEENS3_9allocatorIS6_EEEE:
  388|  1.35k|        std::vector<std::pair<aiMesh*, unsigned int> >& avList) {
  389|  1.35k|    if (pMesh->mNumVertices > SplitLargeMeshesProcess_Vertex::LIMIT) {
  ------------------
  |  Branch (389:9): [True: 0, False: 1.35k]
  ------------------
  390|      0|        typedef std::vector< std::pair<unsigned int,float> > VertexWeightTable;
  391|       |
  392|       |        // build a per-vertex weight list if necessary
  393|      0|        VertexWeightTable* avPerVertexWeights = ComputeVertexBoneWeightTable(pMesh);
  394|       |
  395|       |        // we need to split this mesh into sub meshes
  396|       |        // determine the estimated size of a submesh
  397|       |        // (this could be too large. Max waste is a single digit percentage)
  398|      0|        const unsigned int iSubMeshes = (pMesh->mNumVertices / SplitLargeMeshesProcess_Vertex::LIMIT) + 1;
  399|       |
  400|       |        // create a std::vector<unsigned int> to indicate which vertices
  401|       |        // have already been copied
  402|      0|        std::vector<unsigned int> avWasCopied;
  403|      0|        avWasCopied.resize(pMesh->mNumVertices,0xFFFFFFFF);
  404|       |
  405|       |        // try to find a good estimate for the number of output faces
  406|       |        // per mesh. Add 12.5% as buffer
  407|      0|        unsigned int iEstimatedSize = pMesh->mNumFaces / iSubMeshes;
  408|      0|        iEstimatedSize += iEstimatedSize >> 3;
  409|       |
  410|       |        // now generate all submeshes
  411|      0|        unsigned int iBase( 0 );
  412|      0|        while (true) {
  ------------------
  |  Branch (412:16): [True: 0, Folded]
  ------------------
  413|      0|            const unsigned int iOutVertexNum = SplitLargeMeshesProcess_Vertex::LIMIT;
  414|      0|            aiMesh* pcMesh          = new aiMesh;
  415|      0|            pcMesh->mNumVertices    = 0;
  416|      0|            pcMesh->mMaterialIndex  = pMesh->mMaterialIndex;
  417|       |
  418|       |            // the name carries the adjacency information between the meshes
  419|      0|            pcMesh->mName = pMesh->mName;
  420|       |
  421|      0|            typedef std::vector<aiVertexWeight> BoneWeightList;
  422|      0|            if (pMesh->HasBones()) {
  ------------------
  |  Branch (422:17): [True: 0, False: 0]
  ------------------
  423|      0|                pcMesh->mBones = new aiBone*[pMesh->mNumBones];
  424|      0|                ::memset(pcMesh->mBones,0,sizeof(void*)*pMesh->mNumBones);
  425|      0|            }
  426|       |
  427|       |            // clear the temporary helper array
  428|      0|            if (iBase) {
  ------------------
  |  Branch (428:17): [True: 0, False: 0]
  ------------------
  429|       |                // we can't use memset here we unsigned int needn' be 32 bits
  430|      0|                for (auto &elem : avWasCopied) {
  ------------------
  |  Branch (430:33): [True: 0, False: 0]
  ------------------
  431|      0|                    elem = 0xffffffff;
  432|      0|                }
  433|      0|            }
  434|       |
  435|       |            // output vectors
  436|      0|            std::vector<aiFace> vFaces;
  437|       |
  438|       |            // reserve enough storage for most cases
  439|      0|            if (pMesh->HasPositions()) {
  ------------------
  |  Branch (439:17): [True: 0, False: 0]
  ------------------
  440|      0|                pcMesh->mVertices = new aiVector3D[iOutVertexNum];
  441|      0|            }
  442|      0|            if (pMesh->HasNormals()) {
  ------------------
  |  Branch (442:17): [True: 0, False: 0]
  ------------------
  443|      0|                pcMesh->mNormals = new aiVector3D[iOutVertexNum];
  444|      0|            }
  445|      0|            if (pMesh->HasTangentsAndBitangents()) {
  ------------------
  |  Branch (445:17): [True: 0, False: 0]
  ------------------
  446|      0|                pcMesh->mTangents = new aiVector3D[iOutVertexNum];
  447|      0|                pcMesh->mBitangents = new aiVector3D[iOutVertexNum];
  448|      0|            }
  449|      0|            for (unsigned int c = 0; pMesh->HasVertexColors(c);++c) {
  ------------------
  |  Branch (449:38): [True: 0, False: 0]
  ------------------
  450|      0|                pcMesh->mColors[c] = new aiColor4D[iOutVertexNum];
  451|      0|            }
  452|      0|            for (unsigned int c = 0; pMesh->HasTextureCoords(c);++c) {
  ------------------
  |  Branch (452:38): [True: 0, False: 0]
  ------------------
  453|      0|                pcMesh->mNumUVComponents[c] = pMesh->mNumUVComponents[c];
  454|      0|                pcMesh->mTextureCoords[c] = new aiVector3D[iOutVertexNum];
  455|      0|            }
  456|      0|            vFaces.reserve(iEstimatedSize);
  457|       |
  458|       |            // (we will also need to copy the array of indices)
  459|      0|            while (iBase < pMesh->mNumFaces) {
  ------------------
  |  Branch (459:20): [True: 0, False: 0]
  ------------------
  460|       |                // allocate a new array
  461|      0|                const unsigned int iNumIndices = pMesh->mFaces[iBase].mNumIndices;
  462|       |
  463|       |                // doesn't catch degenerates but is quite fast
  464|      0|                unsigned int iNeed = 0;
  465|      0|                for (unsigned int v = 0; v < iNumIndices;++v) {
  ------------------
  |  Branch (465:42): [True: 0, False: 0]
  ------------------
  466|      0|                    unsigned int iIndex = pMesh->mFaces[iBase].mIndices[v];
  467|       |
  468|       |                    // check whether we do already have this vertex
  469|      0|                    if (0xFFFFFFFF == avWasCopied[iIndex]) {
  ------------------
  |  Branch (469:25): [True: 0, False: 0]
  ------------------
  470|      0|                        iNeed++;
  471|      0|                    }
  472|      0|                }
  473|      0|                if (pcMesh->mNumVertices + iNeed > iOutVertexNum) {
  ------------------
  |  Branch (473:21): [True: 0, False: 0]
  ------------------
  474|       |                    // don't use this face
  475|      0|                    break;
  476|      0|                }
  477|       |
  478|      0|                vFaces.emplace_back();
  479|      0|                aiFace& rFace = vFaces.back();
  480|       |
  481|       |                // setup face type and number of indices
  482|      0|                rFace.mNumIndices = iNumIndices;
  483|      0|                rFace.mIndices = new unsigned int[iNumIndices];
  484|       |
  485|       |                // need to update the output primitive types
  486|      0|                switch (rFace.mNumIndices) {
  487|      0|                case 1:
  ------------------
  |  Branch (487:17): [True: 0, False: 0]
  ------------------
  488|      0|                    pcMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
  489|      0|                    break;
  490|      0|                case 2:
  ------------------
  |  Branch (490:17): [True: 0, False: 0]
  ------------------
  491|      0|                    pcMesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
  492|      0|                    break;
  493|      0|                case 3:
  ------------------
  |  Branch (493:17): [True: 0, False: 0]
  ------------------
  494|      0|                    pcMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
  495|      0|                    break;
  496|      0|                default:
  ------------------
  |  Branch (496:17): [True: 0, False: 0]
  ------------------
  497|      0|                    pcMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
  498|      0|                }
  499|       |
  500|       |                // and copy the contents of the old array, offset by current base
  501|      0|                for (unsigned int v = 0; v < iNumIndices;++v) {
  ------------------
  |  Branch (501:42): [True: 0, False: 0]
  ------------------
  502|      0|                    unsigned int iIndex = pMesh->mFaces[iBase].mIndices[v];
  503|       |
  504|       |                    // check whether we do already have this vertex
  505|      0|                    if (0xFFFFFFFF != avWasCopied[iIndex]) {
  ------------------
  |  Branch (505:25): [True: 0, False: 0]
  ------------------
  506|      0|                        rFace.mIndices[v] = avWasCopied[iIndex];
  507|      0|                        continue;
  508|      0|                    }
  509|       |
  510|       |                    // copy positions
  511|      0|                    pcMesh->mVertices[pcMesh->mNumVertices] = (pMesh->mVertices[iIndex]);
  512|       |
  513|       |                    // copy normals
  514|      0|                    if (pMesh->HasNormals()) {
  ------------------
  |  Branch (514:25): [True: 0, False: 0]
  ------------------
  515|      0|                        pcMesh->mNormals[pcMesh->mNumVertices] = (pMesh->mNormals[iIndex]);
  516|      0|                    }
  517|       |
  518|       |                    // copy tangents/bitangents
  519|      0|                    if (pMesh->HasTangentsAndBitangents()) {
  ------------------
  |  Branch (519:25): [True: 0, False: 0]
  ------------------
  520|      0|                        pcMesh->mTangents[pcMesh->mNumVertices] = (pMesh->mTangents[iIndex]);
  521|      0|                        pcMesh->mBitangents[pcMesh->mNumVertices] = (pMesh->mBitangents[iIndex]);
  522|      0|                    }
  523|       |
  524|       |                    // texture coordinates
  525|      0|                    for (unsigned int c = 0;  c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) {
  ------------------
  |  Branch (525:47): [True: 0, False: 0]
  ------------------
  526|      0|                        if (pMesh->HasTextureCoords( c)) {
  ------------------
  |  Branch (526:29): [True: 0, False: 0]
  ------------------
  527|      0|                            pcMesh->mTextureCoords[c][pcMesh->mNumVertices] = pMesh->mTextureCoords[c][iIndex];
  528|      0|                        }
  529|      0|                    }
  530|       |                    // vertex colors
  531|      0|                    for (unsigned int c = 0;  c < AI_MAX_NUMBER_OF_COLOR_SETS;++c) {
  ------------------
  |  Branch (531:47): [True: 0, False: 0]
  ------------------
  532|      0|                        if (pMesh->HasVertexColors( c)) {
  ------------------
  |  Branch (532:29): [True: 0, False: 0]
  ------------------
  533|      0|                            pcMesh->mColors[c][pcMesh->mNumVertices] = pMesh->mColors[c][iIndex];
  534|      0|                        }
  535|      0|                    }
  536|       |                    // check whether we have bone weights assigned to this vertex
  537|      0|                    rFace.mIndices[v] = pcMesh->mNumVertices;
  538|      0|                    if (avPerVertexWeights) {
  ------------------
  |  Branch (538:25): [True: 0, False: 0]
  ------------------
  539|      0|                        VertexWeightTable& table = avPerVertexWeights[ pcMesh->mNumVertices ];
  540|      0|                        if( !table.empty() ) {
  ------------------
  |  Branch (540:29): [True: 0, False: 0]
  ------------------
  541|      0|                            for (VertexWeightTable::const_iterator iter =  table.begin();
  542|      0|                                    iter != table.end();++iter) {
  ------------------
  |  Branch (542:37): [True: 0, False: 0]
  ------------------
  543|       |                                // allocate the bone weight array if necessary
  544|      0|                                BoneWeightList* pcWeightList = (BoneWeightList*)pcMesh->mBones[(*iter).first];
  545|      0|                                if (nullptr == pcWeightList) {
  ------------------
  |  Branch (545:37): [True: 0, False: 0]
  ------------------
  546|      0|                                    pcMesh->mBones[(*iter).first] = (aiBone*)(pcWeightList = new BoneWeightList());
  547|      0|                                }
  548|      0|                                pcWeightList->push_back(aiVertexWeight(pcMesh->mNumVertices,(*iter).second));
  549|      0|                            }
  550|      0|                        }
  551|      0|                    }
  552|       |
  553|      0|                    avWasCopied[iIndex] = pcMesh->mNumVertices;
  554|      0|                    pcMesh->mNumVertices++;
  555|      0|                }
  556|      0|                ++iBase;
  557|      0|                if(pcMesh->mNumVertices == iOutVertexNum) {
  ------------------
  |  Branch (557:20): [True: 0, False: 0]
  ------------------
  558|       |                    // break here. The face is only added if it was complete
  559|      0|                    break;
  560|      0|                }
  561|      0|            }
  562|       |
  563|       |            // check which bones we'll need to create for this submesh
  564|      0|            if (pMesh->HasBones()) {
  ------------------
  |  Branch (564:17): [True: 0, False: 0]
  ------------------
  565|      0|                aiBone** ppCurrent = pcMesh->mBones;
  566|      0|                for (unsigned int k = 0; k < pMesh->mNumBones;++k) {
  ------------------
  |  Branch (566:42): [True: 0, False: 0]
  ------------------
  567|       |                    // check whether the bone is existing
  568|      0|                    BoneWeightList* pcWeightList;
  569|      0|                    pcWeightList = (BoneWeightList *)pcMesh->mBones[k];
  570|      0|                    if (nullptr != pcWeightList) {
  ------------------
  |  Branch (570:25): [True: 0, False: 0]
  ------------------
  571|      0|                        aiBone *pcOldBone = pMesh->mBones[k];
  572|      0|                        aiBone* pcOut( nullptr );
  573|      0|                        *ppCurrent++ = pcOut = new aiBone();
  574|      0|                        pcOut->mName = aiString(pcOldBone->mName);
  575|      0|                        pcOut->mOffsetMatrix = pcOldBone->mOffsetMatrix;
  576|      0|                        pcOut->mNumWeights = (unsigned int)pcWeightList->size();
  577|      0|                        pcOut->mWeights = new aiVertexWeight[pcOut->mNumWeights];
  578|       |
  579|       |                        // copy the vertex weights
  580|      0|                        ::memcpy(pcOut->mWeights,&pcWeightList->operator[](0),
  581|      0|                            pcOut->mNumWeights * sizeof(aiVertexWeight));
  582|       |
  583|       |                        // delete the temporary bone weight list
  584|      0|                        delete pcWeightList;
  585|      0|                        pcMesh->mNumBones++;
  586|      0|                    }
  587|      0|                }
  588|      0|            }
  589|       |
  590|       |            // copy the face list to the mesh
  591|      0|            pcMesh->mFaces = new aiFace[vFaces.size()];
  592|      0|            pcMesh->mNumFaces = (unsigned int)vFaces.size();
  593|       |
  594|      0|            for (unsigned int p = 0; p < pcMesh->mNumFaces;++p) {
  ------------------
  |  Branch (594:38): [True: 0, False: 0]
  ------------------
  595|      0|                pcMesh->mFaces[p] = vFaces[p];
  596|      0|            }
  597|       |
  598|       |            // add the newly created mesh to the list
  599|      0|            avList.emplace_back(pcMesh,a);
  600|       |
  601|      0|            if (iBase == pMesh->mNumFaces) {
  ------------------
  |  Branch (601:17): [True: 0, False: 0]
  ------------------
  602|       |                // have all faces ... finish the outer loop, too
  603|      0|                break;
  604|      0|            }
  605|      0|        }
  606|       |
  607|       |        // delete the per-vertex weight list again
  608|      0|        delete[] avPerVertexWeights;
  609|       |
  610|       |        // now delete the old mesh data
  611|      0|        delete pMesh;
  612|      0|        return;
  613|      0|    }
  614|  1.35k|    avList.emplace_back(pMesh,a);
  615|  1.35k|}

_ZNK6Assimp20TextureTransformStep8IsActiveEj:
   54|  1.54k|bool TextureTransformStep::IsActive( unsigned int pFlags) const {
   55|  1.54k|    return  (pFlags & aiProcess_TransformUVCoords) != 0;
   56|  1.54k|}

_ZN6Assimp20TextureTransformStepC2Ev:
  172|  5.13k|    TextureTransformStep() = default;

_ZNK6Assimp18TriangulateProcess8IsActiveEj:
  179|  1.54k|bool TriangulateProcess::IsActive( unsigned int pFlags) const {
  180|  1.54k|    return (pFlags & aiProcess_Triangulate) != 0;
  181|  1.54k|}
_ZN6Assimp18TriangulateProcess7ExecuteEP7aiScene:
  185|  1.54k|void TriangulateProcess::Execute( aiScene* pScene) {
  186|  1.54k|    ASSIMP_LOG_DEBUG("TriangulateProcess begin");
  187|       |
  188|  1.54k|    bool bHas = false;
  189|  2.98k|    for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
  ------------------
  |  Branch (189:30): [True: 1.43k, False: 1.54k]
  ------------------
  190|  1.43k|    {
  191|  1.43k|        if (pScene->mMeshes[ a ]) {
  ------------------
  |  Branch (191:13): [True: 1.43k, False: 0]
  ------------------
  192|  1.43k|            if ( TriangulateMesh( pScene->mMeshes[ a ] ) ) {
  ------------------
  |  Branch (192:18): [True: 0, False: 1.43k]
  ------------------
  193|      0|                bHas = true;
  194|      0|            }
  195|  1.43k|        }
  196|  1.43k|    }
  197|  1.54k|    if ( bHas ) {
  ------------------
  |  Branch (197:10): [True: 0, False: 1.54k]
  ------------------
  198|      0|        ASSIMP_LOG_INFO( "TriangulateProcess finished. All polygons have been triangulated." );
  199|  1.54k|    } else {
  200|       |        ASSIMP_LOG_DEBUG( "TriangulateProcess finished. There was nothing to be done." );
  201|  1.54k|    }
  202|  1.54k|}
_ZN6Assimp18TriangulateProcess15TriangulateMeshEP6aiMesh:
  206|  1.43k|bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) {
  207|       |    // Now we have aiMesh::mPrimitiveTypes, so this is only here for test cases
  208|  1.43k|    if (!pMesh->mPrimitiveTypes)    {
  ------------------
  |  Branch (208:9): [True: 0, False: 1.43k]
  ------------------
  209|      0|        bool bNeed = false;
  210|       |
  211|      0|        for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
  ------------------
  |  Branch (211:34): [True: 0, False: 0]
  ------------------
  212|      0|            const aiFace& face = pMesh->mFaces[a];
  213|      0|            if( face.mNumIndices != 3)  {
  ------------------
  |  Branch (213:17): [True: 0, False: 0]
  ------------------
  214|      0|                bNeed = true;
  215|      0|            }
  216|      0|        }
  217|      0|        if (!bNeed) {
  ------------------
  |  Branch (217:13): [True: 0, False: 0]
  ------------------
  218|      0|            return false;
  219|      0|        }
  220|      0|    }
  221|  1.43k|    else if (!(pMesh->mPrimitiveTypes & aiPrimitiveType_POLYGON)) {
  ------------------
  |  Branch (221:14): [True: 1.43k, False: 0]
  ------------------
  222|  1.43k|        return false;
  223|  1.43k|    }
  224|       |
  225|       |    // Find out how many output faces we'll get
  226|      0|    uint32_t numOut = 0, max_out = 0;
  227|      0|    bool get_normals = true;
  228|      0|    for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
  ------------------
  |  Branch (228:30): [True: 0, False: 0]
  ------------------
  229|      0|        aiFace& face = pMesh->mFaces[a];
  230|      0|        if (face.mNumIndices <= 4) {
  ------------------
  |  Branch (230:13): [True: 0, False: 0]
  ------------------
  231|      0|            get_normals = false;
  232|      0|        }
  233|      0|        if( face.mNumIndices <= 3) {
  ------------------
  |  Branch (233:13): [True: 0, False: 0]
  ------------------
  234|      0|            ++numOut;
  235|      0|        } else {
  236|      0|            numOut += face.mNumIndices-2;
  237|      0|            max_out = std::max<uint32_t>(max_out,face.mNumIndices);
  238|      0|        }
  239|      0|    }
  240|       |
  241|       |    // Just another check whether aiMesh::mPrimitiveTypes is correct
  242|      0|    if (numOut == pMesh->mNumFaces) {
  ------------------
  |  Branch (242:9): [True: 0, False: 0]
  ------------------
  243|      0|        ASSIMP_LOG_ERROR( "Invalidation detected in the number of indices: does not fit to the primitive type." );
  244|      0|        return false;
  245|      0|    }
  246|       |
  247|      0|    aiVector3D *nor_out = nullptr;
  248|       |
  249|       |    // if we don't have normals yet, but expect them to be a cheap side
  250|       |    // product of triangulation anyway, allocate storage for them.
  251|      0|    if (!pMesh->mNormals && get_normals) {
  ------------------
  |  Branch (251:9): [True: 0, False: 0]
  |  Branch (251:29): [True: 0, False: 0]
  ------------------
  252|       |        // XXX need a mechanism to inform the GenVertexNormals process to treat these normals as preprocessed per-face normals
  253|       |    //  nor_out = pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
  254|      0|    }
  255|       |
  256|       |    // the output mesh will contain triangles, but no polys anymore
  257|      0|    pMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
  258|      0|    pMesh->mPrimitiveTypes &= ~aiPrimitiveType_POLYGON;
  259|       |
  260|       |    // The mesh becomes NGON encoded now, during the triangulation process.
  261|      0|    pMesh->mPrimitiveTypes |= aiPrimitiveType_NGONEncodingFlag;
  262|       |
  263|      0|    aiFace* out = new aiFace[numOut](), *curOut = out;
  264|      0|    std::vector<aiVector3D> temp_verts3d(max_out+2); /* temporary storage for vertices */
  265|      0|    std::vector<std::vector<aiVector2D>> temp_poly(1); /* temporary storage for earcut.hpp */
  266|      0|    std::vector<aiVector2D>& temp_verts = temp_poly[0];
  267|      0|    temp_verts.reserve(max_out + 2);
  268|       |
  269|      0|    NGONEncoder ngonEncoder;
  270|       |
  271|       |    // Apply vertex colors to represent the face winding?
  272|       |#ifdef AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING
  273|       |    if (!pMesh->mColors[0])
  274|       |        pMesh->mColors[0] = new aiColor4D[pMesh->mNumVertices];
  275|       |    else
  276|       |        new(pMesh->mColors[0]) aiColor4D[pMesh->mNumVertices];
  277|       |
  278|       |    aiColor4D* clr = pMesh->mColors[0];
  279|       |#endif
  280|       |
  281|       |#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
  282|       |    FILE* fout = fopen(POLY_OUTPUT_FILE,"a");
  283|       |#endif
  284|       |
  285|      0|    const aiVector3D* verts = pMesh->mVertices;
  286|       |
  287|      0|    for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
  ------------------
  |  Branch (287:30): [True: 0, False: 0]
  ------------------
  288|      0|        aiFace& face = pMesh->mFaces[a];
  289|       |
  290|      0|        unsigned int* idx = face.mIndices;
  291|      0|        unsigned int num = face.mNumIndices;
  292|       |
  293|       |        // Apply vertex colors to represent the face winding?
  294|       |#ifdef AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING
  295|       |        for (unsigned int i = 0; i < face.mNumIndices; ++i) {
  296|       |            aiColor4D& c = clr[idx[i]];
  297|       |            c.r = (i+1) / (float)max;
  298|       |            c.b = 1.f - c.r;
  299|       |        }
  300|       |#endif
  301|       |
  302|      0|        aiFace* const last_face = curOut;
  303|       |
  304|       |        // if it's a simple point,line or triangle: just copy it
  305|      0|        if( face.mNumIndices <= 3)
  ------------------
  |  Branch (305:13): [True: 0, False: 0]
  ------------------
  306|      0|        {
  307|      0|            aiFace& nface = *curOut++;
  308|      0|            nface.mNumIndices = face.mNumIndices;
  309|      0|            nface.mIndices    = face.mIndices;
  310|      0|            face.mIndices = nullptr;
  311|       |
  312|       |            // points and lines don't require ngon encoding (and are not supported either!)
  313|      0|            if (nface.mNumIndices == 3) ngonEncoder.ngonEncodeTriangle(&nface);
  ------------------
  |  Branch (313:17): [True: 0, False: 0]
  ------------------
  314|       |
  315|      0|            continue;
  316|      0|        }
  317|       |        // optimized code for quadrilaterals
  318|      0|        else if ( face.mNumIndices == 4) {
  ------------------
  |  Branch (318:19): [True: 0, False: 0]
  ------------------
  319|       |
  320|       |            // quads can have at maximum one concave vertex. Determine
  321|       |            // this vertex (if it exists) and start tri-fanning from
  322|       |            // it.
  323|      0|            unsigned int start_vertex = 0;
  324|      0|            for (unsigned int i = 0; i < 4; ++i) {
  ------------------
  |  Branch (324:38): [True: 0, False: 0]
  ------------------
  325|      0|                const aiVector3D& v0 = verts[face.mIndices[(i+3) % 4]];
  326|      0|                const aiVector3D& v1 = verts[face.mIndices[(i+2) % 4]];
  327|      0|                const aiVector3D& v2 = verts[face.mIndices[(i+1) % 4]];
  328|       |
  329|      0|                const aiVector3D& v = verts[face.mIndices[i]];
  330|       |
  331|      0|                aiVector3D left = (v0-v);
  332|      0|                aiVector3D diag = (v1-v);
  333|      0|                aiVector3D right = (v2-v);
  334|       |
  335|      0|                left.Normalize();
  336|      0|                diag.Normalize();
  337|      0|                right.Normalize();
  338|       |
  339|      0|                const float angle = std::acos(left*diag) + std::acos(right*diag);
  340|      0|                if (angle > AI_MATH_PI_F) {
  ------------------
  |  Branch (340:21): [True: 0, False: 0]
  ------------------
  341|       |                    // this is the concave point
  342|      0|                    start_vertex = i;
  343|      0|                    break;
  344|      0|                }
  345|      0|            }
  346|       |
  347|      0|            const unsigned int temp[] = {face.mIndices[0], face.mIndices[1], face.mIndices[2], face.mIndices[3]};
  348|       |
  349|      0|            aiFace& nface = *curOut++;
  350|      0|            nface.mNumIndices = 3;
  351|      0|            nface.mIndices = face.mIndices;
  352|       |
  353|      0|            nface.mIndices[0] = temp[start_vertex];
  354|      0|            nface.mIndices[1] = temp[(start_vertex + 1) % 4];
  355|      0|            nface.mIndices[2] = temp[(start_vertex + 2) % 4];
  356|       |
  357|      0|            aiFace& sface = *curOut++;
  358|      0|            sface.mNumIndices = 3;
  359|      0|            sface.mIndices = new unsigned int[3];
  360|       |
  361|      0|            sface.mIndices[0] = temp[start_vertex];
  362|      0|            sface.mIndices[1] = temp[(start_vertex + 2) % 4];
  363|      0|            sface.mIndices[2] = temp[(start_vertex + 3) % 4];
  364|       |
  365|       |            // prevent double deletion of the indices field
  366|      0|            face.mIndices = nullptr;
  367|       |
  368|      0|            ngonEncoder.ngonEncodeQuad(&nface, &sface);
  369|       |
  370|      0|            continue;
  371|      0|        }
  372|      0|        else
  373|      0|        {
  374|       |            // A polygon with more than 3 vertices can be either concave or convex.
  375|       |            // Usually everything we're getting is convex and we could easily
  376|       |            // triangulate by tri-fanning. However, LightWave is probably the only
  377|       |            // modeling suite to make extensive use of highly concave, monster polygons ...
  378|       |            // so we need to apply the full 'ear cutting' algorithm to get it right.
  379|       |
  380|       |            // REQUIREMENT: polygon is expected to be simple and *nearly* planar.
  381|       |            // We project it onto a plane to get a 2d triangle.
  382|       |
  383|       |            // Collect all vertices of of the polygon.
  384|      0|            for (unsigned int tmp = 0; tmp < num; ++tmp) {
  ------------------
  |  Branch (384:40): [True: 0, False: 0]
  ------------------
  385|      0|                temp_verts3d[tmp] = verts[idx[tmp]];
  386|      0|            }
  387|       |
  388|       |            // Get newell normal of the polygon. Store it for future use if it's a polygon-only mesh
  389|      0|            aiVector3D n;
  390|      0|            NewellNormal<3, 3, 3>(n, num, &temp_verts3d.front().x, &temp_verts3d.front().y, &temp_verts3d.front().z);
  391|      0|            if (nor_out) {
  ------------------
  |  Branch (391:17): [True: 0, False: 0]
  ------------------
  392|      0|                for (unsigned int tmp = 0; tmp < num; ++tmp)
  ------------------
  |  Branch (392:44): [True: 0, False: 0]
  ------------------
  393|      0|                    nor_out[idx[tmp]] = n;
  394|      0|            }
  395|       |
  396|       |            // Select largest normal coordinate to ignore for projection
  397|      0|            const float ax = (n.x>0 ? n.x : -n.x);
  ------------------
  |  Branch (397:31): [True: 0, False: 0]
  ------------------
  398|      0|            const float ay = (n.y>0 ? n.y : -n.y);
  ------------------
  |  Branch (398:31): [True: 0, False: 0]
  ------------------
  399|      0|            const float az = (n.z>0 ? n.z : -n.z);
  ------------------
  |  Branch (399:31): [True: 0, False: 0]
  ------------------
  400|       |
  401|      0|            unsigned int ac = 0, bc = 1; /* no z coord. projection to xy */
  402|      0|            float inv = n.z;
  403|      0|            if (ax > ay) {
  ------------------
  |  Branch (403:17): [True: 0, False: 0]
  ------------------
  404|      0|                if (ax > az) { /* no x coord. projection to yz */
  ------------------
  |  Branch (404:21): [True: 0, False: 0]
  ------------------
  405|      0|                    ac = 1; bc = 2;
  406|      0|                    inv = n.x;
  407|      0|                }
  408|      0|            }
  409|      0|            else if (ay > az) { /* no y coord. projection to zy */
  ------------------
  |  Branch (409:22): [True: 0, False: 0]
  ------------------
  410|      0|                ac = 2; bc = 0;
  411|      0|                inv = n.y;
  412|      0|            }
  413|       |
  414|       |            // Swap projection axes to take the negated projection vector into account
  415|      0|            if (inv < 0.f) {
  ------------------
  |  Branch (415:17): [True: 0, False: 0]
  ------------------
  416|      0|                std::swap(ac,bc);
  417|      0|            }
  418|       |
  419|      0|            temp_verts.resize(num);
  420|      0|            for (unsigned int tmp = 0; tmp < num; ++tmp) {
  ------------------
  |  Branch (420:40): [True: 0, False: 0]
  ------------------
  421|      0|                temp_verts[tmp].x = verts[idx[tmp]][ac];
  422|      0|                temp_verts[tmp].y = verts[idx[tmp]][bc];
  423|      0|            }
  424|       |
  425|      0|            auto indices = mapbox::earcut(temp_poly);
  426|      0|            for (size_t i = 0; i < indices.size(); i += 3) {
  ------------------
  |  Branch (426:32): [True: 0, False: 0]
  ------------------
  427|      0|                aiFace& nface = *curOut++;
  428|      0|                nface.mIndices = new unsigned int[3];
  429|      0|                nface.mNumIndices = 3;
  430|      0|                nface.mIndices[0] = indices[i];
  431|      0|                nface.mIndices[1] = indices[i + 1];
  432|      0|                nface.mIndices[2] = indices[i + 2];
  433|      0|            }
  434|       |
  435|       |#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
  436|       |            // plot the plane onto which we mapped the polygon to a 2D ASCII pic
  437|       |            aiVector2D bmin,bmax;
  438|       |            ArrayBounds(&temp_verts[0],max,bmin,bmax);
  439|       |
  440|       |            char grid[POLY_GRID_Y][POLY_GRID_X+POLY_GRID_XPAD];
  441|       |            std::fill_n((char*)grid,POLY_GRID_Y*(POLY_GRID_X+POLY_GRID_XPAD),' ');
  442|       |
  443|       |            for (int i =0; i < max; ++i) {
  444|       |                const aiVector2D& v = (temp_verts[i] - bmin) / (bmax-bmin);
  445|       |                const size_t x = static_cast<size_t>(v.x*(POLY_GRID_X-1)), y = static_cast<size_t>(v.y*(POLY_GRID_Y-1));
  446|       |                char* loc = grid[y]+x;
  447|       |                if (grid[y][x] != ' ') {
  448|       |                    for(;*loc != ' '; ++loc);
  449|       |                    *loc++ = '_';
  450|       |                }
  451|       |                *(loc+::ai_snprintf(loc, POLY_GRID_XPAD,"%i",i)) = ' ';
  452|       |            }
  453|       |
  454|       |
  455|       |            for(size_t y = 0; y < POLY_GRID_Y; ++y) {
  456|       |                grid[y][POLY_GRID_X+POLY_GRID_XPAD-1] = '\0';
  457|       |                fprintf(fout,"%s\n",grid[y]);
  458|       |            }
  459|       |
  460|       |            fprintf(fout,"\ntriangulation sequence: ");
  461|       |#endif
  462|      0|        }
  463|       |
  464|       |#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
  465|       |
  466|       |        for(aiFace* f = last_face; f != curOut; ++f) {
  467|       |            unsigned int* i = f->mIndices;
  468|       |            fprintf(fout," (%i %i %i)",i[0],i[1],i[2]);
  469|       |        }
  470|       |
  471|       |        fprintf(fout,"\n*********************************************************************\n");
  472|       |        fflush(fout);
  473|       |
  474|       |#endif
  475|       |
  476|      0|        for(aiFace* f = last_face; f != curOut; ) {
  ------------------
  |  Branch (476:36): [True: 0, False: 0]
  ------------------
  477|      0|            unsigned int* i = f->mIndices;
  478|       |
  479|      0|            i[0] = idx[i[0]];
  480|      0|            i[1] = idx[i[1]];
  481|      0|            i[2] = idx[i[2]];
  482|       |
  483|       |            // IMPROVEMENT: Polygons are not supported yet by this ngon encoding + triangulation step.
  484|       |            //              So we encode polygons as regular triangles. No way to reconstruct the original
  485|       |            //              polygon in this case.
  486|      0|            ngonEncoder.ngonEncodeTriangle(f);
  487|      0|            ++f;
  488|      0|        }
  489|       |
  490|      0|        delete[] face.mIndices;
  491|      0|        face.mIndices = nullptr;
  492|      0|    }
  493|       |
  494|       |#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
  495|       |    fclose(fout);
  496|       |#endif
  497|       |
  498|       |    // kill the old faces
  499|      0|    delete [] pMesh->mFaces;
  500|       |
  501|       |    // ... and store the new ones
  502|      0|    pMesh->mFaces    = out;
  503|      0|    pMesh->mNumFaces = (unsigned int)(curOut-out); /* not necessarily equal to numOut */
  504|      0|    return true;
  505|      0|}

_ZN6Assimp18TriangulateProcessC2Ev:
   65|  5.13k|    TriangulateProcess() = default;

_ZN6Assimp17ValidateDSProcessC2Ev:
   61|  2.02k|ValidateDSProcess::ValidateDSProcess() : mScene(nullptr) {}
_ZN6Assimp17ValidateDSProcess11ReportErrorEPKcz:
   69|    481|AI_WONT_RETURN void ValidateDSProcess::ReportError(const char *msg, ...) {
   70|    481|    ai_assert(nullptr != msg);
   71|       |
   72|    481|    va_list args;
   73|    481|    va_start(args, msg);
   74|       |
   75|    481|    char szBuffer[3000];
   76|    481|    const int iLen = vsnprintf(szBuffer, sizeof(szBuffer), msg, args);
   77|    481|    ai_assert(iLen > 0);
   78|       |
   79|    481|    va_end(args);
   80|       |
   81|    481|    throw DeadlyImportError("Validation failed: ", std::string(szBuffer, iLen));
   82|    481|}
_ZN6Assimp17ValidateDSProcess13ReportWarningEPKcz:
   84|  2.73k|void ValidateDSProcess::ReportWarning(const char *msg, ...) {
   85|  2.73k|    ai_assert(nullptr != msg);
   86|       |
   87|  2.73k|    va_list args;
   88|  2.73k|    va_start(args, msg);
   89|       |
   90|  2.73k|    char szBuffer[3000];
   91|  2.73k|    const int iLen = vsnprintf(szBuffer, sizeof(szBuffer), msg, args);
   92|  2.73k|    ai_assert(iLen > 0);
   93|       |
   94|  2.73k|    va_end(args);
   95|       |    ASSIMP_LOG_WARN("Validation warning: ", std::string(szBuffer, iLen));
   96|  2.73k|}
_ZN6Assimp17ValidateDSProcess7ExecuteEP7aiScene:
  183|  2.02k|void ValidateDSProcess::Execute(aiScene *pScene) {
  184|  2.02k|    mScene = pScene;
  185|  2.02k|    ASSIMP_LOG_DEBUG("ValidateDataStructureProcess begin");
  186|       |
  187|       |    // validate the node graph of the scene
  188|  2.02k|    Validate(pScene->mRootNode);
  189|       |
  190|       |    // validate all meshes
  191|  2.02k|    if (pScene->mNumMeshes) {
  ------------------
  |  Branch (191:9): [True: 1.33k, False: 690]
  ------------------
  192|  1.33k|        DoValidation(pScene->mMeshes, pScene->mNumMeshes, "mMeshes", "mNumMeshes");
  193|  1.33k|    } else if (!(mScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)) {
  ------------------
  |  Branch (193:16): [True: 0, False: 690]
  ------------------
  194|      0|        ReportError("aiScene::mNumMeshes is 0. At least one mesh must be there");
  195|    690|    } else if (pScene->mMeshes) {
  ------------------
  |  Branch (195:16): [True: 0, False: 690]
  ------------------
  196|      0|        ReportError("aiScene::mMeshes is non-null although there are no meshes");
  197|      0|    }
  198|       |
  199|       |    // validate all animations
  200|  2.02k|    if (pScene->mNumAnimations) {
  ------------------
  |  Branch (200:9): [True: 178, False: 1.85k]
  ------------------
  201|    178|        DoValidation(pScene->mAnimations, pScene->mNumAnimations,
  202|    178|                "mAnimations", "mNumAnimations");
  203|  1.85k|    } else if (pScene->mAnimations) {
  ------------------
  |  Branch (203:16): [True: 0, False: 1.85k]
  ------------------
  204|      0|        ReportError("aiScene::mAnimations is non-null although there are no animations");
  205|      0|    }
  206|       |
  207|       |    // validate all cameras
  208|  2.02k|    if (pScene->mNumCameras) {
  ------------------
  |  Branch (208:9): [True: 35, False: 1.99k]
  ------------------
  209|     35|        DoValidationWithNameCheck(pScene->mCameras, pScene->mNumCameras,
  210|     35|                "mCameras", "mNumCameras");
  211|  1.99k|    } else if (pScene->mCameras) {
  ------------------
  |  Branch (211:16): [True: 0, False: 1.99k]
  ------------------
  212|      0|        ReportError("aiScene::mCameras is non-null although there are no cameras");
  213|      0|    }
  214|       |
  215|       |    // validate all lights
  216|  2.02k|    if (pScene->mNumLights) {
  ------------------
  |  Branch (216:9): [True: 0, False: 2.02k]
  ------------------
  217|      0|        DoValidationWithNameCheck(pScene->mLights, pScene->mNumLights,
  218|      0|                "mLights", "mNumLights");
  219|  2.02k|    } else if (pScene->mLights) {
  ------------------
  |  Branch (219:16): [True: 0, False: 2.02k]
  ------------------
  220|      0|        ReportError("aiScene::mLights is non-null although there are no lights");
  221|      0|    }
  222|       |
  223|       |    // validate all textures
  224|  2.02k|    if (pScene->mNumTextures) {
  ------------------
  |  Branch (224:9): [True: 95, False: 1.93k]
  ------------------
  225|     95|        DoValidation(pScene->mTextures, pScene->mNumTextures,
  226|     95|                "mTextures", "mNumTextures");
  227|  1.93k|    } else if (pScene->mTextures) {
  ------------------
  |  Branch (227:16): [True: 0, False: 1.93k]
  ------------------
  228|      0|        ReportError("aiScene::mTextures is non-null although there are no textures");
  229|      0|    }
  230|       |
  231|       |    // validate all materials
  232|  2.02k|    if (pScene->mNumMaterials) {
  ------------------
  |  Branch (232:9): [True: 1.54k, False: 481]
  ------------------
  233|  1.54k|        DoValidation(pScene->mMaterials, pScene->mNumMaterials, "mMaterials", "mNumMaterials");
  234|  1.54k|    }
  235|    481|    else if (pScene->mMaterials) {
  ------------------
  |  Branch (235:14): [True: 0, False: 481]
  ------------------
  236|      0|        ReportError("aiScene::mMaterials is non-null although there are no materials");
  237|      0|    }
  238|       |
  239|       |    //  if (!has)ReportError("The aiScene data structure is empty");
  240|       |    ASSIMP_LOG_DEBUG("ValidateDataStructureProcess end");
  241|  2.02k|}
_ZN6Assimp17ValidateDSProcess8ValidateEPK8aiCamera:
  263|     49|void ValidateDSProcess::Validate(const aiCamera *pCamera) {
  264|     49|    if (pCamera->mClipPlaneFar <= pCamera->mClipPlaneNear)
  ------------------
  |  Branch (264:9): [True: 3, False: 46]
  ------------------
  265|      3|        ReportError("aiCamera::mClipPlaneFar must be >= aiCamera::mClipPlaneNear");
  266|       |
  267|       |    // There are many 3ds files with invalid FOVs. No reason to reject them at all ... a warning is appropriate.
  268|     49|    if (!pCamera->mHorizontalFOV || pCamera->mHorizontalFOV >= (float)AI_MATH_PI)
  ------------------
  |  Branch (268:9): [True: 16, False: 33]
  |  Branch (268:37): [True: 1, False: 32]
  ------------------
  269|     14|        ReportWarning("%f is not a valid value for aiCamera::mHorizontalFOV", pCamera->mHorizontalFOV);
  270|     49|}
_ZN6Assimp17ValidateDSProcess8ValidateEPK6aiMesh:
  273|  1.55k|void ValidateDSProcess::Validate(const aiMesh *pMesh) {
  274|       |    // validate the material index of the mesh
  275|  1.55k|    if (mScene->mNumMaterials && pMesh->mMaterialIndex >= mScene->mNumMaterials) {
  ------------------
  |  Branch (275:9): [True: 1.55k, False: 0]
  |  Branch (275:34): [True: 0, False: 1.55k]
  ------------------
  276|      0|        ReportError("aiMesh::mMaterialIndex is invalid (value: %i maximum: %i)",
  277|      0|                pMesh->mMaterialIndex, mScene->mNumMaterials - 1);
  278|      0|    }
  279|       |
  280|  1.55k|    Validate(&pMesh->mName);
  281|       |
  282|  26.8k|    for (unsigned int i = 0; i < pMesh->mNumFaces; ++i) {
  ------------------
  |  Branch (282:30): [True: 25.2k, False: 1.55k]
  ------------------
  283|  25.2k|        aiFace &face = pMesh->mFaces[i];
  284|       |
  285|  25.2k|        if (pMesh->mPrimitiveTypes) {
  ------------------
  |  Branch (285:13): [True: 25.2k, False: 0]
  ------------------
  286|  25.2k|            switch (face.mNumIndices) {
  287|      0|            case 0:
  ------------------
  |  Branch (287:13): [True: 0, False: 25.2k]
  ------------------
  288|      0|                ReportError("aiMesh::mFaces[%i].mNumIndices is 0", i);
  289|    640|            case 1:
  ------------------
  |  Branch (289:13): [True: 640, False: 24.6k]
  ------------------
  290|    640|                if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_POINT)) {
  ------------------
  |  Branch (290:21): [True: 0, False: 640]
  ------------------
  291|      0|                    ReportError("aiMesh::mFaces[%i] is a POINT but aiMesh::mPrimitiveTypes "
  292|      0|                                "does not report the POINT flag",
  293|      0|                            i);
  294|      0|                }
  295|    640|                break;
  296|  6.39k|            case 2:
  ------------------
  |  Branch (296:13): [True: 6.39k, False: 18.8k]
  ------------------
  297|  6.39k|                if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_LINE)) {
  ------------------
  |  Branch (297:21): [True: 0, False: 6.39k]
  ------------------
  298|      0|                    ReportError("aiMesh::mFaces[%i] is a LINE but aiMesh::mPrimitiveTypes "
  299|      0|                                "does not report the LINE flag",
  300|      0|                            i);
  301|      0|                }
  302|  6.39k|                break;
  303|  18.2k|            case 3:
  ------------------
  |  Branch (303:13): [True: 18.2k, False: 7.03k]
  ------------------
  304|  18.2k|                if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE)) {
  ------------------
  |  Branch (304:21): [True: 0, False: 18.2k]
  ------------------
  305|      0|                    ReportError("aiMesh::mFaces[%i] is a TRIANGLE but aiMesh::mPrimitiveTypes "
  306|      0|                                "does not report the TRIANGLE flag",
  307|      0|                            i);
  308|      0|                }
  309|  18.2k|                break;
  310|      0|            default:
  ------------------
  |  Branch (310:13): [True: 0, False: 25.2k]
  ------------------
  311|      0|                if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_POLYGON)) {
  ------------------
  |  Branch (311:21): [True: 0, False: 0]
  ------------------
  312|      0|                    this->ReportError("aiMesh::mFaces[%i] is a POLYGON but aiMesh::mPrimitiveTypes "
  313|      0|                                      "does not report the POLYGON flag",
  314|      0|                            i);
  315|      0|                }
  316|      0|                break;
  317|  25.2k|            };
  318|  25.2k|        }
  319|       |
  320|  25.2k|        if (!face.mIndices)
  ------------------
  |  Branch (320:13): [True: 0, False: 25.2k]
  ------------------
  321|      0|            ReportError("aiMesh::mFaces[%i].mIndices is nullptr", i);
  322|  25.2k|    }
  323|       |
  324|       |    // positions must always be there ...
  325|  1.55k|    if (!pMesh->mNumVertices || (!pMesh->mVertices && !mScene->mFlags)) {
  ------------------
  |  Branch (325:9): [True: 21, False: 1.53k]
  |  Branch (325:34): [True: 10, False: 1.52k]
  |  Branch (325:55): [True: 10, False: 0]
  ------------------
  326|     31|        ReportError("The mesh %s contains no vertices", pMesh->mName.C_Str());
  327|     31|    }
  328|       |
  329|  1.55k|    if (pMesh->mNumVertices > AI_MAX_VERTICES) {
  ------------------
  |  Branch (329:9): [True: 0, False: 1.55k]
  ------------------
  330|      0|        ReportError("Mesh has too many vertices: %u, but the limit is %u", pMesh->mNumVertices, AI_MAX_VERTICES);
  331|      0|    }
  332|  1.55k|    if (pMesh->mNumFaces > AI_MAX_FACES) {
  ------------------
  |  Branch (332:9): [True: 0, False: 1.55k]
  ------------------
  333|      0|        ReportError("Mesh has too many faces: %u, but the limit is %u", pMesh->mNumFaces, AI_MAX_FACES);
  334|      0|    }
  335|       |
  336|       |    // if tangents are there there must also be bitangent vectors ...
  337|  1.55k|    if ((pMesh->mTangents != nullptr) != (pMesh->mBitangents != nullptr)) {
  ------------------
  |  Branch (337:9): [True: 0, False: 1.55k]
  ------------------
  338|      0|        ReportError("If there are tangents, bitangent vectors must be present as well");
  339|      0|    }
  340|       |
  341|       |    // faces, too
  342|  1.55k|    if (!pMesh->mNumFaces || (!pMesh->mFaces && !mScene->mFlags)) {
  ------------------
  |  Branch (342:9): [True: 34, False: 1.51k]
  |  Branch (342:31): [True: 0, False: 1.51k]
  |  Branch (342:49): [True: 0, False: 0]
  ------------------
  343|      3|        ReportError("Mesh %s contains no faces", pMesh->mName.C_Str());
  344|      3|    }
  345|       |
  346|       |    // now check whether the face indexing layout is correct:
  347|       |    // unique vertices, pseudo-indexed.
  348|  1.55k|    std::vector<bool> abRefList;
  349|  1.55k|    abRefList.resize(pMesh->mNumVertices, false);
  350|  25.9k|    for (unsigned int i = 0; i < pMesh->mNumFaces; ++i) {
  ------------------
  |  Branch (350:30): [True: 24.3k, False: 1.55k]
  ------------------
  351|  24.3k|        aiFace &face = pMesh->mFaces[i];
  352|  24.3k|        if (face.mNumIndices > AI_MAX_FACE_INDICES) {
  ------------------
  |  Branch (352:13): [True: 0, False: 24.3k]
  ------------------
  353|      0|            ReportError("Face %u has too many faces: %u, but the limit is %u", i, face.mNumIndices, AI_MAX_FACE_INDICES);
  354|      0|        }
  355|       |
  356|  89.8k|        for (unsigned int a = 0; a < face.mNumIndices; ++a) {
  ------------------
  |  Branch (356:34): [True: 65.5k, False: 24.3k]
  ------------------
  357|  65.5k|            if (face.mIndices[a] >= pMesh->mNumVertices) {
  ------------------
  |  Branch (357:17): [True: 0, False: 65.5k]
  ------------------
  358|      0|                ReportError("aiMesh::mFaces[%i]::mIndices[%i] is out of range", i, a);
  359|      0|            }
  360|  65.5k|            abRefList[face.mIndices[a]] = true;
  361|  65.5k|        }
  362|  24.3k|    }
  363|       |
  364|       |    // check whether there are vertices that aren't referenced by a face
  365|  1.55k|    bool b = false;
  366|  29.0k|    for (unsigned int i = 0; i < pMesh->mNumVertices; ++i) {
  ------------------
  |  Branch (366:30): [True: 27.4k, False: 1.55k]
  ------------------
  367|  27.4k|        if (!abRefList[i]) b = true;
  ------------------
  |  Branch (367:13): [True: 458, False: 27.0k]
  ------------------
  368|  27.4k|    }
  369|  1.55k|    abRefList.clear();
  370|  1.55k|    if (b) {
  ------------------
  |  Branch (370:9): [True: 269, False: 1.28k]
  ------------------
  371|    269|        ReportWarning("There are unreferenced vertices");
  372|    269|    }
  373|       |
  374|       |    // vertex color channel 2 may not be set if channel 1 is zero ...
  375|  1.55k|    {
  376|  1.55k|        unsigned int i = 0;
  377|  1.70k|        for (; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) {
  ------------------
  |  Branch (377:16): [True: 1.67k, False: 34]
  ------------------
  378|  1.67k|            if (!pMesh->HasVertexColors(i)) break;
  ------------------
  |  Branch (378:17): [True: 1.51k, False: 157]
  ------------------
  379|  1.67k|        }
  380|  13.5k|        for (; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i)
  ------------------
  |  Branch (380:16): [True: 11.9k, False: 1.55k]
  ------------------
  381|  11.9k|            if (pMesh->HasVertexColors(i)) {
  ------------------
  |  Branch (381:17): [True: 0, False: 11.9k]
  ------------------
  382|      0|                ReportError("Vertex color channel %i is exists "
  383|      0|                            "although the previous channel was nullptr.",
  384|      0|                        i);
  385|      0|            }
  386|  1.55k|    }
  387|       |
  388|       |    // now validate all bones
  389|  1.55k|    if (pMesh->mNumBones) {
  ------------------
  |  Branch (389:9): [True: 281, False: 1.27k]
  ------------------
  390|    281|        if (!pMesh->mBones) {
  ------------------
  |  Branch (390:13): [True: 0, False: 281]
  ------------------
  391|      0|            ReportError("aiMesh::mBones is nullptr (aiMesh::mNumBones is %i)",
  392|      0|                    pMesh->mNumBones);
  393|      0|        }
  394|    281|        std::unique_ptr<float[]> afSum(nullptr);
  395|    281|        if (pMesh->mNumVertices) {
  ------------------
  |  Branch (395:13): [True: 281, False: 0]
  ------------------
  396|    281|            afSum.reset(new float[pMesh->mNumVertices]);
  397|  1.82k|            for (unsigned int i = 0; i < pMesh->mNumVertices; ++i)
  ------------------
  |  Branch (397:38): [True: 1.54k, False: 281]
  ------------------
  398|  1.54k|                afSum[i] = 0.0f;
  399|    281|        }
  400|       |
  401|       |        // check whether there are duplicate bone names
  402|  1.91k|        for (unsigned int i = 0; i < pMesh->mNumBones; ++i) {
  ------------------
  |  Branch (402:34): [True: 1.63k, False: 281]
  ------------------
  403|  1.63k|            const aiBone *bone = pMesh->mBones[i];
  404|  1.63k|            if (bone->mNumWeights > AI_MAX_BONE_WEIGHTS) {
  ------------------
  |  Branch (404:17): [True: 0, False: 1.63k]
  ------------------
  405|      0|                ReportError("Bone %u has too many weights: %u, but the limit is %u", i, bone->mNumWeights, AI_MAX_BONE_WEIGHTS);
  406|      0|            }
  407|       |
  408|  1.63k|            if (!pMesh->mBones[i]) {
  ------------------
  |  Branch (408:17): [True: 0, False: 1.63k]
  ------------------
  409|      0|                ReportError("aiMesh::mBones[%i] is nullptr (aiMesh::mNumBones is %i)",
  410|      0|                        i, pMesh->mNumBones);
  411|      0|            }
  412|  1.63k|            Validate(pMesh, pMesh->mBones[i], afSum.get());
  413|       |
  414|  8.10k|            for (unsigned int a = i + 1; a < pMesh->mNumBones; ++a) {
  ------------------
  |  Branch (414:42): [True: 6.47k, False: 1.63k]
  ------------------
  415|  6.47k|                if (pMesh->mBones[i]->mName == pMesh->mBones[a]->mName) {
  ------------------
  |  Branch (415:21): [True: 32, False: 6.44k]
  ------------------
  416|     32|                    const char *name = "unknown";
  417|     32|                    if (nullptr != pMesh->mBones[i]->mName.C_Str()) {
  ------------------
  |  Branch (417:25): [True: 32, False: 0]
  ------------------
  418|     32|                        name = pMesh->mBones[i]->mName.C_Str();
  419|     32|                    }
  420|     32|                    ReportError("aiMesh::mBones[%i], name = \"%s\" has the same name as "
  421|     32|                                "aiMesh::mBones[%i]",
  422|     32|                            i, name, a);
  423|     32|                }
  424|  6.47k|            }
  425|  1.63k|        }
  426|       |        // check whether all bone weights for a vertex sum to 1.0 ...
  427|  1.67k|        for (unsigned int i = 0; i < pMesh->mNumVertices; ++i) {
  ------------------
  |  Branch (427:34): [True: 1.39k, False: 281]
  ------------------
  428|  1.39k|            if (afSum[i] && (afSum[i] <= 0.94 || afSum[i] >= 1.05)) {
  ------------------
  |  Branch (428:17): [True: 980, False: 411]
  |  Branch (428:30): [True: 315, False: 665]
  |  Branch (428:50): [True: 359, False: 306]
  ------------------
  429|    674|                ReportWarning("aiMesh::mVertices[%i]: bone weight sum != 1.0 (sum is %f)", i, afSum[i]);
  430|    674|            }
  431|  1.39k|        }
  432|  1.27k|    } else if (pMesh->mBones) {
  ------------------
  |  Branch (432:16): [True: 4, False: 1.26k]
  ------------------
  433|      4|        ReportError("aiMesh::mBones is non-null although there are no bones");
  434|      4|    }
  435|  1.55k|}
_ZN6Assimp17ValidateDSProcess8ValidateEPK6aiMeshPK6aiBonePf:
  438|  1.63k|void ValidateDSProcess::Validate(const aiMesh *pMesh, const aiBone *pBone, float *afSum) {
  439|  1.63k|    this->Validate(&pBone->mName);
  440|       |
  441|  1.63k|    if (!pBone->mNumWeights) {
  ------------------
  |  Branch (441:9): [True: 0, False: 1.63k]
  ------------------
  442|      0|        ReportWarning("aiBone::mNumWeights is zero");
  443|      0|    }
  444|       |
  445|       |    // check whether all vertices affected by this bone are valid
  446|  5.88k|    for (unsigned int i = 0; i < pBone->mNumWeights; ++i) {
  ------------------
  |  Branch (446:30): [True: 4.25k, False: 1.63k]
  ------------------
  447|  4.25k|        if (pBone->mWeights[i].mVertexId >= pMesh->mNumVertices) {
  ------------------
  |  Branch (447:13): [True: 2, False: 4.25k]
  ------------------
  448|      2|            ReportError("aiBone::mWeights[%i].mVertexId is out of range", i);
  449|  4.25k|        } else if (!pBone->mWeights[i].mWeight || pBone->mWeights[i].mWeight > 1.0f) {
  ------------------
  |  Branch (449:20): [True: 716, False: 3.53k]
  |  Branch (449:51): [True: 865, False: 2.67k]
  ------------------
  450|  1.58k|                ReportWarning("aiBone::mWeights[%i].mWeight has an invalid value %i. Value must be greater than zero and less than 1.", i, pBone->mWeights[i].mWeight);
  451|  1.58k|        }
  452|  4.25k|        afSum[pBone->mWeights[i].mVertexId] += pBone->mWeights[i].mWeight;
  453|  4.25k|    }
  454|  1.63k|}
_ZN6Assimp17ValidateDSProcess8ValidateEPK11aiAnimation:
  457|    178|void ValidateDSProcess::Validate(const aiAnimation *pAnimation) {
  458|    178|    Validate(&pAnimation->mName);
  459|       |
  460|       |    // validate all animations
  461|    178|    if (pAnimation->mNumChannels || pAnimation->mNumMorphMeshChannels) {
  ------------------
  |  Branch (461:9): [True: 106, False: 72]
  |  Branch (461:37): [True: 0, False: 72]
  ------------------
  462|    106|        if (!pAnimation->mChannels && pAnimation->mNumChannels) {
  ------------------
  |  Branch (462:13): [True: 0, False: 106]
  |  Branch (462:39): [True: 0, False: 0]
  ------------------
  463|      0|            ReportError("aiAnimation::mChannels is nullptr (aiAnimation::mNumChannels is %i)",
  464|      0|                    pAnimation->mNumChannels);
  465|      0|        }
  466|    106|        if (!pAnimation->mMorphMeshChannels && pAnimation->mNumMorphMeshChannels) {
  ------------------
  |  Branch (466:13): [True: 106, False: 0]
  |  Branch (466:48): [True: 0, False: 106]
  ------------------
  467|      0|            ReportError("aiAnimation::mMorphMeshChannels is nullptr (aiAnimation::mNumMorphMeshChannels is %i)",
  468|      0|                    pAnimation->mNumMorphMeshChannels);
  469|      0|        }
  470|    212|        for (unsigned int i = 0; i < pAnimation->mNumChannels; ++i) {
  ------------------
  |  Branch (470:34): [True: 106, False: 106]
  ------------------
  471|    106|            if (!pAnimation->mChannels[i]) {
  ------------------
  |  Branch (471:17): [True: 0, False: 106]
  ------------------
  472|      0|                ReportError("aiAnimation::mChannels[%i] is nullptr (aiAnimation::mNumChannels is %i)",
  473|      0|                        i, pAnimation->mNumChannels);
  474|      0|            }
  475|    106|            Validate(pAnimation, pAnimation->mChannels[i]);
  476|    106|        }
  477|    106|        for (unsigned int i = 0; i < pAnimation->mNumMorphMeshChannels; ++i) {
  ------------------
  |  Branch (477:34): [True: 0, False: 106]
  ------------------
  478|      0|            if (!pAnimation->mMorphMeshChannels[i]) {
  ------------------
  |  Branch (478:17): [True: 0, False: 0]
  ------------------
  479|      0|                ReportError("aiAnimation::mMorphMeshChannels[%i] is nullptr (aiAnimation::mNumMorphMeshChannels is %i)",
  480|      0|                        i, pAnimation->mNumMorphMeshChannels);
  481|      0|            }
  482|      0|            Validate(pAnimation, pAnimation->mMorphMeshChannels[i]);
  483|      0|        }
  484|    106|    } else {
  485|     72|        ReportError("aiAnimation::mNumChannels is 0. At least one node animation channel must be there.");
  486|     72|    }
  487|    178|}
_ZN6Assimp17ValidateDSProcess24SearchForInvalidTexturesEPK10aiMaterial13aiTextureType:
  491|  44.5k|        aiTextureType type) {
  492|  44.5k|    const char *szType = aiTextureTypeToString(type);
  493|       |
  494|       |    // ****************************************************************************
  495|       |    // Search all keys of the material ...
  496|       |    // textures must be specified with ascending indices
  497|       |    // (e.g. diffuse #2 may not be specified if diffuse #1 is not there ...)
  498|       |    // ****************************************************************************
  499|       |
  500|  44.5k|    int iNumIndices = 0;
  501|  44.5k|    int iIndex = -1;
  502|   584k|    for (unsigned int i = 0; i < pMaterial->mNumProperties; ++i) {
  ------------------
  |  Branch (502:30): [True: 539k, False: 44.5k]
  ------------------
  503|   539k|        aiMaterialProperty *prop = pMaterial->mProperties[i];
  504|   539k|        ai_assert(nullptr != prop);
  505|   539k|        if (!::strcmp(prop->mKey.data, "$tex.file") && prop->mSemantic == static_cast<unsigned int>(type)) {
  ------------------
  |  Branch (505:13): [True: 5.57k, False: 533k]
  |  Branch (505:56): [True: 328, False: 5.24k]
  ------------------
  506|    328|            iIndex = std::max(iIndex, (int)prop->mIndex);
  507|    328|            ++iNumIndices;
  508|       |
  509|    328|            if (aiPTI_String != prop->mType) {
  ------------------
  |  Branch (509:17): [True: 0, False: 328]
  ------------------
  510|      0|                ReportError("Material property %s is expected to be a string", prop->mKey.data);
  511|      0|            }
  512|    328|        }
  513|   539k|    }
  514|  44.5k|    if (iIndex + 1 != iNumIndices) {
  ------------------
  |  Branch (514:9): [True: 0, False: 44.5k]
  ------------------
  515|      0|        ReportError("%s #%i is set, but there are only %i %s textures",
  516|      0|                szType, iIndex, iNumIndices, szType);
  517|      0|    }
  518|  44.5k|    if (!iNumIndices) {
  ------------------
  |  Branch (518:9): [True: 44.2k, False: 328]
  ------------------
  519|  44.2k|        return;
  520|  44.2k|    }
  521|    328|    std::vector<aiTextureMapping> mappings(iNumIndices);
  522|       |
  523|       |    // Now check whether all UV indices are valid ...
  524|    328|    bool bNoSpecified = true;
  525|  8.37k|    for (unsigned int i = 0; i < pMaterial->mNumProperties; ++i) {
  ------------------
  |  Branch (525:30): [True: 8.04k, False: 328]
  ------------------
  526|  8.04k|        aiMaterialProperty *prop = pMaterial->mProperties[i];
  527|  8.04k|        if (static_cast<aiTextureType>(prop->mSemantic) != type) {
  ------------------
  |  Branch (527:13): [True: 5.98k, False: 2.06k]
  ------------------
  528|  5.98k|            continue;
  529|  5.98k|        }
  530|       |
  531|  2.06k|        if ((int)prop->mIndex >= iNumIndices) {
  ------------------
  |  Branch (531:13): [True: 0, False: 2.06k]
  ------------------
  532|      0|            ReportError("Found texture property with index %i, although there "
  533|      0|                        "are only %i textures of type %s",
  534|      0|                    prop->mIndex, iNumIndices, szType);
  535|      0|        }
  536|       |
  537|  2.06k|        if (!::strcmp(prop->mKey.data, "$tex.mapping")) {
  ------------------
  |  Branch (537:13): [True: 0, False: 2.06k]
  ------------------
  538|      0|            if (aiPTI_Integer != prop->mType || prop->mDataLength < sizeof(aiTextureMapping)) {
  ------------------
  |  Branch (538:17): [True: 0, False: 0]
  |  Branch (538:49): [True: 0, False: 0]
  ------------------
  539|      0|                ReportError("Material property %s%i is expected to be an integer (size is %i)",
  540|      0|                        prop->mKey.data, prop->mIndex, prop->mDataLength);
  541|      0|            }
  542|      0|            mappings[prop->mIndex] = *((aiTextureMapping *)prop->mData);
  543|  2.06k|        } else if (!::strcmp(prop->mKey.data, "$tex.uvtrafo")) {
  ------------------
  |  Branch (543:20): [True: 0, False: 2.06k]
  ------------------
  544|      0|            if (aiPTI_Float != prop->mType || prop->mDataLength < sizeof(aiUVTransform)) {
  ------------------
  |  Branch (544:17): [True: 0, False: 0]
  |  Branch (544:47): [True: 0, False: 0]
  ------------------
  545|      0|                ReportError("Material property %s%i is expected to be 5 floats large (size is %i)",
  546|      0|                        prop->mKey.data, prop->mIndex, prop->mDataLength);
  547|      0|            }
  548|       |            //mappings[prop->mIndex] = ((aiUVTransform*)prop->mData);
  549|  2.06k|        } else if (!::strcmp(prop->mKey.data, "$tex.uvwsrc")) {
  ------------------
  |  Branch (549:20): [True: 328, False: 1.73k]
  ------------------
  550|    328|            if (aiPTI_Integer != prop->mType || sizeof(int) > prop->mDataLength) {
  ------------------
  |  Branch (550:17): [True: 0, False: 328]
  |  Branch (550:49): [True: 0, False: 328]
  ------------------
  551|      0|                ReportError("Material property %s%i is expected to be an integer (size is %i)",
  552|      0|                        prop->mKey.data, prop->mIndex, prop->mDataLength);
  553|      0|            }
  554|    328|            bNoSpecified = false;
  555|       |
  556|       |            // Ignore UV indices for texture channels that are not there ...
  557|       |
  558|       |            // Get the value
  559|    328|            iIndex = *((unsigned int *)prop->mData);
  560|       |
  561|       |            // Check whether there is a mesh using this material
  562|       |            // which has not enough UV channels ...
  563|  1.40k|            for (unsigned int a = 0; a < mScene->mNumMeshes; ++a) {
  ------------------
  |  Branch (563:38): [True: 1.07k, False: 328]
  ------------------
  564|  1.07k|                aiMesh *mesh = this->mScene->mMeshes[a];
  565|  1.07k|                if (mesh->mMaterialIndex == (unsigned int)i) {
  ------------------
  |  Branch (565:21): [True: 36, False: 1.03k]
  ------------------
  566|     36|                    int iChannels = 0;
  567|     56|                    while (mesh->HasTextureCoords(iChannels))
  ------------------
  |  Branch (567:28): [True: 20, False: 36]
  ------------------
  568|     20|                        ++iChannels;
  569|     36|                    if (iIndex >= iChannels) {
  ------------------
  |  Branch (569:25): [True: 16, False: 20]
  ------------------
  570|     16|                        ReportWarning("Invalid UV index: %i (key %s). Mesh %i has only %i UV channels",
  571|     16|                                iIndex, prop->mKey.data, a, iChannels);
  572|     16|                    }
  573|     36|                }
  574|  1.07k|            }
  575|    328|        }
  576|  2.06k|    }
  577|    328|    if (bNoSpecified) {
  ------------------
  |  Branch (577:9): [True: 0, False: 328]
  ------------------
  578|       |        // Assume that all textures are using the first UV channel
  579|      0|        for (unsigned int a = 0; a < mScene->mNumMeshes; ++a) {
  ------------------
  |  Branch (579:34): [True: 0, False: 0]
  ------------------
  580|      0|            aiMesh *mesh = mScene->mMeshes[a];
  581|      0|            if (mesh->mMaterialIndex == (unsigned int)iIndex && mappings[0] == aiTextureMapping_UV) {
  ------------------
  |  Branch (581:17): [True: 0, False: 0]
  |  Branch (581:65): [True: 0, False: 0]
  ------------------
  582|      0|                if (!mesh->mTextureCoords[0]) {
  ------------------
  |  Branch (582:21): [True: 0, False: 0]
  ------------------
  583|       |                    // This is a special case ... it could be that the
  584|       |                    // original mesh format intended the use of a special
  585|       |                    // mapping here.
  586|      0|                    ReportWarning("UV-mapped texture, but there are no UV coords");
  587|      0|                }
  588|      0|            }
  589|      0|        }
  590|      0|    }
  591|    328|}
_ZN6Assimp17ValidateDSProcess8ValidateEPK10aiMaterial:
  593|  2.62k|void ValidateDSProcess::Validate(const aiMaterial *pMaterial) {
  594|       |    // check whether there are material keys that are obviously not legal
  595|  34.3k|    for (unsigned int i = 0; i < pMaterial->mNumProperties; ++i) {
  ------------------
  |  Branch (595:30): [True: 31.7k, False: 2.62k]
  ------------------
  596|  31.7k|        const aiMaterialProperty *prop = pMaterial->mProperties[i];
  597|  31.7k|        if (!prop) {
  ------------------
  |  Branch (597:13): [True: 0, False: 31.7k]
  ------------------
  598|      0|            ReportError("aiMaterial::mProperties[%i] is nullptr (aiMaterial::mNumProperties is %i)",
  599|      0|                    i, pMaterial->mNumProperties);
  600|      0|        }
  601|  31.7k|        if (!prop->mDataLength || !prop->mData) {
  ------------------
  |  Branch (601:13): [True: 0, False: 31.7k]
  |  Branch (601:35): [True: 0, False: 31.7k]
  ------------------
  602|      0|            ReportError("aiMaterial::mProperties[%i].mDataLength or "
  603|      0|                        "aiMaterial::mProperties[%i].mData is 0",
  604|      0|                    i, i);
  605|      0|        }
  606|       |        // check all predefined types
  607|  31.7k|        if (aiPTI_String == prop->mType) {
  ------------------
  |  Branch (607:13): [True: 4.51k, False: 27.2k]
  ------------------
  608|       |            // FIX: strings are now stored in a less expensive way, but we can't use the
  609|       |            // validation routine for 'normal' aiStrings
  610|  4.51k|            if (prop->mDataLength < 5 || prop->mDataLength < 4 + (*reinterpret_cast<uint32_t *>(prop->mData)) + 1) {
  ------------------
  |  Branch (610:17): [True: 0, False: 4.51k]
  |  Branch (610:42): [True: 0, False: 4.51k]
  ------------------
  611|      0|                ReportError("aiMaterial::mProperties[%i].mDataLength is "
  612|      0|                            "too small to contain a string (%i, needed: %i)",
  613|      0|                        i, prop->mDataLength, static_cast<int>(sizeof(aiString)));
  614|      0|            }
  615|  4.51k|            if (prop->mData[prop->mDataLength - 1]) {
  ------------------
  |  Branch (615:17): [True: 0, False: 4.51k]
  ------------------
  616|      0|                ReportError("Missing null-terminator in string material property");
  617|      0|            }
  618|       |            //  Validate((const aiString*)prop->mData);
  619|  27.2k|        } else if (aiPTI_Float == prop->mType) {
  ------------------
  |  Branch (619:20): [True: 20.8k, False: 6.39k]
  ------------------
  620|  20.8k|            if (prop->mDataLength < sizeof(float)) {
  ------------------
  |  Branch (620:17): [True: 0, False: 20.8k]
  ------------------
  621|      0|                ReportError("aiMaterial::mProperties[%i].mDataLength is "
  622|      0|                            "too small to contain a float (%i, needed: %i)",
  623|      0|                        i, prop->mDataLength, static_cast<int>(sizeof(float)));
  624|      0|            }
  625|  20.8k|        } else if (aiPTI_Integer == prop->mType) {
  ------------------
  |  Branch (625:20): [True: 328, False: 6.06k]
  ------------------
  626|    328|            if (prop->mDataLength < sizeof(int)) {
  ------------------
  |  Branch (626:17): [True: 0, False: 328]
  ------------------
  627|      0|                ReportError("aiMaterial::mProperties[%i].mDataLength is "
  628|      0|                            "too small to contain an integer (%i, needed: %i)",
  629|      0|                        i, prop->mDataLength, static_cast<int>(sizeof(int)));
  630|      0|            }
  631|    328|        }
  632|       |        // TODO: check whether there is a key with an unknown name ...
  633|  31.7k|    }
  634|       |
  635|       |    // make some more specific tests
  636|  2.62k|    ai_real fTemp;
  637|  2.62k|    int iShading;
  638|  2.62k|    if (AI_SUCCESS == aiGetMaterialInteger(pMaterial, AI_MATKEY_SHADING_MODEL, &iShading)) {
  ------------------
  |  Branch (638:9): [True: 2.60k, False: 18]
  ------------------
  639|  2.60k|        switch ((aiShadingMode)iShading) {
  640|      0|        case aiShadingMode_Blinn:
  ------------------
  |  Branch (640:9): [True: 0, False: 2.60k]
  ------------------
  641|      0|        case aiShadingMode_CookTorrance:
  ------------------
  |  Branch (641:9): [True: 0, False: 2.60k]
  ------------------
  642|      0|        case aiShadingMode_Phong:
  ------------------
  |  Branch (642:9): [True: 0, False: 2.60k]
  ------------------
  643|       |
  644|      0|            if (AI_SUCCESS != aiGetMaterialFloat(pMaterial, AI_MATKEY_SHININESS, &fTemp)) {
  ------------------
  |  Branch (644:17): [True: 0, False: 0]
  ------------------
  645|      0|                ReportWarning("A specular shading model is specified but there is no "
  646|      0|                              "AI_MATKEY_SHININESS key");
  647|      0|            }
  648|      0|            if (AI_SUCCESS == aiGetMaterialFloat(pMaterial, AI_MATKEY_SHININESS_STRENGTH, &fTemp) && !fTemp) {
  ------------------
  |  Branch (648:17): [True: 0, False: 0]
  |  Branch (648:102): [True: 0, False: 0]
  ------------------
  649|      0|                ReportWarning("A specular shading model is specified but the value of the "
  650|      0|                              "AI_MATKEY_SHININESS_STRENGTH key is 0.0");
  651|      0|            }
  652|      0|            break;
  653|  2.60k|        default:
  ------------------
  |  Branch (653:9): [True: 2.60k, False: 0]
  ------------------
  654|  2.60k|            break;
  655|  2.60k|        }
  656|  2.60k|    }
  657|       |
  658|  2.62k|    if (AI_SUCCESS == aiGetMaterialFloat(pMaterial, AI_MATKEY_OPACITY, &fTemp) && (!fTemp || fTemp > 1.01)) {
  ------------------
  |  Branch (658:9): [True: 2.60k, False: 18]
  |  Branch (658:84): [True: 8, False: 2.59k]
  |  Branch (658:94): [True: 12, False: 2.58k]
  ------------------
  659|     20|        ReportWarning("Invalid opacity value (must be 0 < opacity < 1.0)");
  660|     20|    }
  661|       |
  662|       |    // Check whether there are invalid texture keys
  663|       |    // TODO: that's a relict of the past, where texture type and index were baked
  664|       |    // into the material string ... we could do that in one single pass.
  665|  2.62k|    SearchForInvalidTextures(pMaterial, aiTextureType_DIFFUSE);
  666|  2.62k|    SearchForInvalidTextures(pMaterial, aiTextureType_SPECULAR);
  667|  2.62k|    SearchForInvalidTextures(pMaterial, aiTextureType_AMBIENT);
  668|  2.62k|    SearchForInvalidTextures(pMaterial, aiTextureType_EMISSIVE);
  669|  2.62k|    SearchForInvalidTextures(pMaterial, aiTextureType_OPACITY);
  670|  2.62k|    SearchForInvalidTextures(pMaterial, aiTextureType_SHININESS);
  671|  2.62k|    SearchForInvalidTextures(pMaterial, aiTextureType_HEIGHT);
  672|  2.62k|    SearchForInvalidTextures(pMaterial, aiTextureType_NORMALS);
  673|  2.62k|    SearchForInvalidTextures(pMaterial, aiTextureType_DISPLACEMENT);
  674|  2.62k|    SearchForInvalidTextures(pMaterial, aiTextureType_LIGHTMAP);
  675|  2.62k|    SearchForInvalidTextures(pMaterial, aiTextureType_REFLECTION);
  676|  2.62k|    SearchForInvalidTextures(pMaterial, aiTextureType_BASE_COLOR);
  677|  2.62k|    SearchForInvalidTextures(pMaterial, aiTextureType_NORMAL_CAMERA);
  678|  2.62k|    SearchForInvalidTextures(pMaterial, aiTextureType_EMISSION_COLOR);
  679|  2.62k|    SearchForInvalidTextures(pMaterial, aiTextureType_METALNESS);
  680|  2.62k|    SearchForInvalidTextures(pMaterial, aiTextureType_DIFFUSE_ROUGHNESS);
  681|  2.62k|    SearchForInvalidTextures(pMaterial, aiTextureType_AMBIENT_OCCLUSION);
  682|  2.62k|}
_ZN6Assimp17ValidateDSProcess8ValidateEPK9aiTexture:
  685|     95|void ValidateDSProcess::Validate(const aiTexture *pTexture) {
  686|       |    // the data section may NEVER be nullptr
  687|     95|    if (nullptr == pTexture->pcData) {
  ------------------
  |  Branch (687:9): [True: 0, False: 95]
  ------------------
  688|      0|        ReportError("aiTexture::pcData is nullptr");
  689|      0|    }
  690|     95|    if (pTexture->mHeight) {
  ------------------
  |  Branch (690:9): [True: 0, False: 95]
  ------------------
  691|      0|        if (!pTexture->mWidth) {
  ------------------
  |  Branch (691:13): [True: 0, False: 0]
  ------------------
  692|      0|            ReportError("aiTexture::mWidth is zero (aiTexture::mHeight is %i, uncompressed texture)",
  693|      0|                    pTexture->mHeight);
  694|      0|        }
  695|     95|    } else {
  696|     95|        if (!pTexture->mWidth) {
  ------------------
  |  Branch (696:13): [True: 0, False: 95]
  ------------------
  697|      0|            ReportError("aiTexture::mWidth is zero (compressed texture)");
  698|      0|        }
  699|     95|        if ('\0' != pTexture->achFormatHint[HINTMAXTEXTURELEN - 1]) {
  ------------------
  |  Branch (699:13): [True: 0, False: 95]
  ------------------
  700|      0|            ReportWarning("aiTexture::achFormatHint must be zero-terminated");
  701|     95|        } else if ('.' == pTexture->achFormatHint[0]) {
  ------------------
  |  Branch (701:20): [True: 1, False: 94]
  ------------------
  702|      1|            ReportWarning("aiTexture::achFormatHint should contain a file extension "
  703|      1|                          "without a leading dot (format hint: %s).",
  704|      1|                    pTexture->achFormatHint);
  705|      1|        }
  706|     95|    }
  707|       |
  708|     95|    const char *sz = pTexture->achFormatHint;
  709|     95|    if ((sz[0] >= 'A' && sz[0] <= 'Z') ||
  ------------------
  |  Branch (709:10): [True: 93, False: 2]
  |  Branch (709:26): [True: 2, False: 91]
  ------------------
  710|     93|            (sz[1] >= 'A' && sz[1] <= 'Z') ||
  ------------------
  |  Branch (710:14): [True: 90, False: 3]
  |  Branch (710:30): [True: 1, False: 89]
  ------------------
  711|     92|            (sz[2] >= 'A' && sz[2] <= 'Z') ||
  ------------------
  |  Branch (711:14): [True: 89, False: 3]
  |  Branch (711:30): [True: 1, False: 88]
  ------------------
  712|     91|            (sz[3] >= 'A' && sz[3] <= 'Z')) {
  ------------------
  |  Branch (712:14): [True: 0, False: 91]
  |  Branch (712:30): [True: 0, False: 0]
  ------------------
  713|      4|        ReportError("aiTexture::achFormatHint contains non-lowercase letters");
  714|      4|    }
  715|     95|}
_ZN6Assimp17ValidateDSProcess8ValidateEPK11aiAnimationPK10aiNodeAnim:
  719|    106|        const aiNodeAnim *pNodeAnim) {
  720|    106|    Validate(&pNodeAnim->mNodeName);
  721|       |
  722|    106|    if (!pNodeAnim->mNumPositionKeys && !pNodeAnim->mScalingKeys && !pNodeAnim->mNumRotationKeys) {
  ------------------
  |  Branch (722:9): [True: 58, False: 48]
  |  Branch (722:41): [True: 58, False: 0]
  |  Branch (722:69): [True: 3, False: 55]
  ------------------
  723|      3|        ReportError("Empty node animation channel");
  724|      3|    }
  725|       |    // otherwise check whether one of the keys exceeds the total duration of the animation
  726|    106|    if (pNodeAnim->mNumPositionKeys) {
  ------------------
  |  Branch (726:9): [True: 48, False: 58]
  ------------------
  727|     48|        if (!pNodeAnim->mPositionKeys) {
  ------------------
  |  Branch (727:13): [True: 0, False: 48]
  ------------------
  728|      0|            ReportError("aiNodeAnim::mPositionKeys is nullptr (aiNodeAnim::mNumPositionKeys is %i)",
  729|      0|                    pNodeAnim->mNumPositionKeys);
  730|      0|        }
  731|     48|        double dLast = -10e10;
  732|    337|        for (unsigned int i = 0; i < pNodeAnim->mNumPositionKeys; ++i) {
  ------------------
  |  Branch (732:34): [True: 289, False: 48]
  ------------------
  733|       |            // ScenePreprocessor will compute the duration if still the default value
  734|       |            // (Aramis) Add small epsilon, comparison tended to fail if max_time == duration,
  735|       |            //  seems to be due the compilers register usage/width.
  736|    289|            if (pAnimation->mDuration > 0. && pNodeAnim->mPositionKeys[i].mTime > pAnimation->mDuration + 0.001) {
  ------------------
  |  Branch (736:17): [True: 162, False: 127]
  |  Branch (736:47): [True: 17, False: 145]
  ------------------
  737|     17|                ReportError("aiNodeAnim::mPositionKeys[%i].mTime (%.5f) is larger "
  738|     17|                            "than aiAnimation::mDuration (which is %.5f)",
  739|     17|                        i,
  740|     17|                        (float)pNodeAnim->mPositionKeys[i].mTime,
  741|     17|                        (float)pAnimation->mDuration);
  742|     17|            }
  743|    289|            if (i && pNodeAnim->mPositionKeys[i].mTime <= dLast) {
  ------------------
  |  Branch (743:17): [True: 233, False: 56]
  |  Branch (743:22): [True: 96, False: 137]
  ------------------
  744|     96|                ReportWarning("aiNodeAnim::mPositionKeys[%i].mTime (%.5f) is smaller "
  745|     96|                              "than aiAnimation::mPositionKeys[%i] (which is %.5f)",
  746|     96|                        i,
  747|     96|                        (float)pNodeAnim->mPositionKeys[i].mTime,
  748|     96|                        i - 1, (float)dLast);
  749|     96|            }
  750|    289|            dLast = pNodeAnim->mPositionKeys[i].mTime;
  751|    289|        }
  752|     48|    }
  753|       |    // rotation keys
  754|    106|    if (pNodeAnim->mNumRotationKeys) {
  ------------------
  |  Branch (754:9): [True: 76, False: 30]
  ------------------
  755|     76|        if (!pNodeAnim->mRotationKeys) {
  ------------------
  |  Branch (755:13): [True: 0, False: 76]
  ------------------
  756|      0|            ReportError("aiNodeAnim::mRotationKeys is nullptr (aiNodeAnim::mNumRotationKeys is %i)",
  757|      0|                    pNodeAnim->mNumRotationKeys);
  758|      0|        }
  759|     76|        double dLast = -10e10;
  760|    722|        for (unsigned int i = 0; i < pNodeAnim->mNumRotationKeys; ++i) {
  ------------------
  |  Branch (760:34): [True: 646, False: 76]
  ------------------
  761|    646|            if (pAnimation->mDuration > 0. && pNodeAnim->mRotationKeys[i].mTime > pAnimation->mDuration + 0.001) {
  ------------------
  |  Branch (761:17): [True: 551, False: 95]
  |  Branch (761:47): [True: 12, False: 539]
  ------------------
  762|     12|                ReportError("aiNodeAnim::mRotationKeys[%i].mTime (%.5f) is larger "
  763|     12|                            "than aiAnimation::mDuration (which is %.5f)",
  764|     12|                        i,
  765|     12|                        (float)pNodeAnim->mRotationKeys[i].mTime,
  766|     12|                        (float)pAnimation->mDuration);
  767|     12|            }
  768|    646|            if (i && pNodeAnim->mRotationKeys[i].mTime <= dLast) {
  ------------------
  |  Branch (768:17): [True: 565, False: 81]
  |  Branch (768:22): [True: 68, False: 497]
  ------------------
  769|     68|                ReportWarning("aiNodeAnim::mRotationKeys[%i].mTime (%.5f) is smaller "
  770|     68|                              "than aiAnimation::mRotationKeys[%i] (which is %.5f)",
  771|     68|                        i,
  772|     68|                        (float)pNodeAnim->mRotationKeys[i].mTime,
  773|     68|                        i - 1, (float)dLast);
  774|     68|            }
  775|    646|            dLast = pNodeAnim->mRotationKeys[i].mTime;
  776|    646|        }
  777|     76|    }
  778|       |    // scaling keys
  779|    106|    if (pNodeAnim->mNumScalingKeys) {
  ------------------
  |  Branch (779:9): [True: 0, False: 106]
  ------------------
  780|      0|        if (!pNodeAnim->mScalingKeys) {
  ------------------
  |  Branch (780:13): [True: 0, False: 0]
  ------------------
  781|      0|            ReportError("aiNodeAnim::mScalingKeys is nullptr (aiNodeAnim::mNumScalingKeys is %i)",
  782|      0|                    pNodeAnim->mNumScalingKeys);
  783|      0|        }
  784|      0|        double dLast = -10e10;
  785|      0|        for (unsigned int i = 0; i < pNodeAnim->mNumScalingKeys; ++i) {
  ------------------
  |  Branch (785:34): [True: 0, False: 0]
  ------------------
  786|      0|            if (pAnimation->mDuration > 0. && pNodeAnim->mScalingKeys[i].mTime > pAnimation->mDuration + 0.001) {
  ------------------
  |  Branch (786:17): [True: 0, False: 0]
  |  Branch (786:47): [True: 0, False: 0]
  ------------------
  787|      0|                ReportError("aiNodeAnim::mScalingKeys[%i].mTime (%.5f) is larger "
  788|      0|                            "than aiAnimation::mDuration (which is %.5f)",
  789|      0|                        i,
  790|      0|                        (float)pNodeAnim->mScalingKeys[i].mTime,
  791|      0|                        (float)pAnimation->mDuration);
  792|      0|            }
  793|      0|            if (i && pNodeAnim->mScalingKeys[i].mTime <= dLast) {
  ------------------
  |  Branch (793:17): [True: 0, False: 0]
  |  Branch (793:22): [True: 0, False: 0]
  ------------------
  794|      0|                ReportWarning("aiNodeAnim::mScalingKeys[%i].mTime (%.5f) is smaller "
  795|      0|                              "than aiAnimation::mScalingKeys[%i] (which is %.5f)",
  796|      0|                        i,
  797|      0|                        (float)pNodeAnim->mScalingKeys[i].mTime,
  798|      0|                        i - 1, (float)dLast);
  799|      0|            }
  800|      0|            dLast = pNodeAnim->mScalingKeys[i].mTime;
  801|      0|        }
  802|      0|    }
  803|       |
  804|    106|    if (!pNodeAnim->mNumScalingKeys && !pNodeAnim->mNumRotationKeys &&
  ------------------
  |  Branch (804:9): [True: 74, False: 32]
  |  Branch (804:40): [True: 10, False: 64]
  ------------------
  805|     10|            !pNodeAnim->mNumPositionKeys) {
  ------------------
  |  Branch (805:13): [True: 0, False: 10]
  ------------------
  806|      0|        ReportError("A node animation channel must have at least one subtrack");
  807|      0|    }
  808|    106|}
_ZN6Assimp17ValidateDSProcess8ValidateEPK6aiNode:
  850|  7.43k|void ValidateDSProcess::Validate(const aiNode *pNode) {
  851|  7.43k|    if (!pNode) {
  ------------------
  |  Branch (851:9): [True: 291, False: 7.14k]
  ------------------
  852|    291|        ReportError("A node of the scene-graph is nullptr");
  853|    291|    }
  854|       |    // Validate node name string first so that it's safe to use in below expressions
  855|  7.43k|    this->Validate(&pNode->mName);
  856|  7.43k|    const char *nodeName = (&pNode->mName)->C_Str();
  857|  7.43k|    if (pNode != mScene->mRootNode && !pNode->mParent) {
  ------------------
  |  Branch (857:9): [True: 5.40k, False: 2.02k]
  |  Branch (857:39): [True: 0, False: 5.40k]
  ------------------
  858|      0|        ReportError("Non-root node %s lacks a valid parent (aiNode::mParent is nullptr) ", nodeName);
  859|      0|    }
  860|       |
  861|       |    // validate all meshes
  862|  7.43k|    if (pNode->mNumMeshes) {
  ------------------
  |  Branch (862:9): [True: 1.69k, False: 5.74k]
  ------------------
  863|  1.69k|        if (!pNode->mMeshes) {
  ------------------
  |  Branch (863:13): [True: 0, False: 1.69k]
  ------------------
  864|      0|            ReportError("aiNode::mMeshes is nullptr for node %s (aiNode::mNumMeshes is %i)",
  865|      0|                    nodeName, pNode->mNumMeshes);
  866|      0|        }
  867|  1.69k|        std::vector<bool> abHadMesh;
  868|  1.69k|        abHadMesh.resize(mScene->mNumMeshes, false);
  869|  3.40k|        for (unsigned int i = 0; i < pNode->mNumMeshes; ++i) {
  ------------------
  |  Branch (869:34): [True: 1.70k, False: 1.69k]
  ------------------
  870|  1.70k|            if (pNode->mMeshes[i] >= mScene->mNumMeshes) {
  ------------------
  |  Branch (870:17): [True: 0, False: 1.70k]
  ------------------
  871|      0|                ReportError("aiNode::mMeshes[%i] is out of range for node %s (maximum is %i)",
  872|      0|                        pNode->mMeshes[i], nodeName, mScene->mNumMeshes - 1);
  873|      0|            }
  874|  1.70k|            if (abHadMesh[pNode->mMeshes[i]]) {
  ------------------
  |  Branch (874:17): [True: 0, False: 1.70k]
  ------------------
  875|      0|                ReportError("aiNode::mMeshes[%i] is already referenced by this node %s (value: %i)",
  876|      0|                        i, nodeName, pNode->mMeshes[i]);
  877|      0|            }
  878|  1.70k|            abHadMesh[pNode->mMeshes[i]] = true;
  879|  1.70k|        }
  880|  1.69k|    }
  881|  7.43k|    if (pNode->mNumChildren) {
  ------------------
  |  Branch (881:9): [True: 3.35k, False: 4.08k]
  ------------------
  882|  3.35k|        if (!pNode->mChildren) {
  ------------------
  |  Branch (882:13): [True: 0, False: 3.35k]
  ------------------
  883|      0|            ReportError("aiNode::mChildren is nullptr for node %s (aiNode::mNumChildren is %i)",
  884|      0|                    nodeName, pNode->mNumChildren);
  885|      0|        }
  886|  8.76k|        for (unsigned int i = 0; i < pNode->mNumChildren; ++i) {
  ------------------
  |  Branch (886:34): [True: 5.40k, False: 3.35k]
  ------------------
  887|  5.40k|            const aiNode *pChild = pNode->mChildren[i];
  888|  5.40k|            Validate(pChild);
  889|  5.40k|            if (pChild->mParent != pNode) {
  ------------------
  |  Branch (889:17): [True: 0, False: 5.40k]
  ------------------
  890|      0|                const char *parentName = (pChild->mParent != nullptr) ? pChild->mParent->mName.C_Str() : "null";
  ------------------
  |  Branch (890:42): [True: 0, False: 0]
  ------------------
  891|      0|                ReportError("aiNode \"%s\" child %i \"%s\" parent is someone else: \"%s\"", pNode->mName.C_Str(), i, pChild->mName.C_Str(), parentName);
  892|      0|            }
  893|  5.40k|        }
  894|  4.08k|    } else if (pNode->mChildren) {
  ------------------
  |  Branch (894:16): [True: 0, False: 4.08k]
  ------------------
  895|      0|        ReportError("aiNode::mChildren is not nullptr for empty node %s (aiNode::mNumChildren is %i)",
  896|      0|                nodeName, pNode->mNumChildren);
  897|      0|    }
  898|  7.43k|}
_ZN6Assimp17ValidateDSProcess8ValidateEPK8aiString:
  901|  10.6k|void ValidateDSProcess::Validate(const aiString *pString) {
  902|  10.6k|    if (pString->length > AI_MAXLEN) {
  ------------------
  |  Branch (902:9): [True: 0, False: 10.6k]
  ------------------
  903|      0|        ReportError("aiString::length is too large (%u, maximum is %lu)",
  904|      0|                pString->length, AI_MAXLEN);
  905|      0|    }
  906|  10.6k|    const char *sz = pString->data;
  907|   111k|    while (true) {
  ------------------
  |  Branch (907:12): [True: 111k, Folded]
  ------------------
  908|   111k|        if ('\0' == *sz) {
  ------------------
  |  Branch (908:13): [True: 10.6k, False: 100k]
  ------------------
  909|  10.6k|            if (pString->length != (unsigned int)(sz - pString->data)) {
  ------------------
  |  Branch (909:17): [True: 0, False: 10.6k]
  ------------------
  910|      0|                ReportError("aiString::data is invalid: the terminal zero is at a wrong offset");
  911|      0|            }
  912|  10.6k|            break;
  913|   100k|        } else if (sz >= &pString->data[AI_MAXLEN]) {
  ------------------
  |  Branch (913:20): [True: 0, False: 100k]
  ------------------
  914|      0|            ReportError("aiString::data is invalid. There is no terminal character");
  915|      0|        }
  916|   100k|        ++sz;
  917|   100k|    }
  918|  10.6k|}
_ZN6Assimp17ValidateDSProcess12DoValidationI6aiMeshEEvPPT_jPKcS7_:
  109|  1.33k|inline void ValidateDSProcess::DoValidation(T **parray, unsigned int size, const char *firstName, const char *secondName) {
  110|       |    // validate all entries
  111|  1.33k|    if (size == 0) {
  ------------------
  |  Branch (111:9): [True: 0, False: 1.33k]
  ------------------
  112|      0|        return;
  113|      0|    }
  114|       |
  115|  1.33k|    if (!parray) {
  ------------------
  |  Branch (115:9): [True: 0, False: 1.33k]
  ------------------
  116|      0|        ReportError("aiScene::%s is nullptr (aiScene::%s is %i)",
  117|      0|                firstName, secondName, size);
  118|      0|    }
  119|       |
  120|  2.89k|    for (unsigned int i = 0; i < size; ++i) {
  ------------------
  |  Branch (120:30): [True: 1.55k, False: 1.33k]
  ------------------
  121|  1.55k|        if (!parray[i]) {
  ------------------
  |  Branch (121:13): [True: 0, False: 1.55k]
  ------------------
  122|      0|            ReportError("aiScene::%s[%i] is nullptr (aiScene::%s is %i)",
  123|      0|                    firstName, i, secondName, size);
  124|      0|        }
  125|  1.55k|        Validate(parray[i]);
  126|  1.55k|    }
  127|  1.33k|}
_ZN6Assimp17ValidateDSProcess12DoValidationI11aiAnimationEEvPPT_jPKcS7_:
  109|    178|inline void ValidateDSProcess::DoValidation(T **parray, unsigned int size, const char *firstName, const char *secondName) {
  110|       |    // validate all entries
  111|    178|    if (size == 0) {
  ------------------
  |  Branch (111:9): [True: 0, False: 178]
  ------------------
  112|      0|        return;
  113|      0|    }
  114|       |
  115|    178|    if (!parray) {
  ------------------
  |  Branch (115:9): [True: 0, False: 178]
  ------------------
  116|      0|        ReportError("aiScene::%s is nullptr (aiScene::%s is %i)",
  117|      0|                firstName, secondName, size);
  118|      0|    }
  119|       |
  120|    356|    for (unsigned int i = 0; i < size; ++i) {
  ------------------
  |  Branch (120:30): [True: 178, False: 178]
  ------------------
  121|    178|        if (!parray[i]) {
  ------------------
  |  Branch (121:13): [True: 0, False: 178]
  ------------------
  122|      0|            ReportError("aiScene::%s[%i] is nullptr (aiScene::%s is %i)",
  123|      0|                    firstName, i, secondName, size);
  124|      0|        }
  125|    178|        Validate(parray[i]);
  126|    178|    }
  127|    178|}
_ZN6Assimp17ValidateDSProcess25DoValidationWithNameCheckI8aiCameraEEvPPT_jPKcS7_:
  163|     35|        const char *secondName) {
  164|       |    // validate all entries
  165|     35|    DoValidationEx(array, size, firstName, secondName);
  166|       |
  167|     74|    for (unsigned int i = 0; i < size; ++i) {
  ------------------
  |  Branch (167:30): [True: 39, False: 35]
  ------------------
  168|     39|        int res = HasNameMatch(array[i]->mName, mScene->mRootNode);
  169|     39|        if (0 == res) {
  ------------------
  |  Branch (169:13): [True: 0, False: 39]
  ------------------
  170|      0|            const std::string name = static_cast<char *>(array[i]->mName.data);
  171|      0|            ReportError("aiScene::%s[%i] has no corresponding node in the scene graph (%s)",
  172|      0|                    firstName, i, name.c_str());
  173|     39|        } else if (1 != res) {
  ------------------
  |  Branch (173:20): [True: 7, False: 32]
  ------------------
  174|      7|            const std::string name = static_cast<char *>(array[i]->mName.data);
  175|      7|            ReportError("aiScene::%s[%i]: there are more than one nodes with %s as name",
  176|      7|                    firstName, i, name.c_str());
  177|      7|        }
  178|     39|    }
  179|     35|}
_ZN6Assimp17ValidateDSProcess14DoValidationExI8aiCameraEEvPPT_jPKcS7_:
  132|     35|        const char *firstName, const char *secondName) {
  133|       |    // validate all entries
  134|     35|    if (size == 0) {
  ------------------
  |  Branch (134:9): [True: 0, False: 35]
  ------------------
  135|      0|        return;
  136|      0|    }
  137|       |
  138|     35|    if (!parray) {
  ------------------
  |  Branch (138:9): [True: 0, False: 35]
  ------------------
  139|      0|        ReportError("aiScene::%s is nullptr (aiScene::%s is %i)",
  140|      0|                firstName, secondName, size);
  141|      0|    }
  142|     84|    for (unsigned int i = 0; i < size; ++i) {
  ------------------
  |  Branch (142:30): [True: 49, False: 35]
  ------------------
  143|     49|        if (!parray[i]) {
  ------------------
  |  Branch (143:13): [True: 0, False: 49]
  ------------------
  144|      0|            ReportError("aiScene::%s[%u] is nullptr (aiScene::%s is %u)",
  145|      0|                    firstName, i, secondName, size);
  146|      0|        }
  147|     49|        Validate(parray[i]);
  148|       |
  149|       |        // check whether there are duplicate names
  150|     63|        for (unsigned int a = i + 1; a < size; ++a) {
  ------------------
  |  Branch (150:38): [True: 14, False: 49]
  ------------------
  151|     14|            if (parray[i]->mName == parray[a]->mName) {
  ------------------
  |  Branch (151:17): [True: 0, False: 14]
  ------------------
  152|      0|                ReportError("aiScene::%s[%u] has the same name as "
  153|      0|                            "aiScene::%s[%u]",
  154|      0|                        firstName, i, secondName, a);
  155|      0|            }
  156|     14|        }
  157|     49|    }
  158|     35|}
_Z12HasNameMatchRK8aiStringP6aiNode:
   99|    147|inline int HasNameMatch(const aiString &in, aiNode *node) {
  100|    147|    int result = (node->mName == in ? 1 : 0);
  ------------------
  |  Branch (100:19): [True: 46, False: 101]
  ------------------
  101|    255|    for (unsigned int i = 0; i < node->mNumChildren; ++i) {
  ------------------
  |  Branch (101:30): [True: 108, False: 147]
  ------------------
  102|    108|        result += HasNameMatch(in, node->mChildren[i]);
  103|    108|    }
  104|    147|    return result;
  105|    147|}
_ZN6Assimp17ValidateDSProcess12DoValidationI9aiTextureEEvPPT_jPKcS7_:
  109|     95|inline void ValidateDSProcess::DoValidation(T **parray, unsigned int size, const char *firstName, const char *secondName) {
  110|       |    // validate all entries
  111|     95|    if (size == 0) {
  ------------------
  |  Branch (111:9): [True: 0, False: 95]
  ------------------
  112|      0|        return;
  113|      0|    }
  114|       |
  115|     95|    if (!parray) {
  ------------------
  |  Branch (115:9): [True: 0, False: 95]
  ------------------
  116|      0|        ReportError("aiScene::%s is nullptr (aiScene::%s is %i)",
  117|      0|                firstName, secondName, size);
  118|      0|    }
  119|       |
  120|    190|    for (unsigned int i = 0; i < size; ++i) {
  ------------------
  |  Branch (120:30): [True: 95, False: 95]
  ------------------
  121|     95|        if (!parray[i]) {
  ------------------
  |  Branch (121:13): [True: 0, False: 95]
  ------------------
  122|      0|            ReportError("aiScene::%s[%i] is nullptr (aiScene::%s is %i)",
  123|      0|                    firstName, i, secondName, size);
  124|      0|        }
  125|     95|        Validate(parray[i]);
  126|     95|    }
  127|     95|}
_ZN6Assimp17ValidateDSProcess12DoValidationI10aiMaterialEEvPPT_jPKcS7_:
  109|  1.54k|inline void ValidateDSProcess::DoValidation(T **parray, unsigned int size, const char *firstName, const char *secondName) {
  110|       |    // validate all entries
  111|  1.54k|    if (size == 0) {
  ------------------
  |  Branch (111:9): [True: 0, False: 1.54k]
  ------------------
  112|      0|        return;
  113|      0|    }
  114|       |
  115|  1.54k|    if (!parray) {
  ------------------
  |  Branch (115:9): [True: 0, False: 1.54k]
  ------------------
  116|      0|        ReportError("aiScene::%s is nullptr (aiScene::%s is %i)",
  117|      0|                firstName, secondName, size);
  118|      0|    }
  119|       |
  120|  4.16k|    for (unsigned int i = 0; i < size; ++i) {
  ------------------
  |  Branch (120:30): [True: 2.62k, False: 1.54k]
  ------------------
  121|  2.62k|        if (!parray[i]) {
  ------------------
  |  Branch (121:13): [True: 0, False: 2.62k]
  ------------------
  122|      0|            ReportError("aiScene::%s[%i] is nullptr (aiScene::%s is %i)",
  123|      0|                    firstName, i, secondName, size);
  124|      0|        }
  125|  2.62k|        Validate(parray[i]);
  126|  2.62k|    }
  127|  1.54k|}

_ZN10ODDLParser5Value8IteratorC2EPS0_:
   39|      2|        m_start(start),
   40|      2|        m_current(start) {
   41|       |    // empty
   42|      2|}

_ZN4pugi13xml_attributeC2Ev:
 5234|      2|	PUGI_IMPL_FN xml_attribute::xml_attribute(): _attr(nullptr)
 5235|      2|	{
 5236|      2|	}
_ZN4pugi8xml_nodeC2Ev:
 5593|  10.2k|	PUGI_IMPL_FN xml_node::xml_node(): _root(nullptr)
 5594|  10.2k|	{
 5595|  10.2k|	}
_ZN4pugi10xpath_nodeC2Ev:
12714|      2|	{
12715|      2|	}
_ZN4pugi14xpath_node_setC2Ev:
12821|      2|	PUGI_IMPL_FN xpath_node_set::xpath_node_set(): _type(type_unsorted), _begin(_storage), _end(_storage)
12822|      2|	{
12823|      2|	}

_ZN9rapidjson12CrtAllocator6MallocEm:
   86|  27.1k|    void* Malloc(size_t size) { 
   87|  27.1k|        if (size) //  behavior of malloc(0) is implementation defined.
  ------------------
  |  Branch (87:13): [True: 27.1k, False: 0]
  ------------------
   88|  27.1k|            return RAPIDJSON_MALLOC(size);
  ------------------
  |  |  696|  27.1k|#define RAPIDJSON_MALLOC(size) std::malloc(size)
  ------------------
   89|      0|        else
   90|      0|            return NULL; // standardize to returning NULL.
   91|  27.1k|    }
_ZN9rapidjson12CrtAllocator7ReallocEPvmm:
   92|  27.9k|    void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
   93|  27.9k|        (void)originalSize;
   94|  27.9k|        if (newSize == 0) {
  ------------------
  |  Branch (94:13): [True: 0, False: 27.9k]
  ------------------
   95|      0|            RAPIDJSON_FREE(originalPtr);
  ------------------
  |  |  704|      0|#define RAPIDJSON_FREE(ptr) std::free(ptr)
  ------------------
   96|      0|            return NULL;
   97|      0|        }
   98|  27.9k|        return RAPIDJSON_REALLOC(originalPtr, newSize);
  ------------------
  |  |  700|  27.9k|#define RAPIDJSON_REALLOC(ptr, new_size) std::realloc(ptr, new_size)
  ------------------
   99|  27.9k|    }
_ZN9rapidjson12CrtAllocator4FreeEPv:
  100|  69.2k|    static void Free(void *ptr) RAPIDJSON_NOEXCEPT { RAPIDJSON_FREE(ptr); }
  ------------------
  |  |  704|  69.2k|#define RAPIDJSON_FREE(ptr) std::free(ptr)
  ------------------
_ZN9rapidjson19MemoryPoolAllocatorINS_12CrtAllocatorEE12GetChunkHeadEPNS2_10SharedDataE:
  151|  14.0k|    {
  152|  14.0k|        return reinterpret_cast<ChunkHeader*>(reinterpret_cast<uint8_t*>(shared) + SIZEOF_SHARED_DATA);
  153|  14.0k|    }
_ZN9rapidjson19MemoryPoolAllocatorINS_12CrtAllocatorEE5ClearEv:
  277|  14.0k|    void Clear() RAPIDJSON_NOEXCEPT {
  278|  14.0k|        RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
  ------------------
  |  |  687|  14.0k|#define RAPIDJSON_NOEXCEPT_ASSERT(x) RAPIDJSON_ASSERT(x)
  |  |  ------------------
  |  |  |  |  437|  14.0k|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  ------------------
  ------------------
  |  Branch (278:9): [True: 14.0k, False: 0]
  ------------------
  279|  27.1k|        for (;;) {
  280|  27.1k|            ChunkHeader* c = shared_->chunkHead;
  281|  27.1k|            if (!c->next) {
  ------------------
  |  Branch (281:17): [True: 14.0k, False: 13.1k]
  ------------------
  282|  14.0k|                break;
  283|  14.0k|            }
  284|  13.1k|            shared_->chunkHead = c->next;
  285|  13.1k|            baseAllocator_->Free(c);
  286|  13.1k|        }
  287|  14.0k|        shared_->chunkHead->size = 0;
  288|  14.0k|    }
_ZN9rapidjson19MemoryPoolAllocatorINS_12CrtAllocatorEE6MallocEm:
  321|  1.41M|    void* Malloc(size_t size) {
  322|  1.41M|        RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
  ------------------
  |  |  687|  1.41M|#define RAPIDJSON_NOEXCEPT_ASSERT(x) RAPIDJSON_ASSERT(x)
  |  |  ------------------
  |  |  |  |  437|  1.41M|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  ------------------
  ------------------
  |  Branch (322:9): [True: 1.41M, False: 0]
  ------------------
  323|  1.41M|        if (!size)
  ------------------
  |  Branch (323:13): [True: 0, False: 1.41M]
  ------------------
  324|      0|            return NULL;
  325|       |
  326|  1.41M|        size = RAPIDJSON_ALIGN(size);
  ------------------
  |  |  307|  1.41M|#define RAPIDJSON_ALIGN(x) (((x) + static_cast<size_t>(7u)) & ~static_cast<size_t>(7u))
  ------------------
  327|  1.41M|        if (RAPIDJSON_UNLIKELY(shared_->chunkHead->size + size > shared_->chunkHead->capacity))
  ------------------
  |  |  505|  1.41M|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 13.1k, False: 1.40M]
  |  |  ------------------
  ------------------
  328|  13.1k|            if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size))
  ------------------
  |  Branch (328:17): [True: 0, False: 13.1k]
  |  Branch (328:27): [True: 12.8k, False: 335]
  ------------------
  329|      0|                return NULL;
  330|       |
  331|  1.41M|        void *buffer = GetChunkBuffer(shared_) + shared_->chunkHead->size;
  332|  1.41M|        shared_->chunkHead->size += size;
  333|  1.41M|        return buffer;
  334|  1.41M|    }
_ZN9rapidjson19MemoryPoolAllocatorINS_12CrtAllocatorEE8AddChunkEm:
  390|  13.1k|    bool AddChunk(size_t capacity) {
  391|  13.1k|        if (!baseAllocator_)
  ------------------
  |  Branch (391:13): [True: 0, False: 13.1k]
  ------------------
  392|      0|            shared_->ownBaseAllocator = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator)();
  ------------------
  |  |  712|      0|#define RAPIDJSON_NEW(TypeName) new TypeName
  ------------------
  393|  13.1k|        if (ChunkHeader* chunk = static_cast<ChunkHeader*>(baseAllocator_->Malloc(SIZEOF_CHUNK_HEADER + capacity))) {
  ------------------
  |  Branch (393:26): [True: 13.1k, False: 0]
  ------------------
  394|  13.1k|            chunk->capacity = capacity;
  395|  13.1k|            chunk->size = 0;
  396|  13.1k|            chunk->next = shared_->chunkHead;
  397|  13.1k|            shared_->chunkHead = chunk;
  398|  13.1k|            return true;
  399|  13.1k|        }
  400|      0|        else
  401|      0|            return false;
  402|  13.1k|    }
_ZN9rapidjson19MemoryPoolAllocatorINS_12CrtAllocatorEE14GetChunkBufferEPNS2_10SharedDataE:
  155|  1.41M|    {
  156|  1.41M|        return reinterpret_cast<uint8_t*>(shared->chunkHead) + SIZEOF_CHUNK_HEADER;
  157|  1.41M|    }
_ZN9rapidjson6MallocINS_13GenericMemberINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEEES6_EEPT_RT0_m:
  443|   466k|{
  444|       |    return Realloc<T, A>(a, NULL, 0, n);
  445|   466k|}
_ZN9rapidjson7ReallocINS_13GenericMemberINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEEES6_EEPT_RT0_S9_mm:
  436|   466k|{
  437|   466k|    RAPIDJSON_NOEXCEPT_ASSERT(old_n <= (std::numeric_limits<size_t>::max)() / sizeof(T) && new_n <= (std::numeric_limits<size_t>::max)() / sizeof(T));
  ------------------
  |  |  687|   466k|#define RAPIDJSON_NOEXCEPT_ASSERT(x) RAPIDJSON_ASSERT(x)
  |  |  ------------------
  |  |  |  |  437|   466k|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  ------------------
  ------------------
  |  Branch (437:5): [True: 466k, False: 0]
  |  Branch (437:5): [True: 466k, False: 0]
  |  Branch (437:5): [True: 466k, False: 0]
  ------------------
  438|   466k|    return static_cast<T*>(a.Realloc(old_p, old_n * sizeof(T), new_n * sizeof(T)));
  439|   466k|}
_ZN9rapidjson19MemoryPoolAllocatorINS_12CrtAllocatorEE7ReallocEPvmm:
  337|   466k|    void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
  338|   466k|        if (originalPtr == 0)
  ------------------
  |  Branch (338:13): [True: 466k, False: 0]
  ------------------
  339|   466k|            return Malloc(newSize);
  340|       |
  341|      0|        RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
  ------------------
  |  |  687|      0|#define RAPIDJSON_NOEXCEPT_ASSERT(x) RAPIDJSON_ASSERT(x)
  |  |  ------------------
  |  |  |  |  437|      0|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  ------------------
  ------------------
  |  Branch (341:9): [True: 0, False: 0]
  ------------------
  342|      0|        if (newSize == 0)
  ------------------
  |  Branch (342:13): [True: 0, False: 0]
  ------------------
  343|      0|            return NULL;
  344|       |
  345|      0|        originalSize = RAPIDJSON_ALIGN(originalSize);
  ------------------
  |  |  307|      0|#define RAPIDJSON_ALIGN(x) (((x) + static_cast<size_t>(7u)) & ~static_cast<size_t>(7u))
  ------------------
  346|      0|        newSize = RAPIDJSON_ALIGN(newSize);
  ------------------
  |  |  307|      0|#define RAPIDJSON_ALIGN(x) (((x) + static_cast<size_t>(7u)) & ~static_cast<size_t>(7u))
  ------------------
  347|       |
  348|       |        // Do not shrink if new size is smaller than original
  349|      0|        if (originalSize >= newSize)
  ------------------
  |  Branch (349:13): [True: 0, False: 0]
  ------------------
  350|      0|            return originalPtr;
  351|       |
  352|       |        // Simply expand it if it is the last allocation and there is sufficient space
  353|      0|        if (originalPtr == GetChunkBuffer(shared_) + shared_->chunkHead->size - originalSize) {
  ------------------
  |  Branch (353:13): [True: 0, False: 0]
  ------------------
  354|      0|            size_t increment = static_cast<size_t>(newSize - originalSize);
  355|      0|            if (shared_->chunkHead->size + increment <= shared_->chunkHead->capacity) {
  ------------------
  |  Branch (355:17): [True: 0, False: 0]
  ------------------
  356|      0|                shared_->chunkHead->size += increment;
  357|      0|                return originalPtr;
  358|      0|            }
  359|      0|        }
  360|       |
  361|       |        // Realloc process: allocate and copy memory, do not free original buffer.
  362|      0|        if (void* newBuffer = Malloc(newSize)) {
  ------------------
  |  Branch (362:19): [True: 0, False: 0]
  ------------------
  363|      0|            if (originalSize)
  ------------------
  |  Branch (363:17): [True: 0, False: 0]
  ------------------
  364|      0|                std::memcpy(newBuffer, originalPtr, originalSize);
  365|      0|            return newBuffer;
  366|      0|        }
  367|      0|        else
  368|      0|            return NULL;
  369|      0|    }
_ZN9rapidjson19MemoryPoolAllocatorINS_12CrtAllocatorEEC2EmPS1_:
  171|  14.0k|        chunk_capacity_(chunkSize),
  172|  14.0k|        baseAllocator_(baseAllocator ? baseAllocator : RAPIDJSON_NEW(BaseAllocator)()),
  ------------------
  |  |  712|  14.0k|#define RAPIDJSON_NEW(TypeName) new TypeName
  ------------------
  |  Branch (172:24): [True: 0, False: 14.0k]
  ------------------
  173|  14.0k|        shared_(static_cast<SharedData*>(baseAllocator_ ? baseAllocator_->Malloc(SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER) : 0))
  ------------------
  |  Branch (173:42): [True: 14.0k, False: 0]
  ------------------
  174|  14.0k|    {
  175|  14.0k|        RAPIDJSON_ASSERT(baseAllocator_ != 0);
  ------------------
  |  |  437|  14.0k|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (175:9): [True: 14.0k, False: 0]
  ------------------
  176|  14.0k|        RAPIDJSON_ASSERT(shared_ != 0);
  ------------------
  |  |  437|  14.0k|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (176:9): [True: 14.0k, False: 0]
  ------------------
  177|  14.0k|        if (baseAllocator) {
  ------------------
  |  Branch (177:13): [True: 0, False: 14.0k]
  ------------------
  178|      0|            shared_->ownBaseAllocator = 0;
  179|      0|        }
  180|  14.0k|        else {
  181|  14.0k|            shared_->ownBaseAllocator = baseAllocator_;
  182|  14.0k|        }
  183|  14.0k|        shared_->chunkHead = GetChunkHead(shared_);
  184|  14.0k|        shared_->chunkHead->capacity = 0;
  185|  14.0k|        shared_->chunkHead->size = 0;
  186|  14.0k|        shared_->chunkHead->next = 0;
  187|  14.0k|        shared_->ownBuffer = true;
  188|  14.0k|        shared_->refcount = 1;
  189|  14.0k|    }
_ZN9rapidjson19MemoryPoolAllocatorINS_12CrtAllocatorEED2Ev:
  259|  14.0k|    ~MemoryPoolAllocator() RAPIDJSON_NOEXCEPT {
  260|  14.0k|        if (!shared_) {
  ------------------
  |  Branch (260:13): [True: 0, False: 14.0k]
  ------------------
  261|       |            // do nothing if moved
  262|      0|            return;
  263|      0|        }
  264|  14.0k|        if (shared_->refcount > 1) {
  ------------------
  |  Branch (264:13): [True: 0, False: 14.0k]
  ------------------
  265|      0|            --shared_->refcount;
  266|      0|            return;
  267|      0|        }
  268|  14.0k|        Clear();
  269|  14.0k|        BaseAllocator *a = shared_->ownBaseAllocator;
  270|  14.0k|        if (shared_->ownBuffer) {
  ------------------
  |  Branch (270:13): [True: 14.0k, False: 0]
  ------------------
  271|  14.0k|            baseAllocator_->Free(shared_);
  272|  14.0k|        }
  273|  14.0k|        RAPIDJSON_DELETE(a);
  ------------------
  |  |  716|  14.0k|#define RAPIDJSON_DELETE(x) delete x
  ------------------
  274|  14.0k|    }

_ZNK9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE6IsBoolEv:
 1115|  14.8k|    bool IsBool()   const { return (data_.f.flags & kBoolFlag) != 0; }
_ZNK9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE7GetBoolEv:
 1176|  7.41k|    bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return data_.f.flags == kTrueFlag; }
  ------------------
  |  |  437|  7.41k|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (1176:28): [True: 7.41k, False: 0]
  ------------------
_ZNK9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE8IsNumberEv:
 1118|   385k|    bool IsNumber() const { return (data_.f.flags & kNumberFlag) != 0; }
_ZNK9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE9GetDoubleEv:
 1825|   183k|    double GetDouble() const {
 1826|   183k|        RAPIDJSON_ASSERT(IsNumber());
  ------------------
  |  |  437|   183k|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (1826:9): [True: 183k, False: 0]
  ------------------
 1827|   183k|        if ((data_.f.flags & kDoubleFlag) != 0)                return data_.n.d;   // exact type, no conversion.
  ------------------
  |  Branch (1827:13): [True: 126k, False: 56.1k]
  ------------------
 1828|  56.1k|        if ((data_.f.flags & kIntFlag) != 0)                   return data_.n.i.i; // int -> double
  ------------------
  |  Branch (1828:13): [True: 55.9k, False: 162]
  ------------------
 1829|    162|        if ((data_.f.flags & kUintFlag) != 0)                  return data_.n.u.u; // unsigned -> double
  ------------------
  |  Branch (1829:13): [True: 15, False: 147]
  ------------------
 1830|    147|        if ((data_.f.flags & kInt64Flag) != 0)                 return static_cast<double>(data_.n.i64); // int64_t -> double (may lose precision)
  ------------------
  |  Branch (1830:13): [True: 134, False: 13]
  ------------------
 1831|     13|        RAPIDJSON_ASSERT((data_.f.flags & kUint64Flag) != 0);  return static_cast<double>(data_.n.u64); // uint64_t -> double (may lose precision)
  ------------------
  |  |  437|     13|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (1831:9): [True: 13, False: 0]
  ------------------
 1832|     13|    }
_ZNK9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE8IsStringEv:
 1124|  21.0M|    bool IsString() const { return (data_.f.flags & kStringFlag) != 0; }
_ZNK9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE9GetStringEv:
 1853|  1.15M|    const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return DataString(data_); }
  ------------------
  |  |  437|  1.15M|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (1853:35): [True: 1.15M, False: 0]
  ------------------
_ZN9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE10DataStringERKNS6_4DataE:
 2107|  1.15M|    static RAPIDJSON_FORCEINLINE const Ch* DataString(const Data& data) {
 2108|  1.15M|        return (data.f.flags & kInlineStrFlag) ? data.ss.str : RAPIDJSON_GETPOINTER(Ch, data.s.str);
  ------------------
  |  |  347|  1.15M|#define RAPIDJSON_GETPOINTER(type, p) (reinterpret_cast<type *>(reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0x0000FFFF, 0xFFFFFFFF))))
  |  |  ------------------
  |  |  |  |  320|  1.15M|#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32))
  |  |  ------------------
  ------------------
  |  Branch (2108:16): [True: 0, False: 1.15M]
  ------------------
 2109|  1.15M|    }
_ZNK9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE15GetStringLengthEv:
 1858|  9.58M|    SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return DataStringLength(data_); }
  ------------------
  |  |  437|  9.58M|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (1858:40): [True: 9.58M, False: 0]
  ------------------
_ZN9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE16DataStringLengthERKNS6_4DataE:
 2110|  9.58M|    static RAPIDJSON_FORCEINLINE SizeType DataStringLength(const Data& data) {
 2111|  9.58M|        return (data.f.flags & kInlineStrFlag) ? data.ss.GetLength() : data.s.length;
  ------------------
  |  Branch (2111:16): [True: 0, False: 9.58M]
  ------------------
 2112|  9.58M|    }
_ZNK9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE8IsUint64Ev:
 1122|  32.6k|    bool IsUint64() const { return (data_.f.flags & kUint64Flag) != 0; }
_ZNK9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE9GetUint64Ev:
 1820|  32.4k|    uint64_t GetUint64() const  { RAPIDJSON_ASSERT(data_.f.flags & kUint64Flag); return data_.n.u64; }
  ------------------
  |  |  437|  32.4k|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (1820:35): [True: 32.4k, False: 0]
  ------------------
_ZNK9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE7IsInt64Ev:
 1121|    141|    bool IsInt64()  const { return (data_.f.flags & kInt64Flag) != 0; }
_ZNK9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE8GetInt64Ev:
 1819|     15|    int64_t GetInt64() const    { RAPIDJSON_ASSERT(data_.f.flags & kInt64Flag); return data_.n.i64; }
  ------------------
  |  |  437|     15|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (1819:35): [True: 15, False: 0]
  ------------------
_ZNK9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE8IsObjectEv:
 1116|  7.89M|    bool IsObject() const { return data_.f.flags == kObjectFlag; }
_ZN9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE10FindMemberEPKc:
 1337|   646k|    MemberIterator FindMember(const Ch* name) {
 1338|   646k|        GenericValue n(StringRef(name));
 1339|   646k|        return FindMember(n);
 1340|   646k|    }
_ZN9rapidjson9StringRefIcEENS_16GenericStringRefIT_EEPKS2_:
  454|   646k|inline GenericStringRef<CharType> StringRef(const CharType* str) {
  455|   646k|    return GenericStringRef<CharType>(str);
  456|   646k|}
_ZN9rapidjson16GenericStringRefIcE13NotNullStrLenEPKc:
  423|   646k|    SizeType NotNullStrLen(const CharType* str) {
  424|   646k|        RAPIDJSON_ASSERT(str != 0);
  ------------------
  |  |  437|   646k|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (424:9): [True: 646k, False: 0]
  ------------------
  425|   646k|        return internal::StrLen(str);
  426|   646k|    }
_ZN9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE12SetStringRawENS_16GenericStringRefIcEE:
 2435|  6.61M|    void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT {
 2436|  6.61M|        data_.f.flags = kConstStringFlag;
 2437|  6.61M|        SetStringPointer(s);
 2438|  6.61M|        data_.s.length = s.length;
 2439|  6.61M|    }
_ZN9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE16SetStringPointerEPKc:
 2115|  6.61M|    RAPIDJSON_FORCEINLINE const Ch* SetStringPointer(const Ch* str) { return RAPIDJSON_SETPOINTER(Ch, data_.s.str, str); }
  ------------------
  |  |  346|  6.61M|#define RAPIDJSON_SETPOINTER(type, p, x) (p = reinterpret_cast<type *>((reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0xFFFF0000, 0x00000000))) | reinterpret_cast<uintptr_t>(reinterpret_cast<const void*>(x))))
  |  |  ------------------
  |  |  |  |  320|  6.61M|#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32))
  |  |  ------------------
  ------------------
_ZNK9rapidjson16GenericStringRefIcEcvPKcEv:
  417|  6.61M|    operator const Ch *() const { return s; }
_ZNK9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE18GetElementsPointerEv:
 2116|   475k|    RAPIDJSON_FORCEINLINE GenericValue* GetElementsPointer() const { return RAPIDJSON_GETPOINTER(GenericValue, data_.a.elements); }
  ------------------
  |  |  347|   475k|#define RAPIDJSON_GETPOINTER(type, p) (reinterpret_cast<type *>(reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0x0000FFFF, 0xFFFFFFFF))))
  |  |  ------------------
  |  |  |  |  320|   475k|#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32))
  |  |  ------------------
  ------------------
_ZNK9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE17GetMembersPointerEv:
 2118|  6.51M|    RAPIDJSON_FORCEINLINE Member* GetMembersPointer() const { return RAPIDJSON_GETPOINTER(Member, data_.o.members); }
  ------------------
  |  |  347|  6.51M|#define RAPIDJSON_GETPOINTER(type, p) (reinterpret_cast<type *>(reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0x0000FFFF, 0xFFFFFFFF))))
  |  |  ------------------
  |  |  |  |  320|  6.51M|#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32))
  |  |  ------------------
  ------------------
_ZN9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE10FindMemberIS5_EEPNS_13GenericMemberIS2_S5_EERKNS0_IS2_T_EE:
 1358|   646k|    MemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) {
 1359|   646k|        RAPIDJSON_ASSERT(IsObject());
  ------------------
  |  |  437|   646k|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (1359:9): [True: 646k, False: 0]
  ------------------
 1360|   646k|        RAPIDJSON_ASSERT(name.IsString());
  ------------------
  |  |  437|   646k|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (1360:9): [True: 646k, False: 0]
  ------------------
 1361|   646k|        return DoFindMember(name);
 1362|   646k|    }
_ZN9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE12DoFindMemberIS5_EEPNS_13GenericMemberIS2_S5_EERKNS0_IS2_T_EE:
 2282|   646k|    MemberIterator DoFindMember(const GenericValue<Encoding, SourceAllocator>& name) {
 2283|   646k|        MemberIterator member = MemberBegin();
 2284|  5.17M|        for ( ; member != MemberEnd(); ++member)
  ------------------
  |  Branch (2284:17): [True: 4.77M, False: 395k]
  ------------------
 2285|  4.77M|            if (name.StringEqual(member->name))
  ------------------
  |  Branch (2285:17): [True: 250k, False: 4.52M]
  ------------------
 2286|   250k|                break;
 2287|   646k|        return member;
 2288|   646k|    }
_ZNK9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE11StringEqualIS5_EEbRKNS0_IS2_T_EE:
 2466|  4.77M|    bool StringEqual(const GenericValue<Encoding, SourceAllocator>& rhs) const {
 2467|  4.77M|        RAPIDJSON_ASSERT(IsString());
  ------------------
  |  |  437|  4.77M|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (2467:9): [True: 4.77M, False: 0]
  ------------------
 2468|  4.77M|        RAPIDJSON_ASSERT(rhs.IsString());
  ------------------
  |  |  437|  4.77M|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (2468:9): [True: 4.77M, False: 0]
  ------------------
 2469|       |
 2470|  4.77M|        const SizeType len1 = GetStringLength();
 2471|  4.77M|        const SizeType len2 = rhs.GetStringLength();
 2472|  4.77M|        if(len1 != len2) { return false; }
  ------------------
  |  Branch (2472:12): [True: 4.25M, False: 522k]
  ------------------
 2473|       |
 2474|   522k|        const Ch* const str1 = GetString();
 2475|   522k|        const Ch* const str2 = rhs.GetString();
 2476|   522k|        if(str1 == str2) { return true; } // fast path for constant string
  ------------------
  |  Branch (2476:12): [True: 0, False: 522k]
  ------------------
 2477|       |
 2478|   522k|        return (std::memcmp(str1, str2, sizeof(Ch) * len1) == 0);
 2479|   522k|    }
_ZN9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE9MemberEndEv:
 1277|  5.86M|    MemberIterator MemberEnd()              { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer() + data_.o.size); }
  ------------------
  |  |  437|  5.86M|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (1277:47): [True: 5.86M, False: 0]
  ------------------
_ZNK9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE6IsUintEv:
 1120|  77.2k|    bool IsUint()   const { return (data_.f.flags & kUintFlag) != 0; }
_ZNK9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE7IsArrayEv:
 1117|   768k|    bool IsArray()  const { return data_.f.flags == kArrayFlag; }
_ZN9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE11MemberBeginEv:
 1274|   655k|    MemberIterator MemberBegin()            { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer()); }
  ------------------
  |  |  437|   655k|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (1274:47): [True: 655k, False: 0]
  ------------------
_ZNK9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE4SizeEv:
 1643|   147k|    SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; }
  ------------------
  |  |  437|   147k|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (1643:29): [True: 147k, False: 0]
  ------------------
_ZN9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEEixEj:
 1668|   475k|    GenericValue& operator[](SizeType index) {
 1669|   475k|        RAPIDJSON_ASSERT(IsArray());
  ------------------
  |  |  437|   475k|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (1669:9): [True: 475k, False: 0]
  ------------------
 1670|   475k|        RAPIDJSON_ASSERT(index < data_.a.size);
  ------------------
  |  |  437|   475k|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (1670:9): [True: 475k, False: 0]
  ------------------
 1671|   475k|        return GetElementsPointer()[index];
 1672|   475k|    }
_ZNK9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE8IsDoubleEv:
 1123|    126|    bool IsDouble() const { return (data_.f.flags & kDoubleFlag) != 0; }
_ZNK9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE11MemberCountEv:
 1191|  4.81k|    SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; }
  ------------------
  |  |  437|  4.81k|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (1191:36): [True: 4.81k, False: 0]
  ------------------
_ZNK9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE7GetUintEv:
 1818|  75.9k|    unsigned GetUint() const    { RAPIDJSON_ASSERT(data_.f.flags & kUintFlag);  return data_.n.u.u;   }
  ------------------
  |  |  437|  75.9k|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (1818:35): [True: 75.9k, False: 0]
  ------------------
_ZNK9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE5IsIntEv:
 1119|  21.1k|    bool IsInt()    const { return (data_.f.flags & kIntFlag) != 0; }
_ZNK9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE6GetIntEv:
 1817|  21.0k|    int GetInt() const          { RAPIDJSON_ASSERT(data_.f.flags & kIntFlag);   return data_.n.i.i;   }
  ------------------
  |  |  437|  21.0k|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (1817:35): [True: 21.0k, False: 0]
  ------------------
_ZNK9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE8GetFloatEv:
 1837|     19|    float GetFloat() const {
 1838|     19|        return static_cast<float>(GetDouble());
 1839|     19|    }
_ZN9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE7SetNullEv:
 1169|  14.0k|    GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; }
_ZN9rapidjson15GenericDocumentINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEES4_E7DestroyEv:
 2877|  14.0k|    void Destroy() {
 2878|  14.0k|        RAPIDJSON_DELETE(ownAllocator_);
  ------------------
  |  |  716|  14.0k|#define RAPIDJSON_DELETE(x) delete x
  ------------------
 2879|  14.0k|    }
_ZN9rapidjson15GenericDocumentINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEES4_E11ParseInsituEPc:
 2694|  14.0k|    GenericDocument& ParseInsitu(Ch* str) {
 2695|  14.0k|        return ParseInsitu<kParseDefaultFlags>(str);
 2696|  14.0k|    }
_ZN9rapidjson15GenericDocumentINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEES4_E11ParseInsituILj0EEERS6_Pc:
 2685|  14.0k|    GenericDocument& ParseInsitu(Ch* str) {
 2686|  14.0k|        GenericInsituStringStream<Encoding> s(str);
 2687|  14.0k|        return ParseStream<parseFlags | kParseInsituFlag>(s);
 2688|  14.0k|    }
_ZN9rapidjson15GenericDocumentINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEES4_E11ParseStreamILj1ENS_25GenericInsituStringStreamIS2_EEEERS6_RT0_:
 2661|  14.0k|    GenericDocument& ParseStream(InputStream& is) {
 2662|  14.0k|        return ParseStream<parseFlags, Encoding, InputStream>(is);
 2663|  14.0k|    }
_ZN9rapidjson15GenericDocumentINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEES4_E11ParseStreamILj1ES2_NS_25GenericInsituStringStreamIS2_EEEERS6_RT1_:
 2642|  14.0k|    GenericDocument& ParseStream(InputStream& is) {
 2643|  14.0k|        GenericReader<SourceEncoding, Encoding, StackAllocator> reader(
 2644|  14.0k|            stack_.HasAllocator() ? &stack_.GetAllocator() : 0);
  ------------------
  |  Branch (2644:13): [True: 0, False: 14.0k]
  ------------------
 2645|  14.0k|        ClearStackOnExit scope(*this);
 2646|  14.0k|        parseResult_ = reader.template Parse<parseFlags>(is, *this);
 2647|  14.0k|        if (parseResult_) {
  ------------------
  |  Branch (2647:13): [True: 11.5k, False: 2.48k]
  ------------------
 2648|  11.5k|            RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
  ------------------
  |  |  437|  11.5k|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (2648:13): [True: 11.5k, False: 0]
  ------------------
 2649|  11.5k|            ValueType::operator=(*stack_.template Pop<ValueType>(1));// Move value from stack to document
 2650|  11.5k|        }
 2651|  14.0k|        return *this;
 2652|  14.0k|    }
_ZN9rapidjson15GenericDocumentINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEES4_E10ClearStackEv:
 2868|  14.0k|    void ClearStack() {
 2869|  14.0k|        if (Allocator::kNeedFree)
  ------------------
  |  Branch (2869:13): [Folded, False: 14.0k]
  ------------------
 2870|      0|            while (stack_.GetSize() > 0)    // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects)
  ------------------
  |  Branch (2870:20): [True: 0, False: 0]
  ------------------
 2871|      0|                (stack_.template Pop<ValueType>(1))->~ValueType();
 2872|  14.0k|        else
 2873|  14.0k|            stack_.Clear();
 2874|  14.0k|        stack_.ShrinkToFit();
 2875|  14.0k|    }
_ZN9rapidjson15GenericDocumentINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEES4_E11StartObjectEv:
 2844|   511k|    bool StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); return true; }
_ZN9rapidjson15GenericDocumentINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEES4_E10StartArrayEv:
 2854|  5.49M|    bool StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArrayType); return true; }
_ZN9rapidjson15GenericDocumentINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEES4_E3KeyEPKcjb:
 2846|  5.67M|    bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); }
_ZN9rapidjson15GenericDocumentINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEES4_E6StringEPKcjb:
 2836|  5.97M|    bool String(const Ch* str, SizeType length, bool copy) { 
 2837|  5.97M|        if (copy) 
  ------------------
  |  Branch (2837:13): [True: 0, False: 5.97M]
  ------------------
 2838|      0|            new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());
 2839|  5.97M|        else
 2840|  5.97M|            new (stack_.template Push<ValueType>()) ValueType(str, length);
 2841|  5.97M|        return true;
 2842|  5.97M|    }
_ZN9rapidjson15GenericDocumentINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEES4_E12GetAllocatorEv:
 2795|  1.42M|    Allocator& GetAllocator() {
 2796|  1.42M|        RAPIDJSON_ASSERT(allocator_);
  ------------------
  |  |  437|  1.42M|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (2796:9): [True: 1.42M, False: 0]
  ------------------
 2797|  1.42M|        return *allocator_;
 2798|  1.42M|    }
_ZN9rapidjson9StringRefIcEENS_16GenericStringRefIT_EEPKS2_m:
  474|  5.97M|inline GenericStringRef<CharType> StringRef(const CharType* str, size_t length) {
  475|  5.97M|    return GenericStringRef<CharType>(str, SizeType(length));
  476|  5.97M|}
_ZN9rapidjson15GenericDocumentINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEES4_E9EndObjectEj:
 2848|   470k|    bool EndObject(SizeType memberCount) {
 2849|   470k|        typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount);
 2850|   470k|        stack_.template Top<ValueType>()->SetObjectRaw(members, memberCount, GetAllocator());
 2851|   470k|        return true;
 2852|   470k|    }
_ZN9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE12SetObjectRawEPNS_13GenericMemberIS2_S5_EEjRS5_:
 2415|   470k|    void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) {
 2416|   470k|        data_.f.flags = kObjectFlag;
 2417|   470k|        if (count) {
  ------------------
  |  Branch (2417:13): [True: 466k, False: 3.57k]
  ------------------
 2418|   466k|            Member* m = DoAllocMembers(count, allocator);
 2419|   466k|            SetMembersPointer(m);
 2420|   466k|            std::memcpy(static_cast<void*>(m), members, count * sizeof(Member));
 2421|       |#if RAPIDJSON_USE_MEMBERSMAP
 2422|       |            Map* &map = GetMap(m);
 2423|       |            MapIterator* mit = GetMapIterators(map);
 2424|       |            for (SizeType i = 0; i < count; i++) {
 2425|       |                new (&mit[i]) MapIterator(map->insert(MapPair(m[i].name.data_, i)));
 2426|       |            }
 2427|       |#endif
 2428|   466k|        }
 2429|  3.57k|        else
 2430|  3.57k|            SetMembersPointer(0);
 2431|   470k|        data_.o.size = data_.o.capacity = count;
 2432|   470k|    }
_ZN9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE14DoAllocMembersEjRS5_:
 2268|   466k|    RAPIDJSON_FORCEINLINE Member* DoAllocMembers(SizeType capacity, Allocator& allocator) {
 2269|   466k|        return Malloc<Member>(allocator, capacity);
 2270|   466k|    }
_ZN9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE17SetMembersPointerEPNS_13GenericMemberIS2_S5_EE:
 2119|   470k|    RAPIDJSON_FORCEINLINE Member* SetMembersPointer(Member* members) { return RAPIDJSON_SETPOINTER(Member, data_.o.members, members); }
  ------------------
  |  |  346|   470k|#define RAPIDJSON_SETPOINTER(type, p, x) (p = reinterpret_cast<type *>((reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0xFFFF0000, 0x00000000))) | reinterpret_cast<uintptr_t>(reinterpret_cast<const void*>(x))))
  |  |  ------------------
  |  |  |  |  320|   470k|#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32))
  |  |  ------------------
  ------------------
_ZN9rapidjson15GenericDocumentINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEES4_E8EndArrayEj:
 2856|   954k|    bool EndArray(SizeType elementCount) {
 2857|   954k|        ValueType* elements = stack_.template Pop<ValueType>(elementCount);
 2858|   954k|        stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount, GetAllocator());
 2859|   954k|        return true;
 2860|   954k|    }
_ZN9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE11SetArrayRawEPS6_jRS5_:
 2402|   954k|    void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) {
 2403|   954k|        data_.f.flags = kArrayFlag;
 2404|   954k|        if (count) {
  ------------------
  |  Branch (2404:13): [True: 949k, False: 4.71k]
  ------------------
 2405|   949k|            GenericValue* e = static_cast<GenericValue*>(allocator.Malloc(count * sizeof(GenericValue)));
 2406|   949k|            SetElementsPointer(e);
 2407|   949k|            std::memcpy(static_cast<void*>(e), values, count * sizeof(GenericValue));
 2408|   949k|        }
 2409|  4.71k|        else
 2410|  4.71k|            SetElementsPointer(0);
 2411|   954k|        data_.a.size = data_.a.capacity = count;
 2412|   954k|    }
_ZN9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE18SetElementsPointerEPS6_:
 2117|   954k|    RAPIDJSON_FORCEINLINE GenericValue* SetElementsPointer(GenericValue* elements) { return RAPIDJSON_SETPOINTER(GenericValue, data_.a.elements, elements); }
  ------------------
  |  |  346|   954k|#define RAPIDJSON_SETPOINTER(type, p, x) (p = reinterpret_cast<type *>((reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0xFFFF0000, 0x00000000))) | reinterpret_cast<uintptr_t>(reinterpret_cast<const void*>(x))))
  |  |  ------------------
  |  |  |  |  320|   954k|#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32))
  |  |  ------------------
  ------------------
_ZN9rapidjson15GenericDocumentINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEES4_E4NullEv:
 2820|  7.67k|    bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return true; }
_ZN9rapidjson15GenericDocumentINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEES4_E4BoolEb:
 2821|  41.8k|    bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); return true; }
_ZN9rapidjson15GenericDocumentINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEES4_E6DoubleEd:
 2826|   974k|    bool Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); return true; }
_ZN9rapidjson15GenericDocumentINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEES4_E5Int64El:
 2824|  5.54k|    bool Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
_ZN9rapidjson15GenericDocumentINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEES4_E6Uint64Em:
 2825|  39.2k|    bool Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
_ZN9rapidjson15GenericDocumentINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEES4_E3IntEi:
 2822|  37.3k|    bool Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
_ZN9rapidjson15GenericDocumentINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEES4_E4UintEj:
 2823|  12.1M|    bool Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
_ZN9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEEaSERS6_:
  921|  11.5k|    GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
  922|  11.5k|        if (RAPIDJSON_LIKELY(this != &rhs)) {
  ------------------
  |  |  492|  11.5k|#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (492:29): [True: 11.5k, False: 0]
  |  |  ------------------
  ------------------
  923|       |            // Can't destroy "this" before assigning "rhs", otherwise "rhs"
  924|       |            // could be used after free if it's an sub-Value of "this",
  925|       |            // hence the temporary danse.
  926|  11.5k|            GenericValue temp;
  927|  11.5k|            temp.RawAssign(rhs);
  928|  11.5k|            this->~GenericValue();
  929|  11.5k|            RawAssign(temp);
  930|  11.5k|        }
  931|  11.5k|        return *this;
  932|  11.5k|    }
_ZN9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEE9RawAssignERS6_:
 2459|  23.0k|    void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
 2460|  23.0k|        data_ = rhs.data_;
 2461|       |        // data_.f.flags = rhs.data_.f.flags;
 2462|  23.0k|        rhs.data_.f.flags = kNullFlag;
 2463|  23.0k|    }
_ZNK9rapidjson15GenericDocumentINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEES4_E13HasParseErrorEv:
 2771|  14.0k|    bool HasParseError() const { return parseResult_.IsError(); }
_ZNK9rapidjson15GenericDocumentINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEES4_E14GetErrorOffsetEv:
 2777|  2.48k|    size_t GetErrorOffset() const { return parseResult_.Offset(); }
_ZNK9rapidjson15GenericDocumentINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEES4_E13GetParseErrorEv:
 2774|  2.48k|    ParseErrorCode GetParseError() const { return parseResult_.Code(); }
_ZN9rapidjson16GenericStringRefIcEC2EPKc:
  400|   646k|        : s(str), length(NotNullStrLen(str)) {}
_ZN9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEEC2ENS_16GenericStringRefIcEE:
  840|   646k|    explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(s); }
_ZN9rapidjson16GenericStringRefIcEC2ERKS1_:
  414|   646k|    GenericStringRef(const GenericStringRef& rhs) : s(rhs.s), length(rhs.length) {}
_ZN9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEED2Ev:
  880|   697k|    ~GenericValue() {
  881|       |        // With RAPIDJSON_USE_MEMBERSMAP, the maps need to be destroyed to release
  882|       |        // their Allocator if it's refcounted (e.g. MemoryPoolAllocator).
  883|   697k|        if (Allocator::kNeedFree || (RAPIDJSON_USE_MEMBERSMAP+0 &&
  ------------------
  |  |  180|      0|#define RAPIDJSON_USE_MEMBERSMAP 0 // not by default
  ------------------
  |  Branch (883:13): [Folded, False: 0]
  |  Branch (883:38): [Folded, False: 0]
  ------------------
  884|      0|                                     internal::IsRefCounted<Allocator>::Value)) {
  ------------------
  |  Branch (884:38): [True: 0, Folded]
  ------------------
  885|      0|            switch(data_.f.flags) {
  886|      0|            case kArrayFlag:
  ------------------
  |  Branch (886:13): [True: 0, False: 0]
  ------------------
  887|      0|                {
  888|      0|                    GenericValue* e = GetElementsPointer();
  889|      0|                    for (GenericValue* v = e; v != e + data_.a.size; ++v)
  ------------------
  |  Branch (889:47): [True: 0, False: 0]
  ------------------
  890|      0|                        v->~GenericValue();
  891|      0|                    if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
  ------------------
  |  Branch (891:25): [Folded, False: 0]
  ------------------
  892|      0|                        Allocator::Free(e);
  893|      0|                    }
  894|      0|                }
  895|      0|                break;
  896|       |
  897|      0|            case kObjectFlag:
  ------------------
  |  Branch (897:13): [True: 0, False: 0]
  ------------------
  898|      0|                DoFreeMembers();
  899|      0|                break;
  900|       |
  901|      0|            case kCopyStringFlag:
  ------------------
  |  Branch (901:13): [True: 0, False: 0]
  ------------------
  902|      0|                if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
  ------------------
  |  Branch (902:21): [Folded, False: 0]
  ------------------
  903|      0|                    Allocator::Free(const_cast<Ch*>(GetStringPointer()));
  904|      0|                }
  905|      0|                break;
  906|       |
  907|      0|            default:
  ------------------
  |  Branch (907:13): [True: 0, False: 0]
  ------------------
  908|      0|                break;  // Do nothing for other types.
  909|      0|            }
  910|      0|        }
  911|   697k|    }
_ZN9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEEC2Ev:
  690|  47.2k|    GenericValue() RAPIDJSON_NOEXCEPT : data_() { data_.f.flags = kNullFlag; }
_ZN9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEEC2ENS_4TypeE:
  720|  6.00M|    explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_() {
  721|  6.00M|        static const uint16_t defaultFlags[] = {
  722|  6.00M|            kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag,
  723|  6.00M|            kNumberAnyFlag
  724|  6.00M|        };
  725|  6.00M|        RAPIDJSON_NOEXCEPT_ASSERT(type >= kNullType && type <= kNumberType);
  ------------------
  |  |  687|  6.00M|#define RAPIDJSON_NOEXCEPT_ASSERT(x) RAPIDJSON_ASSERT(x)
  |  |  ------------------
  |  |  |  |  437|  6.00M|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  ------------------
  ------------------
  |  Branch (725:9): [True: 6.00M, False: 0]
  |  Branch (725:9): [True: 6.00M, False: 0]
  |  Branch (725:9): [True: 6.00M, False: 0]
  ------------------
  726|  6.00M|        data_.f.flags = defaultFlags[type];
  727|       |
  728|       |        // Use ShortString to store empty string.
  729|  6.00M|        if (type == kStringType)
  ------------------
  |  Branch (729:13): [True: 0, False: 6.00M]
  ------------------
  730|      0|            data_.ss.SetLength(0);
  731|  6.00M|    }
_ZN9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEEC2Ej:
  798|  12.1M|    explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_() {
  799|  12.1M|        data_.n.u64 = u; 
  800|  12.1M|        data_.f.flags = (u & 0x80000000) ? kNumberUintFlag : (kNumberUintFlag | kIntFlag | kInt64Flag);
  ------------------
  |  Branch (800:25): [True: 2.60k, False: 12.1M]
  ------------------
  801|  12.1M|    }
_ZN9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEEC2Ei:
  792|  37.3k|    explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_() {
  793|  37.3k|        data_.n.i64 = i;
  794|  37.3k|        data_.f.flags = (i >= 0) ? (kNumberIntFlag | kUintFlag | kUint64Flag) : kNumberIntFlag;
  ------------------
  |  Branch (794:25): [True: 2.72k, False: 34.5k]
  ------------------
  795|  37.3k|    }
_ZN9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEEC2Ed:
  831|   974k|    explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = d; data_.f.flags = kNumberDoubleFlag; }
_ZN9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEEC2El:
  804|  5.54k|    explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_() {
  805|  5.54k|        data_.n.i64 = i64;
  806|  5.54k|        data_.f.flags = kNumberInt64Flag;
  807|  5.54k|        if (i64 >= 0) {
  ------------------
  |  Branch (807:13): [True: 0, False: 5.54k]
  ------------------
  808|      0|            data_.f.flags |= kNumberUint64Flag;
  809|      0|            if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
  ------------------
  |  |  320|      0|#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32))
  ------------------
  |  Branch (809:17): [True: 0, False: 0]
  ------------------
  810|      0|                data_.f.flags |= kUintFlag;
  811|      0|            if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
  ------------------
  |  |  320|      0|#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32))
  ------------------
  |  Branch (811:17): [True: 0, False: 0]
  ------------------
  812|      0|                data_.f.flags |= kIntFlag;
  813|      0|        }
  814|  5.54k|        else if (i64 >= static_cast<int64_t>(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
  ------------------
  |  |  320|  5.54k|#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32))
  ------------------
  |  Branch (814:18): [True: 0, False: 5.54k]
  ------------------
  815|      0|            data_.f.flags |= kIntFlag;
  816|  5.54k|    }
_ZN9rapidjson16GenericStringRefIcEC2EPKcj:
  412|  5.97M|        : s(RAPIDJSON_LIKELY(str) ? str : emptyString), length(len) { RAPIDJSON_ASSERT(str != 0 || len == 0u); }
  ------------------
  |  |  492|  5.97M|#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (492:29): [True: 5.97M, False: 0]
  |  |  ------------------
  ------------------
                      : s(RAPIDJSON_LIKELY(str) ? str : emptyString), length(len) { RAPIDJSON_ASSERT(str != 0 || len == 0u); }
  ------------------
  |  |  437|  5.97M|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (412:71): [True: 5.97M, False: 0]
  |  Branch (412:71): [True: 0, False: 0]
  |  Branch (412:71): [True: 5.97M, False: 0]
  ------------------
_ZN9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEEC2Em:
  819|  39.2k|    explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_() {
  820|  39.2k|        data_.n.u64 = u64;
  821|  39.2k|        data_.f.flags = kNumberUint64Flag;
  822|  39.2k|        if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000)))
  ------------------
  |  |  320|  39.2k|#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32))
  ------------------
  |  Branch (822:13): [True: 29.2k, False: 10.0k]
  ------------------
  823|  29.2k|            data_.f.flags |= kInt64Flag;
  824|  39.2k|        if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
  ------------------
  |  |  320|  39.2k|#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32))
  ------------------
  |  Branch (824:13): [True: 0, False: 39.2k]
  ------------------
  825|      0|            data_.f.flags |= kUintFlag;
  826|  39.2k|        if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
  ------------------
  |  |  320|  39.2k|#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32))
  ------------------
  |  Branch (826:13): [True: 0, False: 39.2k]
  ------------------
  827|      0|            data_.f.flags |= kIntFlag;
  828|  39.2k|    }
_ZN9rapidjson15GenericDocumentINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEES4_EC2EPS5_mPS4_:
 2527|  14.0k|        allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
 2528|  14.0k|    {
 2529|  14.0k|        if (!allocator_)
  ------------------
  |  Branch (2529:13): [True: 14.0k, False: 0]
  ------------------
 2530|  14.0k|            ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
  ------------------
  |  |  712|  14.0k|#define RAPIDJSON_NEW(TypeName) new TypeName
  ------------------
 2531|  14.0k|    }
_ZN9rapidjson15GenericDocumentINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEES4_E16ClearStackOnExitC2ERS6_:
 2806|  14.0k|        explicit ClearStackOnExit(GenericDocument& d) : d_(d) {}
_ZN9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEEC2IbEET_PNS_8internal8EnableIfINS9_15RemoveSfinaeTagIPFRNS9_9SfinaeTagENS9_6IsSameIbS8_EEEE4TypeEvE4TypeE:
  785|  41.8k|        : data_() {
  786|       |            // safe-guard against failing SFINAE
  787|  41.8k|            RAPIDJSON_STATIC_ASSERT((internal::IsSame<bool,T>::Value));
  ------------------
  |  |  447|  41.8k|   static_assert(x, RAPIDJSON_STRINGIFY(x))
  ------------------
  788|  41.8k|            data_.f.flags = b ? kTrueFlag : kFalseFlag;
  ------------------
  |  Branch (788:29): [True: 11.4k, False: 30.3k]
  ------------------
  789|  41.8k|    }
_ZN9rapidjson12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEEEC2EPKcj:
  837|  5.97M|    GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(StringRef(s, length)); }
_ZN9rapidjson15GenericDocumentINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEES4_E16ClearStackOnExitD2Ev:
 2807|  14.0k|        ~ClearStackOnExit() { d_.ClearStack(); }
_ZN9rapidjson15GenericDocumentINS_4UTF8IcEENS_19MemoryPoolAllocatorINS_12CrtAllocatorEEES4_ED2Ev:
 2548|  14.0k|    ~GenericDocument() {
 2549|       |        // Clear the ::ValueType before ownAllocator is destroyed, ~ValueType()
 2550|       |        // runs last and may access its elements or members which would be freed
 2551|       |        // with an allocator like MemoryPoolAllocator (CrtAllocator does not
 2552|       |        // free its data when destroyed, but MemoryPoolAllocator does).
 2553|  14.0k|        if (ownAllocator_) {
  ------------------
  |  Branch (2553:13): [True: 14.0k, False: 0]
  ------------------
 2554|  14.0k|            ValueType::SetNull();
 2555|  14.0k|        }
 2556|  14.0k|        Destroy();
 2557|  14.0k|    }

_ZN9rapidjson4UTF8IcE6EncodeINS_25GenericInsituStringStreamIS1_EEEEvRT_j:
  102|  1.00k|    static void Encode(OutputStream& os, unsigned codepoint) {
  103|  1.00k|        if (codepoint <= 0x7F) 
  ------------------
  |  Branch (103:13): [True: 244, False: 758]
  ------------------
  104|    244|            os.Put(static_cast<Ch>(codepoint & 0xFF));
  105|    758|        else if (codepoint <= 0x7FF) {
  ------------------
  |  Branch (105:18): [True: 184, False: 574]
  ------------------
  106|    184|            os.Put(static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
  107|    184|            os.Put(static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
  108|    184|        }
  109|    574|        else if (codepoint <= 0xFFFF) {
  ------------------
  |  Branch (109:18): [True: 315, False: 259]
  ------------------
  110|    315|            os.Put(static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
  111|    315|            os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
  112|    315|            os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
  113|    315|        }
  114|    259|        else {
  115|    259|            RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
  ------------------
  |  |  437|    259|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (115:13): [True: 259, False: 0]
  ------------------
  116|    259|            os.Put(static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
  117|    259|            os.Put(static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
  118|    259|            os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
  119|    259|            os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
  120|    259|        }
  121|  1.00k|    }
_ZN9rapidjson10TranscoderINS_4UTF8IcEES2_E9TranscodeINS_25GenericInsituStringStreamIS2_EES6_EEbRT_RT0_:
  693|  70.8M|    static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) {
  694|  70.8M|        os.Put(is.Take());  // Just copy one code unit. This semantic is different from primary template class.
  695|  70.8M|        return true;
  696|  70.8M|    }

_ZN9rapidjson16GetParseError_EnENS_14ParseErrorCodeE:
   36|  2.48k|inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) {
   37|  2.48k|    switch (parseErrorCode) {
   38|      0|        case kParseErrorNone:                           return RAPIDJSON_ERROR_STRING("No error.");
  ------------------
  |  |   52|      0|#define RAPIDJSON_ERROR_STRING(x) x
  ------------------
  |  Branch (38:9): [True: 0, False: 2.48k]
  ------------------
   39|       |
   40|     32|        case kParseErrorDocumentEmpty:                  return RAPIDJSON_ERROR_STRING("The document is empty.");
  ------------------
  |  |   52|     32|#define RAPIDJSON_ERROR_STRING(x) x
  ------------------
  |  Branch (40:9): [True: 32, False: 2.44k]
  ------------------
   41|    248|        case kParseErrorDocumentRootNotSingular:        return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values.");
  ------------------
  |  |   52|    248|#define RAPIDJSON_ERROR_STRING(x) x
  ------------------
  |  Branch (41:9): [True: 248, False: 2.23k]
  ------------------
   42|       |
   43|    804|        case kParseErrorValueInvalid:                   return RAPIDJSON_ERROR_STRING("Invalid value.");
  ------------------
  |  |   52|    804|#define RAPIDJSON_ERROR_STRING(x) x
  ------------------
  |  Branch (43:9): [True: 804, False: 1.67k]
  ------------------
   44|       |
   45|    118|        case kParseErrorObjectMissName:                 return RAPIDJSON_ERROR_STRING("Missing a name for object member.");
  ------------------
  |  |   52|    118|#define RAPIDJSON_ERROR_STRING(x) x
  ------------------
  |  Branch (45:9): [True: 118, False: 2.36k]
  ------------------
   46|     90|        case kParseErrorObjectMissColon:                return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member.");
  ------------------
  |  |   52|     90|#define RAPIDJSON_ERROR_STRING(x) x
  ------------------
  |  Branch (46:9): [True: 90, False: 2.39k]
  ------------------
   47|    102|        case kParseErrorObjectMissCommaOrCurlyBracket:  return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member.");
  ------------------
  |  |   52|    102|#define RAPIDJSON_ERROR_STRING(x) x
  ------------------
  |  Branch (47:9): [True: 102, False: 2.37k]
  ------------------
   48|       |
   49|    824|        case kParseErrorArrayMissCommaOrSquareBracket:  return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element.");
  ------------------
  |  |   52|    824|#define RAPIDJSON_ERROR_STRING(x) x
  ------------------
  |  Branch (49:9): [True: 824, False: 1.65k]
  ------------------
   50|       |
   51|     26|        case kParseErrorStringUnicodeEscapeInvalidHex:  return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string.");
  ------------------
  |  |   52|     26|#define RAPIDJSON_ERROR_STRING(x) x
  ------------------
  |  Branch (51:9): [True: 26, False: 2.45k]
  ------------------
   52|     20|        case kParseErrorStringUnicodeSurrogateInvalid:  return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid.");
  ------------------
  |  |   52|     20|#define RAPIDJSON_ERROR_STRING(x) x
  ------------------
  |  Branch (52:9): [True: 20, False: 2.46k]
  ------------------
   53|     14|        case kParseErrorStringEscapeInvalid:            return RAPIDJSON_ERROR_STRING("Invalid escape character in string.");
  ------------------
  |  |   52|     14|#define RAPIDJSON_ERROR_STRING(x) x
  ------------------
  |  Branch (53:9): [True: 14, False: 2.46k]
  ------------------
   54|     82|        case kParseErrorStringMissQuotationMark:        return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string.");
  ------------------
  |  |   52|     82|#define RAPIDJSON_ERROR_STRING(x) x
  ------------------
  |  Branch (54:9): [True: 82, False: 2.39k]
  ------------------
   55|     10|        case kParseErrorStringInvalidEncoding:          return RAPIDJSON_ERROR_STRING("Invalid encoding in string.");
  ------------------
  |  |   52|     10|#define RAPIDJSON_ERROR_STRING(x) x
  ------------------
  |  Branch (55:9): [True: 10, False: 2.47k]
  ------------------
   56|       |
   57|     28|        case kParseErrorNumberTooBig:                   return RAPIDJSON_ERROR_STRING("Number too big to be stored in double.");
  ------------------
  |  |   52|     28|#define RAPIDJSON_ERROR_STRING(x) x
  ------------------
  |  Branch (57:9): [True: 28, False: 2.45k]
  ------------------
   58|     18|        case kParseErrorNumberMissFraction:             return RAPIDJSON_ERROR_STRING("Miss fraction part in number.");
  ------------------
  |  |   52|     18|#define RAPIDJSON_ERROR_STRING(x) x
  ------------------
  |  Branch (58:9): [True: 18, False: 2.46k]
  ------------------
   59|     64|        case kParseErrorNumberMissExponent:             return RAPIDJSON_ERROR_STRING("Miss exponent in number.");
  ------------------
  |  |   52|     64|#define RAPIDJSON_ERROR_STRING(x) x
  ------------------
  |  Branch (59:9): [True: 64, False: 2.41k]
  ------------------
   60|       |
   61|      0|        case kParseErrorTermination:                    return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error.");
  ------------------
  |  |   52|      0|#define RAPIDJSON_ERROR_STRING(x) x
  ------------------
  |  Branch (61:9): [True: 0, False: 2.48k]
  ------------------
   62|      0|        case kParseErrorUnspecificSyntaxError:          return RAPIDJSON_ERROR_STRING("Unspecific syntax error.");
  ------------------
  |  |   52|      0|#define RAPIDJSON_ERROR_STRING(x) x
  ------------------
  |  Branch (62:9): [True: 0, False: 2.48k]
  ------------------
   63|       |
   64|      0|        default:                                        return RAPIDJSON_ERROR_STRING("Unknown error.");
  ------------------
  |  |   52|      0|#define RAPIDJSON_ERROR_STRING(x) x
  ------------------
  |  Branch (64:9): [True: 0, False: 2.48k]
  ------------------
   65|  2.48k|    }
   66|  2.48k|}

_ZN9rapidjson11ParseResultC2Ev:
  111|  28.0k|    ParseResult() : code_(kParseErrorNone), offset_(0) {}
_ZNK9rapidjson11ParseResult4CodeEv:
  116|  2.48k|    ParseErrorCode Code() const { return code_; }
_ZNK9rapidjson11ParseResult6OffsetEv:
  118|  2.48k|    size_t Offset() const { return offset_; }
_ZNK9rapidjson11ParseResultcvMS0_KFbvEEv:
  121|  14.0k|    operator BooleanType() const { return !IsError() ? &ParseResult::IsError : NULL; }
  ------------------
  |  Branch (121:43): [True: 11.5k, False: 2.48k]
  ------------------
_ZNK9rapidjson11ParseResult7IsErrorEv:
  123|  77.0M|    bool IsError() const { return code_ != kParseErrorNone; }
_ZN9rapidjson11ParseResult5ClearEv:
  134|  14.0k|    void Clear() { Set(kParseErrorNone); }
_ZN9rapidjson11ParseResult3SetENS_14ParseErrorCodeEm:
  136|  16.5k|    void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; }

_ZN9rapidjson8internal5Pow10Ei:
   28|   978k|inline double Pow10(int n) {
   29|   978k|    static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes
   30|   978k|        1e+0,  
   31|   978k|        1e+1,  1e+2,  1e+3,  1e+4,  1e+5,  1e+6,  1e+7,  1e+8,  1e+9,  1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, 
   32|   978k|        1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40,
   33|   978k|        1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60,
   34|   978k|        1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80,
   35|   978k|        1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100,
   36|   978k|        1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120,
   37|   978k|        1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140,
   38|   978k|        1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160,
   39|   978k|        1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180,
   40|   978k|        1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200,
   41|   978k|        1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220,
   42|   978k|        1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240,
   43|   978k|        1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260,
   44|   978k|        1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280,
   45|   978k|        1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300,
   46|   978k|        1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308
   47|   978k|    };
   48|   978k|    RAPIDJSON_ASSERT(n >= 0 && n <= 308);
  ------------------
  |  |  437|   978k|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (48:5): [True: 978k, False: 0]
  |  Branch (48:5): [True: 978k, False: 0]
  |  Branch (48:5): [True: 978k, False: 0]
  ------------------
   49|   978k|    return e[n];
   50|   978k|}

_ZNK9rapidjson8internal5StackINS_12CrtAllocatorEE11GetCapacityEv:
  179|  41.9k|    size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); }
_ZNK9rapidjson8internal5StackINS_12CrtAllocatorEE7GetSizeEv:
  178|  2.92M|    size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); }
_ZN9rapidjson8internal5StackINS_12CrtAllocatorEE6ResizeEm:
  201|  27.9k|    void Resize(size_t newCapacity) {
  202|  27.9k|        const size_t size = GetSize();  // Backup the current size
  203|  27.9k|        stack_ = static_cast<char*>(allocator_->Realloc(stack_, GetCapacity(), newCapacity));
  204|  27.9k|        stackTop_ = stack_ + size;
  205|  27.9k|        stackEnd_ = stack_ + newCapacity;
  206|  27.9k|    }
_ZNK9rapidjson8internal5StackINS_12CrtAllocatorEE12HasAllocatorEv:
  168|  14.0k|    bool HasAllocator() const {
  169|  14.0k|        return allocator_ != 0;
  170|  14.0k|    }
_ZN9rapidjson8internal5StackINS_12CrtAllocatorEE5ClearEv:
   99|  28.0k|    void Clear() { stackTop_ = stack_; }
_ZN9rapidjson8internal5StackINS_12CrtAllocatorEE11ShrinkToFitEv:
  101|  14.0k|    void ShrinkToFit() { 
  102|  14.0k|        if (Empty()) {
  ------------------
  |  Branch (102:13): [True: 14.0k, False: 0]
  ------------------
  103|       |            // If the stack is empty, completely deallocate the memory.
  104|  14.0k|            Allocator::Free(stack_); // NOLINT (+clang-analyzer-unix.Malloc)
  105|  14.0k|            stack_ = 0;
  106|  14.0k|            stackTop_ = 0;
  107|  14.0k|            stackEnd_ = 0;
  108|  14.0k|        }
  109|      0|        else
  110|      0|            Resize(GetSize());
  111|  14.0k|    }
_ZNK9rapidjson8internal5StackINS_12CrtAllocatorEE5EmptyEv:
  177|  14.0k|    bool Empty() const { return stackTop_ == stack_; }
_ZN9rapidjson8internal5StackINS_12CrtAllocatorEE4PushINS_12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorIS2_EEEEEEPT_m:
  123|  25.2M|    RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) {
  124|  25.2M|        Reserve<T>(count);
  125|  25.2M|        return PushUnsafe<T>(count);
  126|  25.2M|    }
_ZN9rapidjson8internal5StackINS_12CrtAllocatorEE7ReserveINS_12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorIS2_EEEEEEvm:
  116|  25.2M|    RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) {
  117|       |         // Expand the stack if needed
  118|  25.2M|        if (RAPIDJSON_UNLIKELY(static_cast<std::ptrdiff_t>(sizeof(T) * count) > (stackEnd_ - stackTop_)))
  ------------------
  |  |  505|  25.2M|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 27.9k, False: 25.1M]
  |  |  ------------------
  ------------------
  119|  27.9k|            Expand<T>(count);
  120|  25.2M|    }
_ZN9rapidjson8internal5StackINS_12CrtAllocatorEE6ExpandINS_12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorIS2_EEEEEEvm:
  183|  27.9k|    void Expand(size_t count) {
  184|       |        // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity.
  185|  27.9k|        size_t newCapacity;
  186|  27.9k|        if (stack_ == 0) {
  ------------------
  |  Branch (186:13): [True: 13.8k, False: 14.0k]
  ------------------
  187|  13.8k|            if (!allocator_)
  ------------------
  |  Branch (187:17): [True: 13.8k, False: 0]
  ------------------
  188|  13.8k|                ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
  ------------------
  |  |  712|  13.8k|#define RAPIDJSON_NEW(TypeName) new TypeName
  ------------------
  189|  13.8k|            newCapacity = initialCapacity_;
  190|  14.0k|        } else {
  191|  14.0k|            newCapacity = GetCapacity();
  192|  14.0k|            newCapacity += (newCapacity + 1) / 2;
  193|  14.0k|        }
  194|  27.9k|        size_t newSize = GetSize() + sizeof(T) * count;
  195|  27.9k|        if (newCapacity < newSize)
  ------------------
  |  Branch (195:13): [True: 0, False: 27.9k]
  ------------------
  196|      0|            newCapacity = newSize;
  197|       |
  198|  27.9k|        Resize(newCapacity);
  199|  27.9k|    }
_ZN9rapidjson8internal5StackINS_12CrtAllocatorEE10PushUnsafeINS_12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorIS2_EEEEEEPT_m:
  129|  25.2M|    RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) {
  130|  25.2M|        RAPIDJSON_ASSERT(stackTop_);
  ------------------
  |  |  437|  25.2M|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (130:9): [True: 25.2M, False: 0]
  ------------------
  131|  25.2M|        RAPIDJSON_ASSERT(static_cast<std::ptrdiff_t>(sizeof(T) * count) <= (stackEnd_ - stackTop_));
  ------------------
  |  |  437|  25.2M|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (131:9): [True: 25.2M, False: 0]
  ------------------
  132|  25.2M|        T* ret = reinterpret_cast<T*>(stackTop_);
  133|  25.2M|        stackTop_ += sizeof(T) * count;
  134|  25.2M|        return ret;
  135|  25.2M|    }
_ZN9rapidjson8internal5StackINS_12CrtAllocatorEE3PopINS_13GenericMemberINS_4UTF8IcEENS_19MemoryPoolAllocatorIS2_EEEEEEPT_m:
  138|   470k|    T* Pop(size_t count) {
  139|   470k|        RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
  ------------------
  |  |  437|   470k|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (139:9): [True: 470k, False: 0]
  ------------------
  140|   470k|        stackTop_ -= count * sizeof(T);
  141|   470k|        return reinterpret_cast<T*>(stackTop_);
  142|   470k|    }
_ZN9rapidjson8internal5StackINS_12CrtAllocatorEE3TopINS_12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorIS2_EEEEEEPT_v:
  145|  1.42M|    T* Top() { 
  146|  1.42M|        RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
  ------------------
  |  |  437|  1.42M|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (146:9): [True: 1.42M, False: 0]
  ------------------
  147|  1.42M|        return reinterpret_cast<T*>(stackTop_ - sizeof(T));
  148|  1.42M|    }
_ZN9rapidjson8internal5StackINS_12CrtAllocatorEE3PopINS_12GenericValueINS_4UTF8IcEENS_19MemoryPoolAllocatorIS2_EEEEEEPT_m:
  138|   966k|    T* Pop(size_t count) {
  139|   966k|        RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
  ------------------
  |  |  437|   966k|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (139:9): [True: 966k, False: 0]
  ------------------
  140|   966k|        stackTop_ -= count * sizeof(T);
  141|   966k|        return reinterpret_cast<T*>(stackTop_);
  142|   966k|    }
_ZN9rapidjson8internal5StackINS_12CrtAllocatorEE7DestroyEv:
  208|  28.0k|    void Destroy() {
  209|  28.0k|        Allocator::Free(stack_);
  210|  28.0k|        RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack
  ------------------
  |  |  716|  28.0k|#define RAPIDJSON_DELETE(x) delete x
  ------------------
  211|  28.0k|    }
_ZN9rapidjson8internal5StackINS_12CrtAllocatorEEC2EPS2_m:
   41|  28.0k|    Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) {
   42|  28.0k|    }
_ZN9rapidjson8internal5StackINS_12CrtAllocatorEED2Ev:
   62|  28.0k|    ~Stack() {
   63|  28.0k|        Destroy();
   64|  28.0k|    }

_ZN9rapidjson8internal6StrLenIcEEjPKT_:
   39|   646k|inline SizeType StrLen(const char* s) {
   40|   646k|    return SizeType(std::strlen(s));
   41|   646k|}

_ZN9rapidjson8internal8FastPathEdi:
   28|   981k|inline double FastPath(double significand, int exp) {
   29|   981k|    if (exp < -308)
  ------------------
  |  Branch (29:9): [True: 3.08k, False: 978k]
  ------------------
   30|  3.08k|        return 0.0;
   31|   978k|    else if (exp >= 0)
  ------------------
  |  Branch (31:14): [True: 84.1k, False: 894k]
  ------------------
   32|  84.1k|        return significand * internal::Pow10(exp);
   33|   894k|    else
   34|   894k|        return significand / internal::Pow10(-exp);
   35|   981k|}
_ZN9rapidjson8internal21StrtodNormalPrecisionEdi:
   37|   974k|inline double StrtodNormalPrecision(double d, int p) {
   38|   974k|    if (p < -308) {
  ------------------
  |  Branch (38:9): [True: 7.04k, False: 967k]
  ------------------
   39|       |        // Prevent expSum < -308, making Pow10(p) = 0
   40|  7.04k|        d = FastPath(d, -308);
   41|  7.04k|        d = FastPath(d, p + 308);
   42|  7.04k|    }
   43|   967k|    else
   44|   967k|        d = FastPath(d, p);
   45|   974k|    return d;
   46|   974k|}

_ZN9rapidjson13GenericReaderINS_4UTF8IcEES2_NS_12CrtAllocatorEE5ParseILj1ENS_25GenericInsituStringStreamIS2_EENS_15GenericDocumentIS2_NS_19MemoryPoolAllocatorIS3_EES3_EEEENS_11ParseResultERT0_RT1_:
  559|  14.0k|    ParseResult Parse(InputStream& is, Handler& handler) {
  560|  14.0k|        if (parseFlags & kParseIterativeFlag)
  ------------------
  |  Branch (560:13): [Folded, False: 14.0k]
  ------------------
  561|      0|            return IterativeParse<parseFlags>(is, handler);
  562|       |
  563|  14.0k|        parseResult_.Clear();
  564|       |
  565|  14.0k|        ClearStackOnExit scope(*this);
  566|       |
  567|  14.0k|        SkipWhitespaceAndComments<parseFlags>(is);
  568|  14.0k|        RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
  ------------------
  |  |   61|  14.0k|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|  14.0k|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |   62|  14.0k|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  ------------------
  |  |  |  |  505|  14.0k|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (505:31): [True: 0, False: 14.0k]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |   63|  14.0k|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|  14.0k|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|  14.0k|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 14.0k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  569|       |
  570|  14.0k|        if (RAPIDJSON_UNLIKELY(is.Peek() == '\0')) {
  ------------------
  |  |  505|  14.0k|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 32, False: 13.9k]
  |  |  ------------------
  ------------------
  571|     32|            RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell());
  ------------------
  |  |  101|     32|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|     32|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  102|     32|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  ------------------
  |  |  |  |  437|     32|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  ------------------
  |  |  103|     32|    SetParseError(parseErrorCode, offset); \
  |  |  104|     32|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|     32|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|     32|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 32]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (571:13): [True: 32, False: 0]
  ------------------
  572|     32|            RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
  ------------------
  |  |   61|     64|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|     32|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |   62|     64|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  ------------------
  |  |  |  |  505|     32|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (505:31): [True: 32, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |   63|     64|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|     32|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|     32|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  573|     32|        }
  574|  13.9k|        else {
  575|  13.9k|            ParseValue<parseFlags>(is, handler);
  576|  13.9k|            RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
  ------------------
  |  |   61|  13.9k|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|  13.9k|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |   62|  13.9k|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  ------------------
  |  |  |  |  505|  13.9k|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (505:31): [True: 2.20k, False: 11.7k]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |   63|  13.9k|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|  13.9k|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|  13.9k|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 11.7k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  577|       |
  578|  11.7k|            if (!(parseFlags & kParseStopWhenDoneFlag)) {
  ------------------
  |  Branch (578:17): [True: 11.7k, Folded]
  ------------------
  579|  11.7k|                SkipWhitespaceAndComments<parseFlags>(is);
  580|  11.7k|                RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
  ------------------
  |  |   61|  11.7k|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|  11.7k|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |   62|  11.7k|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  ------------------
  |  |  |  |  505|  11.7k|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (505:31): [True: 0, False: 11.7k]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |   63|  11.7k|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|  11.7k|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|  11.7k|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 11.7k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  581|       |
  582|  11.7k|                if (RAPIDJSON_UNLIKELY(is.Peek() != '\0')) {
  ------------------
  |  |  505|  11.7k|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 248, False: 11.5k]
  |  |  ------------------
  ------------------
  583|    248|                    RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell());
  ------------------
  |  |  101|    248|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|    248|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  102|    248|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  ------------------
  |  |  |  |  437|    248|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  ------------------
  |  |  103|    248|    SetParseError(parseErrorCode, offset); \
  |  |  104|    248|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|    248|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|    248|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 248]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (583:21): [True: 248, False: 0]
  ------------------
  584|    248|                    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
  ------------------
  |  |   61|    496|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|    248|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |   62|    496|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  ------------------
  |  |  |  |  505|    248|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (505:31): [True: 248, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |   63|    496|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|    248|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|    248|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  585|    248|                }
  586|  11.7k|            }
  587|  11.7k|        }
  588|       |
  589|  11.5k|        return parseResult_;
  590|  14.0k|    }
_ZN9rapidjson13GenericReaderINS_4UTF8IcEES2_NS_12CrtAllocatorEE11ParseStringILj1ENS_25GenericInsituStringStreamIS2_EENS_15GenericDocumentIS2_NS_19MemoryPoolAllocatorIS3_EES3_EEEEvRT0_RT1_b:
  959|  5.97M|    void ParseString(InputStream& is, Handler& handler, bool isKey = false) {
  960|  5.97M|        internal::StreamLocalCopy<InputStream> copy(is);
  961|  5.97M|        InputStream& s(copy.s);
  962|       |
  963|  5.97M|        RAPIDJSON_ASSERT(s.Peek() == '\"');
  ------------------
  |  |  437|  5.97M|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (963:9): [True: 5.97M, False: 0]
  ------------------
  964|  5.97M|        s.Take();  // Skip '\"'
  965|       |
  966|  5.97M|        bool success = false;
  967|  5.97M|        if (parseFlags & kParseInsituFlag) {
  ------------------
  |  Branch (967:13): [True: 5.97M, Folded]
  ------------------
  968|  5.97M|            typename InputStream::Ch *head = s.PutBegin();
  969|  5.97M|            ParseStringToStream<parseFlags, SourceEncoding, SourceEncoding>(s, s);
  970|  5.97M|            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
  ------------------
  |  |   66|  5.97M|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  ------------------
  |  |  |  |   61|  5.97M|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|  5.97M|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |   62|  5.97M|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  ------------------
  |  |  |  |  |  |  505|  5.97M|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (505:31): [True: 152, False: 5.97M]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |   63|  5.97M|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|  5.97M|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|  5.97M|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 5.97M]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  971|  5.97M|            size_t length = s.PutEnd(head) - 1;
  972|  5.97M|            RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
  ------------------
  |  |  437|  5.97M|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (972:13): [True: 5.97M, False: 0]
  ------------------
  973|  5.97M|            const typename TargetEncoding::Ch* const str = reinterpret_cast<typename TargetEncoding::Ch*>(head);
  974|  5.97M|            success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false));
  ------------------
  |  Branch (974:24): [True: 5.67M, False: 294k]
  ------------------
  975|  5.97M|        }
  976|      0|        else {
  977|      0|            StackStream<typename TargetEncoding::Ch> stackStream(stack_);
  978|      0|            ParseStringToStream<parseFlags, SourceEncoding, TargetEncoding>(s, stackStream);
  979|      0|            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
  ------------------
  |  |   66|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  ------------------
  |  |  |  |   61|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |   62|      0|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  ------------------
  |  |  |  |  |  |  505|      0|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (505:31): [True: 0, False: 0]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |   63|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  980|      0|            SizeType length = static_cast<SizeType>(stackStream.Length()) - 1;
  981|      0|            const typename TargetEncoding::Ch* const str = stackStream.Pop();
  982|      0|            success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true));
  ------------------
  |  Branch (982:24): [True: 0, False: 0]
  ------------------
  983|      0|        }
  984|  5.97M|        if (RAPIDJSON_UNLIKELY(!success))
  ------------------
  |  |  505|  5.97M|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 0, False: 5.97M]
  |  |  ------------------
  ------------------
  985|       |            RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell());
  ------------------
  |  |  120|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|      0|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|      0|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|      0|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|      0|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|      0|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|      0|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 0, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (985:13): [True: 0, False: 0]
  ------------------
  986|  5.97M|    }
_ZN9rapidjson13GenericReaderINS_4UTF8IcEES2_NS_12CrtAllocatorEE19ParseStringToStreamILj1ES2_S2_NS_25GenericInsituStringStreamIS2_EES7_EEvRT2_RT3_:
  991|  5.97M|    RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) {
  992|       |//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
  993|  5.97M|#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  994|  5.97M|        static const char escape[256] = {
  995|  5.97M|            Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '/',
  ------------------
  |  |  993|  5.97M|#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  ------------------
                          Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '/',
  ------------------
  |  |  993|  5.97M|#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  ------------------
  996|  5.97M|            Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0,
  ------------------
  |  |  993|  5.97M|#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  ------------------
                          Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0,
  ------------------
  |  |  993|  5.97M|#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  ------------------
  997|  5.97M|            0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0,
  998|  5.97M|            0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  999|  5.97M|            Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
  ------------------
  |  |  993|  5.97M|#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  ------------------
                          Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
  ------------------
  |  |  993|  5.97M|#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  ------------------
                          Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
  ------------------
  |  |  993|  5.97M|#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  ------------------
                          Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
  ------------------
  |  |  993|  5.97M|#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  ------------------
                          Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
  ------------------
  |  |  993|  5.97M|#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  ------------------
                          Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
  ------------------
  |  |  993|  5.97M|#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  ------------------
                          Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
  ------------------
  |  |  993|  5.97M|#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  ------------------
                          Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
  ------------------
  |  |  993|  5.97M|#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  ------------------
 1000|  5.97M|        };
 1001|  5.97M|#undef Z16
 1002|       |//!@endcond
 1003|       |
 1004|  76.8M|        for (;;) {
 1005|       |            // Scan and copy string before "\\\"" or < 0x20. This is an optional optimzation.
 1006|  76.8M|            if (!(parseFlags & kParseValidateEncodingFlag))
  ------------------
  |  Branch (1006:17): [True: 76.8M, Folded]
  ------------------
 1007|  76.8M|                ScanCopyUnescapedString(is, os);
 1008|       |
 1009|  76.8M|            Ch c = is.Peek();
 1010|  76.8M|            if (RAPIDJSON_UNLIKELY(c == '\\')) {    // Escape
  ------------------
  |  |  505|  76.8M|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 8.15k, False: 76.8M]
  |  |  ------------------
  ------------------
 1011|  8.15k|                size_t escapeOffset = is.Tell();    // For invalid escaping, report the initial '\\' as error offset
 1012|  8.15k|                is.Take();
 1013|  8.15k|                Ch e = is.Peek();
 1014|  8.15k|                if ((sizeof(Ch) == 1 || unsigned(e) < 256) && RAPIDJSON_LIKELY(escape[static_cast<unsigned char>(e)])) {
  ------------------
  |  |  492|  8.15k|#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (492:29): [True: 7.08k, False: 1.06k]
  |  |  ------------------
  ------------------
  |  Branch (1014:22): [True: 8.15k, Folded]
  |  Branch (1014:41): [True: 0, False: 0]
  ------------------
 1015|  7.08k|                    is.Take();
 1016|  7.08k|                    os.Put(static_cast<typename TEncoding::Ch>(escape[static_cast<unsigned char>(e)]));
 1017|  7.08k|                }
 1018|  1.06k|                else if ((parseFlags & kParseEscapedApostropheFlag) && RAPIDJSON_LIKELY(e == '\'')) { // Allow escaped apostrophe
  ------------------
  |  |  492|      0|#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (492:29): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (1018:26): [Folded, False: 1.06k]
  ------------------
 1019|      0|                    is.Take();
 1020|      0|                    os.Put('\'');
 1021|      0|                }
 1022|  1.06k|                else if (RAPIDJSON_LIKELY(e == 'u')) {    // Unicode
  ------------------
  |  |  492|  1.06k|#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (492:29): [True: 1.04k, False: 14]
  |  |  ------------------
  ------------------
 1023|  1.04k|                    is.Take();
 1024|  1.04k|                    unsigned codepoint = ParseHex4(is, escapeOffset);
 1025|  1.04k|                    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
  ------------------
  |  |   66|  1.04k|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  ------------------
  |  |  |  |   61|  1.04k|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|  1.04k|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |   62|  1.04k|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  ------------------
  |  |  |  |  |  |  505|  1.04k|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (505:31): [True: 16, False: 1.03k]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |   63|  1.04k|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|  1.04k|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|  1.04k|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 1.03k]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1026|  1.03k|                    if (RAPIDJSON_UNLIKELY(codepoint >= 0xD800 && codepoint <= 0xDFFF)) {
  ------------------
  |  |  505|  1.58k|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 289, False: 743]
  |  |  |  Branch (505:51): [True: 554, False: 478]
  |  |  |  Branch (505:51): [True: 289, False: 265]
  |  |  ------------------
  ------------------
 1027|       |                        // high surrogate, check if followed by valid low surrogate
 1028|    289|                        if (RAPIDJSON_LIKELY(codepoint <= 0xDBFF)) {
  ------------------
  |  |  492|    289|#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (492:29): [True: 283, False: 6]
  |  |  ------------------
  ------------------
 1029|       |                            // Handle UTF-16 surrogate pair
 1030|    283|                            if (RAPIDJSON_UNLIKELY(!Consume(is, '\\') || !Consume(is, 'u')))
  ------------------
  |  |  505|    560|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 12, False: 271]
  |  |  |  Branch (505:51): [True: 6, False: 277]
  |  |  |  Branch (505:51): [True: 6, False: 271]
  |  |  ------------------
  ------------------
 1031|    283|                                RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
  ------------------
  |  |  120|     24|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|     12|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|     24|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|     12|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|     12|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|     12|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|     12|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|     12|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|     12|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|     12|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|     12|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 12]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|     24|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|     12|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|     24|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|     12|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|     24|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|     12|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 12, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|     24|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|     12|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|     12|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|     12|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|     12|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|     12|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1031:33): [True: 12, False: 0]
  ------------------
 1032|    271|                            unsigned codepoint2 = ParseHex4(is, escapeOffset);
 1033|    271|                            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
  ------------------
  |  |   66|    271|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  ------------------
  |  |  |  |   61|    271|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|    271|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |   62|    271|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  ------------------
  |  |  |  |  |  |  505|    271|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (505:31): [True: 10, False: 261]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |   63|    271|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|    271|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|    271|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 261]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1034|    261|                            if (RAPIDJSON_UNLIKELY(codepoint2 < 0xDC00 || codepoint2 > 0xDFFF))
  ------------------
  |  |  505|    520|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 2, False: 259]
  |  |  |  Branch (505:51): [True: 2, False: 259]
  |  |  |  Branch (505:51): [True: 0, False: 259]
  |  |  ------------------
  ------------------
 1035|    261|                                RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
  ------------------
  |  |  120|      4|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|      2|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|      4|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|      2|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|      2|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|      2|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|      2|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|      2|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|      2|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|      2|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|      2|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 2]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|      4|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|      2|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|      4|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|      2|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|      4|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|      2|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 2, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|      4|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|      2|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|      2|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|      2|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|      2|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|      2|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1035:33): [True: 2, False: 0]
  ------------------
 1036|    259|                            codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
 1037|    259|                        }
 1038|       |                        // single low surrogate
 1039|      6|                        else
 1040|      6|                        {
 1041|      6|                            RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
  ------------------
  |  |  120|      6|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|      6|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|      6|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|      6|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|      6|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|      6|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|      6|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|      6|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|      6|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|      6|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|      6|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 6]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|      6|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|      6|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|     12|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|      6|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|     12|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|      6|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 6, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|     12|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|      6|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|      6|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|      6|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|      6|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|      6|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1041:29): [True: 6, False: 0]
  ------------------
 1042|      6|                        }
 1043|    289|                    }
 1044|  1.00k|                    TEncoding::Encode(os, codepoint);
 1045|  1.00k|                }
 1046|     14|                else
 1047|  1.06k|                    RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, escapeOffset);
  ------------------
  |  |  120|     28|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|     14|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|     28|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|     14|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|     14|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|     14|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|     14|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|     14|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|     14|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|     14|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|     14|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 14]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|     28|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|     14|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|     28|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|     14|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|     28|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|     14|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 14, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|     28|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|     14|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|     14|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|     14|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|     14|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|     14|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1047:21): [True: 14, False: 0]
  ------------------
 1048|  8.15k|            }
 1049|  76.8M|            else if (RAPIDJSON_UNLIKELY(c == '"')) {    // Closing double quote
  ------------------
  |  |  505|  76.8M|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 5.97M, False: 70.8M]
  |  |  ------------------
  ------------------
 1050|  5.97M|                is.Take();
 1051|  5.97M|                os.Put('\0');   // null-terminate the string
 1052|  5.97M|                return;
 1053|  5.97M|            }
 1054|  70.8M|            else if (RAPIDJSON_UNLIKELY(static_cast<unsigned>(c) < 0x20)) { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
  ------------------
  |  |  505|  70.8M|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 92, False: 70.8M]
  |  |  ------------------
  ------------------
 1055|     92|                if (c == '\0')
  ------------------
  |  Branch (1055:21): [True: 82, False: 10]
  ------------------
 1056|     92|                    RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell());
  ------------------
  |  |  120|    164|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|     82|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|    164|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|     82|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|     82|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|     82|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|     82|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|     82|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|     82|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|     82|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|     82|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 82]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|    164|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|     82|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|    164|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|     82|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|    164|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|     82|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 82, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|    164|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|     82|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|     82|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|     82|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|     82|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|     82|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1056:21): [True: 82, False: 0]
  ------------------
 1057|     10|                else
 1058|     92|                    RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, is.Tell());
  ------------------
  |  |  120|     20|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|     10|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|     20|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|     10|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|     10|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|     10|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|     10|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|     10|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|     10|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|     10|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|     10|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 10]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|     20|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|     10|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|     20|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|     10|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|     20|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|     10|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 10, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|     20|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|     10|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|     10|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|     10|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|     10|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|     10|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1058:21): [True: 10, False: 0]
  ------------------
 1059|     92|            }
 1060|  70.8M|            else {
 1061|  70.8M|                size_t offset = is.Tell();
 1062|  70.8M|                if (RAPIDJSON_UNLIKELY((parseFlags & kParseValidateEncodingFlag ?
  ------------------
  |  |  505|   141M|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 0, False: 70.8M]
  |  |  |  Branch (505:51): [Folded, False: 70.8M]
  |  |  ------------------
  ------------------
 1063|  70.8M|                    !Transcoder<SEncoding, TEncoding>::Validate(is, os) :
 1064|  70.8M|                    !Transcoder<SEncoding, TEncoding>::Transcode(is, os))))
 1065|       |                    RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, offset);
  ------------------
  |  |  120|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|      0|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|      0|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|      0|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|      0|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|      0|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|      0|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 0, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1065:21): [True: 0, False: 0]
  ------------------
 1066|  70.8M|            }
 1067|  76.8M|        }
 1068|  5.97M|    }
_ZN9rapidjson13GenericReaderINS_4UTF8IcEES2_NS_12CrtAllocatorEE23ScanCopyUnescapedStringINS_25GenericInsituStringStreamIS2_EES7_EEvRT_RT0_:
 1071|  76.8M|    static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream&, OutputStream&) {
 1072|       |            // Do nothing for generic version
 1073|  76.8M|    }
_ZN9rapidjson13GenericReaderINS_4UTF8IcEES2_NS_12CrtAllocatorEE9ParseHex4INS_25GenericInsituStringStreamIS2_EEEEjRT_m:
  906|  1.31k|    unsigned ParseHex4(InputStream& is, size_t escapeOffset) {
  907|  1.31k|        unsigned codepoint = 0;
  908|  6.50k|        for (int i = 0; i < 4; i++) {
  ------------------
  |  Branch (908:25): [True: 5.21k, False: 1.29k]
  ------------------
  909|  5.21k|            Ch c = is.Peek();
  910|  5.21k|            codepoint <<= 4;
  911|  5.21k|            codepoint += static_cast<unsigned>(c);
  912|  5.21k|            if (c >= '0' && c <= '9')
  ------------------
  |  Branch (912:17): [True: 5.19k, False: 18]
  |  Branch (912:29): [True: 1.97k, False: 3.22k]
  ------------------
  913|  1.97k|                codepoint -= '0';
  914|  3.24k|            else if (c >= 'A' && c <= 'F')
  ------------------
  |  Branch (914:22): [True: 3.22k, False: 18]
  |  Branch (914:34): [True: 2.64k, False: 578]
  ------------------
  915|  2.64k|                codepoint -= 'A' - 10;
  916|    596|            else if (c >= 'a' && c <= 'f')
  ------------------
  |  Branch (916:22): [True: 574, False: 22]
  |  Branch (916:34): [True: 570, False: 4]
  ------------------
  917|    570|                codepoint -= 'a' - 10;
  918|     26|            else {
  919|     26|                RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorStringUnicodeEscapeInvalidHex, escapeOffset);
  ------------------
  |  |  101|     26|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|     26|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  102|     26|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  ------------------
  |  |  |  |  437|     26|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  ------------------
  |  |  103|     26|    SetParseError(parseErrorCode, offset); \
  |  |  104|     26|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|     26|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|     26|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 26]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (919:17): [True: 26, False: 0]
  ------------------
  920|     26|                RAPIDJSON_PARSE_ERROR_EARLY_RETURN(0);
  ------------------
  |  |   61|     52|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|     26|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |   62|     52|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  ------------------
  |  |  |  |  505|     26|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (505:31): [True: 26, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |   63|     52|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|     26|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|     26|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  921|     26|            }
  922|  5.19k|            is.Take();
  923|  5.19k|        }
  924|  1.29k|        return codepoint;
  925|  1.31k|    }
_ZN9rapidjson13GenericReaderINS_4UTF8IcEES2_NS_12CrtAllocatorEE7ConsumeINS_25GenericInsituStringStreamIS2_EEEEbRT_NS8_2ChE:
  895|  22.1M|    RAPIDJSON_FORCEINLINE static bool Consume(InputStream& is, typename InputStream::Ch expect) {
  896|  22.1M|        if (RAPIDJSON_LIKELY(is.Peek() == expect)) {
  ------------------
  |  |  492|  22.1M|#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (492:29): [True: 15.1M, False: 6.95M]
  |  |  ------------------
  ------------------
  897|  15.1M|            is.Take();
  898|  15.1M|            return true;
  899|  15.1M|        }
  900|  6.95M|        else
  901|  6.95M|            return false;
  902|  22.1M|    }
_ZN9rapidjson13GenericReaderINS_4UTF8IcEES2_NS_12CrtAllocatorEE10ClearStackEv:
  698|  14.0k|    void ClearStack() { stack_.Clear(); }
_ZN9rapidjson13GenericReaderINS_4UTF8IcEES2_NS_12CrtAllocatorEE25SkipWhitespaceAndCommentsILj1ENS_25GenericInsituStringStreamIS2_EEEEvRT0_:
  711|  45.8M|    void SkipWhitespaceAndComments(InputStream& is) {
  712|  45.8M|        SkipWhitespace(is);
  713|       |
  714|  45.8M|        if (parseFlags & kParseCommentsFlag) {
  ------------------
  |  Branch (714:13): [Folded, False: 45.8M]
  ------------------
  715|      0|            while (RAPIDJSON_UNLIKELY(Consume(is, '/'))) {
  ------------------
  |  |  505|      0|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  716|      0|                if (Consume(is, '*')) {
  ------------------
  |  Branch (716:21): [True: 0, False: 0]
  ------------------
  717|      0|                    while (true) {
  ------------------
  |  Branch (717:28): [True: 0, Folded]
  ------------------
  718|      0|                        if (RAPIDJSON_UNLIKELY(is.Peek() == '\0'))
  ------------------
  |  |  505|      0|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  719|      0|                            RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
  ------------------
  |  |  120|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|      0|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|      0|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|      0|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|      0|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|      0|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|      0|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 0, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (719:29): [True: 0, False: 0]
  ------------------
  720|      0|                        else if (Consume(is, '*')) {
  ------------------
  |  Branch (720:34): [True: 0, False: 0]
  ------------------
  721|      0|                            if (Consume(is, '/'))
  ------------------
  |  Branch (721:33): [True: 0, False: 0]
  ------------------
  722|      0|                                break;
  723|      0|                        }
  724|      0|                        else
  725|      0|                            is.Take();
  726|      0|                    }
  727|      0|                }
  728|      0|                else if (RAPIDJSON_LIKELY(Consume(is, '/')))
  ------------------
  |  |  492|      0|#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (492:29): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  729|      0|                    while (is.Peek() != '\0' && is.Take() != '\n') {}
  ------------------
  |  Branch (729:28): [True: 0, False: 0]
  |  Branch (729:49): [True: 0, False: 0]
  ------------------
  730|      0|                else
  731|      0|                    RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
  ------------------
  |  |  120|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|      0|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|      0|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|      0|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|      0|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|      0|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|      0|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 0, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (731:21): [True: 0, False: 0]
  ------------------
  732|       |
  733|      0|                SkipWhitespace(is);
  734|      0|            }
  735|      0|        }
  736|  45.8M|    }
_ZN9rapidjson14SkipWhitespaceINS_25GenericInsituStringStreamINS_4UTF8IcEEEEEEvRT_:
  266|  45.8M|void SkipWhitespace(InputStream& is) {
  267|  45.8M|    internal::StreamLocalCopy<InputStream> copy(is);
  268|  45.8M|    InputStream& s(copy.s);
  269|       |
  270|  45.8M|    typename InputStream::Ch c;
  271|  72.7M|    while ((c = s.Peek()) == ' ' || c == '\n' || c == '\r' || c == '\t')
  ------------------
  |  Branch (271:12): [True: 23.9M, False: 48.7M]
  |  Branch (271:37): [True: 2.84M, False: 45.9M]
  |  Branch (271:50): [True: 18.2k, False: 45.8M]
  |  Branch (271:63): [True: 14.1k, False: 45.8M]
  ------------------
  272|  26.8M|        s.Take();
  273|  45.8M|}
_ZNK9rapidjson13GenericReaderINS_4UTF8IcEES2_NS_12CrtAllocatorEE13HasParseErrorEv:
  682|  77.0M|    bool HasParseError() const { return parseResult_.IsError(); }
_ZN9rapidjson13GenericReaderINS_4UTF8IcEES2_NS_12CrtAllocatorEE13SetParseErrorENS_14ParseErrorCodeEm:
  691|  2.48k|    void SetParseError(ParseErrorCode code, size_t offset) { parseResult_.Set(code, offset); }
_ZN9rapidjson13GenericReaderINS_4UTF8IcEES2_NS_12CrtAllocatorEE10ParseValueILj1ENS_25GenericInsituStringStreamIS2_EENS_15GenericDocumentIS2_NS_19MemoryPoolAllocatorIS3_EES3_EEEEvRT0_RT1_:
 1752|  19.5M|    void ParseValue(InputStream& is, Handler& handler) {
 1753|  19.5M|        switch (is.Peek()) {
 1754|  7.69k|            case 'n': ParseNull  <parseFlags>(is, handler); break;
  ------------------
  |  Branch (1754:13): [True: 7.69k, False: 19.5M]
  ------------------
 1755|  11.4k|            case 't': ParseTrue  <parseFlags>(is, handler); break;
  ------------------
  |  Branch (1755:13): [True: 11.4k, False: 19.5M]
  ------------------
 1756|  30.4k|            case 'f': ParseFalse <parseFlags>(is, handler); break;
  ------------------
  |  Branch (1756:13): [True: 30.4k, False: 19.5M]
  ------------------
 1757|   294k|            case '"': ParseString<parseFlags>(is, handler); break;
  ------------------
  |  Branch (1757:13): [True: 294k, False: 19.2M]
  ------------------
 1758|   511k|            case '{': ParseObject<parseFlags>(is, handler); break;
  ------------------
  |  Branch (1758:13): [True: 511k, False: 19.0M]
  ------------------
 1759|  5.49M|            case '[': ParseArray <parseFlags>(is, handler); break;
  ------------------
  |  Branch (1759:13): [True: 5.49M, False: 14.0M]
  ------------------
 1760|  13.1M|            default :
  ------------------
  |  Branch (1760:13): [True: 13.1M, False: 6.35M]
  ------------------
 1761|  13.1M|                      ParseNumber<parseFlags>(is, handler);
 1762|  13.1M|                      break;
 1763|       |
 1764|  19.5M|        }
 1765|  19.5M|    }
_ZN9rapidjson13GenericReaderINS_4UTF8IcEES2_NS_12CrtAllocatorEE9ParseNullILj1ENS_25GenericInsituStringStreamIS2_EENS_15GenericDocumentIS2_NS_19MemoryPoolAllocatorIS3_EES3_EEEEvRT0_RT1_:
  856|  7.69k|    void ParseNull(InputStream& is, Handler& handler) {
  857|  7.69k|        RAPIDJSON_ASSERT(is.Peek() == 'n');
  ------------------
  |  |  437|  7.69k|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (857:9): [True: 7.69k, False: 0]
  ------------------
  858|  7.69k|        is.Take();
  859|       |
  860|  7.69k|        if (RAPIDJSON_LIKELY(Consume(is, 'u') && Consume(is, 'l') && Consume(is, 'l'))) {
  ------------------
  |  |  492|  30.7k|#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (492:29): [True: 7.67k, False: 22]
  |  |  |  Branch (492:49): [True: 7.67k, False: 14]
  |  |  |  Branch (492:49): [True: 7.67k, False: 2]
  |  |  |  Branch (492:49): [True: 7.67k, False: 6]
  |  |  ------------------
  ------------------
  861|  7.67k|            if (RAPIDJSON_UNLIKELY(!handler.Null()))
  ------------------
  |  |  505|  7.67k|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 0, False: 7.67k]
  |  |  ------------------
  ------------------
  862|  7.67k|                RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
  ------------------
  |  |  120|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|      0|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|      0|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|      0|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|      0|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|      0|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|      0|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 0, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (862:17): [True: 0, False: 0]
  ------------------
  863|  7.67k|        }
  864|     22|        else
  865|       |            RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
  ------------------
  |  |  120|     44|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|     22|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|     44|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|     22|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|     22|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|     22|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|     22|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|     22|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|     22|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|     22|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|     22|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 22]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|     44|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|     22|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|     44|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|     22|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|     44|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|     22|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 22, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|     44|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|     22|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|     22|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|     22|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|     22|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|     22|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (865:13): [True: 22, False: 0]
  ------------------
  866|  7.69k|    }
_ZN9rapidjson13GenericReaderINS_4UTF8IcEES2_NS_12CrtAllocatorEE9ParseTrueILj1ENS_25GenericInsituStringStreamIS2_EENS_15GenericDocumentIS2_NS_19MemoryPoolAllocatorIS3_EES3_EEEEvRT0_RT1_:
  869|  11.4k|    void ParseTrue(InputStream& is, Handler& handler) {
  870|  11.4k|        RAPIDJSON_ASSERT(is.Peek() == 't');
  ------------------
  |  |  437|  11.4k|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (870:9): [True: 11.4k, False: 0]
  ------------------
  871|  11.4k|        is.Take();
  872|       |
  873|  11.4k|        if (RAPIDJSON_LIKELY(Consume(is, 'r') && Consume(is, 'u') && Consume(is, 'e'))) {
  ------------------
  |  |  492|  45.8k|#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (492:29): [True: 11.4k, False: 38]
  |  |  |  Branch (492:49): [True: 11.4k, False: 10]
  |  |  |  Branch (492:49): [True: 11.4k, False: 6]
  |  |  |  Branch (492:49): [True: 11.4k, False: 22]
  |  |  ------------------
  ------------------
  874|  11.4k|            if (RAPIDJSON_UNLIKELY(!handler.Bool(true)))
  ------------------
  |  |  505|  11.4k|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 0, False: 11.4k]
  |  |  ------------------
  ------------------
  875|  11.4k|                RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
  ------------------
  |  |  120|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|      0|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|      0|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|      0|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|      0|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|      0|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|      0|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 0, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (875:17): [True: 0, False: 0]
  ------------------
  876|  11.4k|        }
  877|     38|        else
  878|       |            RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
  ------------------
  |  |  120|     76|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|     38|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|     76|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|     38|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|     38|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|     38|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|     38|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|     38|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|     38|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|     38|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|     38|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 38]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|     76|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|     38|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|     76|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|     38|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|     76|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|     38|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 38, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|     76|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|     38|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|     38|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|     38|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|     38|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|     38|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (878:13): [True: 38, False: 0]
  ------------------
  879|  11.4k|    }
_ZN9rapidjson13GenericReaderINS_4UTF8IcEES2_NS_12CrtAllocatorEE10ParseFalseILj1ENS_25GenericInsituStringStreamIS2_EENS_15GenericDocumentIS2_NS_19MemoryPoolAllocatorIS3_EES3_EEEEvRT0_RT1_:
  882|  30.4k|    void ParseFalse(InputStream& is, Handler& handler) {
  883|  30.4k|        RAPIDJSON_ASSERT(is.Peek() == 'f');
  ------------------
  |  |  437|  30.4k|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (883:9): [True: 30.4k, False: 0]
  ------------------
  884|  30.4k|        is.Take();
  885|       |
  886|  30.4k|        if (RAPIDJSON_LIKELY(Consume(is, 'a') && Consume(is, 'l') && Consume(is, 's') && Consume(is, 'e'))) {
  ------------------
  |  |  492|   182k|#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (492:29): [True: 30.3k, False: 20]
  |  |  |  Branch (492:49): [True: 30.4k, False: 6]
  |  |  |  Branch (492:49): [True: 30.4k, False: 6]
  |  |  |  Branch (492:49): [True: 30.3k, False: 6]
  |  |  |  Branch (492:49): [True: 30.3k, False: 2]
  |  |  ------------------
  ------------------
  887|  30.3k|            if (RAPIDJSON_UNLIKELY(!handler.Bool(false)))
  ------------------
  |  |  505|  30.3k|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 0, False: 30.3k]
  |  |  ------------------
  ------------------
  888|  30.3k|                RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
  ------------------
  |  |  120|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|      0|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|      0|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|      0|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|      0|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|      0|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|      0|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 0, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (888:17): [True: 0, False: 0]
  ------------------
  889|  30.3k|        }
  890|     20|        else
  891|       |            RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
  ------------------
  |  |  120|     40|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|     20|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|     40|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|     20|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|     20|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|     20|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|     20|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|     20|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|     20|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|     20|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|     20|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 20]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|     40|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|     20|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|     40|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|     20|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|     40|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|     20|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 20, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|     40|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|     20|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|     20|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|     20|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|     20|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|     20|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (891:13): [True: 20, False: 0]
  ------------------
  892|  30.4k|    }
_ZN9rapidjson13GenericReaderINS_4UTF8IcEES2_NS_12CrtAllocatorEE11ParseObjectILj1ENS_25GenericInsituStringStreamIS2_EENS_15GenericDocumentIS2_NS_19MemoryPoolAllocatorIS3_EES3_EEEEvRT0_RT1_:
  740|   511k|    void ParseObject(InputStream& is, Handler& handler) {
  741|   511k|        RAPIDJSON_ASSERT(is.Peek() == '{');
  ------------------
  |  |  437|   511k|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (741:9): [True: 511k, False: 0]
  ------------------
  742|   511k|        is.Take();  // Skip '{'
  743|       |
  744|   511k|        if (RAPIDJSON_UNLIKELY(!handler.StartObject()))
  ------------------
  |  |  505|   511k|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 0, False: 511k]
  |  |  ------------------
  ------------------
  745|   511k|            RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
  ------------------
  |  |  120|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|      0|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|      0|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|      0|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|      0|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|      0|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|      0|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 0, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (745:13): [True: 0, False: 0]
  ------------------
  746|       |
  747|   511k|        SkipWhitespaceAndComments<parseFlags>(is);
  748|   511k|        RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
  ------------------
  |  |   66|   511k|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  ------------------
  |  |  |  |   61|   511k|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|   511k|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |   62|   511k|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  ------------------
  |  |  |  |  |  |  505|   511k|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (505:31): [True: 0, False: 511k]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |   63|   511k|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|   511k|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|   511k|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 511k]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  749|       |
  750|   511k|        if (Consume(is, '}')) {
  ------------------
  |  Branch (750:13): [True: 3.57k, False: 508k]
  ------------------
  751|  3.57k|            if (RAPIDJSON_UNLIKELY(!handler.EndObject(0)))  // empty object
  ------------------
  |  |  505|  3.57k|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 0, False: 3.57k]
  |  |  ------------------
  ------------------
  752|  3.57k|                RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
  ------------------
  |  |  120|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|      0|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|      0|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|      0|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|      0|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|      0|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|      0|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 0, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (752:17): [True: 0, False: 0]
  ------------------
  753|  3.57k|            return;
  754|  3.57k|        }
  755|       |
  756|  5.67M|        for (SizeType memberCount = 0;;) {
  757|  5.67M|            if (RAPIDJSON_UNLIKELY(is.Peek() != '"'))
  ------------------
  |  |  505|  5.67M|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 118, False: 5.67M]
  |  |  ------------------
  ------------------
  758|  5.67M|                RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell());
  ------------------
  |  |  120|    236|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|    118|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|    236|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|    118|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|    118|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|    118|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|    118|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|    118|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|    118|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|    118|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|    118|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 118]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|    236|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|    118|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|    236|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|    118|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|    236|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|    118|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 118, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|    236|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|    118|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|    118|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|    118|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|    118|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|    118|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (758:17): [True: 118, False: 0]
  ------------------
  759|       |
  760|  5.67M|            ParseString<parseFlags>(is, handler, true);
  761|  5.67M|            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
  ------------------
  |  |   66|  5.67M|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  ------------------
  |  |  |  |   61|  5.67M|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|  5.67M|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |   62|  5.67M|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  ------------------
  |  |  |  |  |  |  505|  5.67M|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (505:31): [True: 54, False: 5.67M]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |   63|  5.67M|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|  5.67M|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|  5.67M|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 5.67M]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  762|       |
  763|  5.67M|            SkipWhitespaceAndComments<parseFlags>(is);
  764|  5.67M|            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
  ------------------
  |  |   66|  5.67M|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  ------------------
  |  |  |  |   61|  5.67M|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|  5.67M|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |   62|  5.67M|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  ------------------
  |  |  |  |  |  |  505|  5.67M|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (505:31): [True: 0, False: 5.67M]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |   63|  5.67M|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|  5.67M|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|  5.67M|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 5.67M]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  765|       |
  766|  5.67M|            if (RAPIDJSON_UNLIKELY(!Consume(is, ':')))
  ------------------
  |  |  505|  5.67M|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 90, False: 5.67M]
  |  |  ------------------
  ------------------
  767|  5.67M|                RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell());
  ------------------
  |  |  120|    180|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|     90|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|    180|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|     90|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|     90|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|     90|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|     90|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|     90|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|     90|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|     90|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|     90|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 90]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|    180|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|     90|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|    180|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|     90|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|    180|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|     90|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 90, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|    180|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|     90|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|     90|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|     90|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|     90|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|     90|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (767:17): [True: 90, False: 0]
  ------------------
  768|       |
  769|  5.67M|            SkipWhitespaceAndComments<parseFlags>(is);
  770|  5.67M|            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
  ------------------
  |  |   66|  5.67M|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  ------------------
  |  |  |  |   61|  5.67M|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|  5.67M|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |   62|  5.67M|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  ------------------
  |  |  |  |  |  |  505|  5.67M|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (505:31): [True: 0, False: 5.67M]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |   63|  5.67M|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|  5.67M|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|  5.67M|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 5.67M]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  771|       |
  772|  5.67M|            ParseValue<parseFlags>(is, handler);
  773|  5.67M|            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
  ------------------
  |  |   66|  5.67M|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  ------------------
  |  |  |  |   61|  5.67M|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|  5.67M|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |   62|  5.67M|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  ------------------
  |  |  |  |  |  |  505|  5.67M|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (505:31): [True: 40.8k, False: 5.63M]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |   63|  5.67M|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|  5.67M|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|  5.67M|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 5.63M]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  774|       |
  775|  5.63M|            SkipWhitespaceAndComments<parseFlags>(is);
  776|  5.63M|            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
  ------------------
  |  |   66|  5.63M|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  ------------------
  |  |  |  |   61|  5.63M|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|  5.63M|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |   62|  5.63M|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  ------------------
  |  |  |  |  |  |  505|  5.63M|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (505:31): [True: 0, False: 5.63M]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |   63|  5.63M|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|  5.63M|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|  5.63M|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 5.63M]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  777|       |
  778|  5.63M|            ++memberCount;
  779|       |
  780|  5.63M|            switch (is.Peek()) {
  781|  5.16M|                case ',':
  ------------------
  |  Branch (781:17): [True: 5.16M, False: 467k]
  ------------------
  782|  5.16M|                    is.Take();
  783|  5.16M|                    SkipWhitespaceAndComments<parseFlags>(is);
  784|  5.16M|                    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
  ------------------
  |  |   66|  5.16M|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  ------------------
  |  |  |  |   61|  5.16M|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|  5.16M|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |   62|  5.16M|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  ------------------
  |  |  |  |  |  |  505|  5.16M|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (505:31): [True: 0, False: 5.16M]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |   63|  5.16M|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|  5.16M|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|  5.16M|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 5.16M]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  785|  5.16M|                    break;
  786|  5.16M|                case '}':
  ------------------
  |  Branch (786:17): [True: 466k, False: 5.16M]
  ------------------
  787|   466k|                    is.Take();
  788|   466k|                    if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount)))
  ------------------
  |  |  505|   466k|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 0, False: 466k]
  |  |  ------------------
  ------------------
  789|   466k|                        RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
  ------------------
  |  |  120|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|      0|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|      0|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|      0|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|      0|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|      0|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|      0|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 0, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (789:25): [True: 0, False: 0]
  ------------------
  790|   466k|                    return;
  791|   466k|                default:
  ------------------
  |  Branch (791:17): [True: 102, False: 5.63M]
  ------------------
  792|    102|                    RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); break; // This useless break is only for making warning and coverage happy
  ------------------
  |  |  120|    102|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|    102|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|    102|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|    102|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|    102|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|    102|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|    102|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|    102|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|    102|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|    102|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|    102|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 102]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|    102|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|    102|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|    204|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|    102|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|    204|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|    102|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 102, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|    204|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|    102|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|    102|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|    102|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|    102|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|    102|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (792:21): [True: 102, False: 0]
  ------------------
  793|  5.63M|            }
  794|       |
  795|  5.16M|            if (parseFlags & kParseTrailingCommasFlag) {
  ------------------
  |  Branch (795:17): [Folded, False: 5.16M]
  ------------------
  796|      0|                if (is.Peek() == '}') {
  ------------------
  |  Branch (796:21): [True: 0, False: 0]
  ------------------
  797|      0|                    if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount)))
  ------------------
  |  |  505|      0|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  798|      0|                        RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
  ------------------
  |  |  120|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|      0|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|      0|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|      0|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|      0|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|      0|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|      0|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 0, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (798:25): [True: 0, False: 0]
  ------------------
  799|      0|                    is.Take();
  800|      0|                    return;
  801|      0|                }
  802|      0|            }
  803|  5.16M|        }
  804|   508k|    }
_ZN9rapidjson13GenericReaderINS_4UTF8IcEES2_NS_12CrtAllocatorEE10ParseArrayILj1ENS_25GenericInsituStringStreamIS2_EENS_15GenericDocumentIS2_NS_19MemoryPoolAllocatorIS3_EES3_EEEEvRT0_RT1_:
  808|  5.49M|    void ParseArray(InputStream& is, Handler& handler) {
  809|  5.49M|        RAPIDJSON_ASSERT(is.Peek() == '[');
  ------------------
  |  |  437|  5.49M|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (809:9): [True: 5.49M, False: 0]
  ------------------
  810|  5.49M|        is.Take();  // Skip '['
  811|       |
  812|  5.49M|        if (RAPIDJSON_UNLIKELY(!handler.StartArray()))
  ------------------
  |  |  505|  5.49M|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 0, False: 5.49M]
  |  |  ------------------
  ------------------
  813|  5.49M|            RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
  ------------------
  |  |  120|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|      0|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|      0|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|      0|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|      0|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|      0|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|      0|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 0, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (813:13): [True: 0, False: 0]
  ------------------
  814|       |
  815|  5.49M|        SkipWhitespaceAndComments<parseFlags>(is);
  816|  5.49M|        RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
  ------------------
  |  |   66|  5.49M|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  ------------------
  |  |  |  |   61|  5.49M|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|  5.49M|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |   62|  5.49M|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  ------------------
  |  |  |  |  |  |  505|  5.49M|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (505:31): [True: 0, False: 5.49M]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |   63|  5.49M|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|  5.49M|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|  5.49M|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 5.49M]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  817|       |
  818|  5.49M|        if (Consume(is, ']')) {
  ------------------
  |  Branch (818:13): [True: 4.71k, False: 5.49M]
  ------------------
  819|  4.71k|            if (RAPIDJSON_UNLIKELY(!handler.EndArray(0))) // empty array
  ------------------
  |  |  505|  4.71k|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 0, False: 4.71k]
  |  |  ------------------
  ------------------
  820|  4.71k|                RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
  ------------------
  |  |  120|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|      0|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|      0|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|      0|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|      0|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|      0|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|      0|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 0, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (820:17): [True: 0, False: 0]
  ------------------
  821|  4.71k|            return;
  822|  4.71k|        }
  823|       |
  824|  13.8M|        for (SizeType elementCount = 0;;) {
  825|  13.8M|            ParseValue<parseFlags>(is, handler);
  826|  13.8M|            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
  ------------------
  |  |   66|  13.8M|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  ------------------
  |  |  |  |   61|  13.8M|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|  13.8M|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |   62|  13.8M|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  ------------------
  |  |  |  |  |  |  505|  13.8M|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (505:31): [True: 4.54M, False: 9.31M]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |   63|  13.8M|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|  13.8M|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|  13.8M|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 9.31M]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  827|       |
  828|  9.31M|            ++elementCount;
  829|  9.31M|            SkipWhitespaceAndComments<parseFlags>(is);
  830|  9.31M|            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
  ------------------
  |  |   66|  9.31M|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  ------------------
  |  |  |  |   61|  9.31M|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|  9.31M|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |   62|  9.31M|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  ------------------
  |  |  |  |  |  |  505|  9.31M|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (505:31): [True: 0, False: 9.31M]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |   63|  9.31M|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|  9.31M|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|  9.31M|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 9.31M]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  831|       |
  832|  9.31M|            if (Consume(is, ',')) {
  ------------------
  |  Branch (832:17): [True: 8.36M, False: 950k]
  ------------------
  833|  8.36M|                SkipWhitespaceAndComments<parseFlags>(is);
  834|  8.36M|                RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
  ------------------
  |  |   66|  8.36M|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  ------------------
  |  |  |  |   61|  8.36M|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|  8.36M|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |   62|  8.36M|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  ------------------
  |  |  |  |  |  |  505|  8.36M|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (505:31): [True: 0, False: 8.36M]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |   63|  8.36M|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|  8.36M|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|  8.36M|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 8.36M]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  835|  8.36M|            }
  836|   950k|            else if (Consume(is, ']')) {
  ------------------
  |  Branch (836:22): [True: 949k, False: 824]
  ------------------
  837|   949k|                if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount)))
  ------------------
  |  |  505|   949k|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 0, False: 949k]
  |  |  ------------------
  ------------------
  838|   949k|                    RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
  ------------------
  |  |  120|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|      0|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|      0|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|      0|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|      0|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|      0|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|      0|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 0, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (838:21): [True: 0, False: 0]
  ------------------
  839|   949k|                return;
  840|   949k|            }
  841|    824|            else
  842|   950k|                RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());
  ------------------
  |  |  120|  1.64k|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|    824|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|  1.64k|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|    824|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|    824|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|    824|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|    824|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|    824|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|    824|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|    824|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|    824|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 824]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|  1.64k|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|    824|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|  1.64k|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|    824|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|  1.64k|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|    824|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 824, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|  1.64k|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|    824|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|    824|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|    824|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|    824|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|    824|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (842:17): [True: 824, False: 0]
  ------------------
  843|       |
  844|  8.36M|            if (parseFlags & kParseTrailingCommasFlag) {
  ------------------
  |  Branch (844:17): [Folded, False: 8.36M]
  ------------------
  845|      0|                if (is.Peek() == ']') {
  ------------------
  |  Branch (845:21): [True: 0, False: 0]
  ------------------
  846|      0|                    if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount)))
  ------------------
  |  |  505|      0|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  847|      0|                        RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
  ------------------
  |  |  120|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|      0|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|      0|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|      0|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|      0|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|      0|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|      0|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 0, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (847:25): [True: 0, False: 0]
  ------------------
  848|      0|                    is.Take();
  849|      0|                    return;
  850|      0|                }
  851|      0|            }
  852|  8.36M|        }
  853|  5.49M|    }
_ZN9rapidjson13GenericReaderINS_4UTF8IcEES2_NS_12CrtAllocatorEE11ParseNumberILj1ENS_25GenericInsituStringStreamIS2_EENS_15GenericDocumentIS2_NS_19MemoryPoolAllocatorIS3_EES3_EEEEvRT0_RT1_:
 1468|  13.1M|    void ParseNumber(InputStream& is, Handler& handler) {
 1469|  13.1M|        typedef typename internal::SelectIf<internal::BoolType<(parseFlags & kParseNumbersAsStringsFlag) != 0>, typename TargetEncoding::Ch, char>::Type NumberCharacter;
 1470|       |
 1471|  13.1M|        internal::StreamLocalCopy<InputStream> copy(is);
 1472|  13.1M|        NumberStream<InputStream, NumberCharacter,
 1473|  13.1M|            ((parseFlags & kParseNumbersAsStringsFlag) != 0) ?
 1474|  13.1M|                ((parseFlags & kParseInsituFlag) == 0) :
 1475|  13.1M|                ((parseFlags & kParseFullPrecisionFlag) != 0),
 1476|  13.1M|            (parseFlags & kParseNumbersAsStringsFlag) != 0 &&
 1477|  13.1M|                (parseFlags & kParseInsituFlag) == 0> s(*this, copy.s);
 1478|       |
 1479|  13.1M|        size_t startOffset = s.Tell();
 1480|  13.1M|        double d = 0.0;
 1481|  13.1M|        bool useNanOrInf = false;
 1482|       |
 1483|       |        // Parse minus
 1484|  13.1M|        bool minus = Consume(s, '-');
 1485|       |
 1486|       |        // Parse int: zero / ( digit1-9 *DIGIT )
 1487|  13.1M|        unsigned i = 0;
 1488|  13.1M|        uint64_t i64 = 0;
 1489|  13.1M|        bool use64bit = false;
 1490|  13.1M|        int significandDigit = 0;
 1491|  13.1M|        if (RAPIDJSON_UNLIKELY(s.Peek() == '0')) {
  ------------------
  |  |  505|  13.1M|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 4.16M, False: 9.03M]
  |  |  ------------------
  ------------------
 1492|  4.16M|            i = 0;
 1493|  4.16M|            s.TakePush();
 1494|  4.16M|        }
 1495|  9.03M|        else if (RAPIDJSON_LIKELY(s.Peek() >= '1' && s.Peek() <= '9')) {
  ------------------
  |  |  492|  18.0M|#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (492:29): [True: 9.03M, False: 724]
  |  |  |  Branch (492:49): [True: 9.03M, False: 638]
  |  |  |  Branch (492:49): [True: 9.03M, False: 86]
  |  |  ------------------
  ------------------
 1496|  9.03M|            i = static_cast<unsigned>(s.TakePush() - '0');
 1497|       |
 1498|  9.03M|            if (minus)
  ------------------
  |  Branch (1498:17): [True: 219k, False: 8.81M]
  ------------------
 1499|   439k|                while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
  ------------------
  |  |  492|   674k|#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (492:29): [True: 231k, False: 208k]
  |  |  |  Branch (492:49): [True: 234k, False: 205k]
  |  |  |  Branch (492:49): [True: 231k, False: 2.82k]
  |  |  ------------------
  ------------------
 1500|   231k|                    if (RAPIDJSON_UNLIKELY(i >= 214748364)) { // 2^31 = 2147483648
  ------------------
  |  |  505|   231k|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 10.9k, False: 220k]
  |  |  ------------------
  ------------------
 1501|  10.9k|                        if (RAPIDJSON_LIKELY(i != 214748364 || s.Peek() > '8')) {
  ------------------
  |  |  492|  11.3k|#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (492:29): [True: 10.6k, False: 342]
  |  |  |  Branch (492:49): [True: 10.5k, False: 360]
  |  |  |  Branch (492:49): [True: 18, False: 342]
  |  |  ------------------
  ------------------
 1502|  10.6k|                            i64 = i;
 1503|  10.6k|                            use64bit = true;
 1504|  10.6k|                            break;
 1505|  10.6k|                        }
 1506|  10.9k|                    }
 1507|   220k|                    i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
 1508|   220k|                    significandDigit++;
 1509|   220k|                }
 1510|  8.81M|            else
 1511|  10.6M|                while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
  ------------------
  |  |  492|  12.7M|#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (492:29): [True: 1.93M, False: 8.74M]
  |  |  |  Branch (492:49): [True: 2.05M, False: 8.63M]
  |  |  |  Branch (492:49): [True: 1.93M, False: 115k]
  |  |  ------------------
  ------------------
 1512|  1.93M|                    if (RAPIDJSON_UNLIKELY(i >= 429496729)) { // 2^32 - 1 = 4294967295
  ------------------
  |  |  505|  1.93M|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 65.5k, False: 1.87M]
  |  |  ------------------
  ------------------
 1513|  65.5k|                        if (RAPIDJSON_LIKELY(i != 429496729 || s.Peek() > '5')) {
  ------------------
  |  |  492|  68.3k|#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (492:29): [True: 64.1k, False: 1.36k]
  |  |  |  Branch (492:49): [True: 62.6k, False: 2.88k]
  |  |  |  Branch (492:49): [True: 1.51k, False: 1.36k]
  |  |  ------------------
  ------------------
 1514|  64.1k|                            i64 = i;
 1515|  64.1k|                            use64bit = true;
 1516|  64.1k|                            break;
 1517|  64.1k|                        }
 1518|  65.5k|                    }
 1519|  1.87M|                    i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
 1520|  1.87M|                    significandDigit++;
 1521|  1.87M|                }
 1522|  9.03M|        }
 1523|       |        // Parse NaN or Infinity here
 1524|    724|        else if ((parseFlags & kParseNanAndInfFlag) && RAPIDJSON_LIKELY((s.Peek() == 'I' || s.Peek() == 'N'))) {
  ------------------
  |  |  492|      0|#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (492:29): [True: 0, False: 0]
  |  |  |  Branch (492:49): [True: 0, False: 0]
  |  |  |  Branch (492:49): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (1524:18): [Folded, False: 724]
  ------------------
 1525|      0|            if (Consume(s, 'N')) {
  ------------------
  |  Branch (1525:17): [True: 0, False: 0]
  ------------------
 1526|      0|                if (Consume(s, 'a') && Consume(s, 'N')) {
  ------------------
  |  Branch (1526:21): [True: 0, False: 0]
  |  Branch (1526:40): [True: 0, False: 0]
  ------------------
 1527|      0|                    d = std::numeric_limits<double>::quiet_NaN();
 1528|      0|                    useNanOrInf = true;
 1529|      0|                }
 1530|      0|            }
 1531|      0|            else if (RAPIDJSON_LIKELY(Consume(s, 'I'))) {
  ------------------
  |  |  492|      0|#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (492:29): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1532|      0|                if (Consume(s, 'n') && Consume(s, 'f')) {
  ------------------
  |  Branch (1532:21): [True: 0, False: 0]
  |  Branch (1532:40): [True: 0, False: 0]
  ------------------
 1533|      0|                    d = (minus ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity());
  ------------------
  |  Branch (1533:26): [True: 0, False: 0]
  ------------------
 1534|      0|                    useNanOrInf = true;
 1535|       |
 1536|      0|                    if (RAPIDJSON_UNLIKELY(s.Peek() == 'i' && !(Consume(s, 'i') && Consume(s, 'n')
  ------------------
  |  |  505|      0|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 0, False: 0]
  |  |  |  Branch (505:51): [True: 0, False: 0]
  |  |  |  Branch (505:51): [True: 0, False: 0]
  |  |  |  Branch (505:51): [True: 0, False: 0]
  |  |  |  Branch (505:51): [True: 0, False: 0]
  |  |  |  Branch (505:51): [True: 0, False: 0]
  |  |  |  Branch (505:51): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1537|      0|                                                                && Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y')))) {
 1538|      0|                        RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
  ------------------
  |  |  120|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|      0|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|      0|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|      0|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|      0|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|      0|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|      0|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 0, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1538:25): [True: 0, False: 0]
  ------------------
 1539|      0|                    }
 1540|      0|                }
 1541|      0|            }
 1542|       |
 1543|      0|            if (RAPIDJSON_UNLIKELY(!useNanOrInf)) {
  ------------------
  |  |  505|      0|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1544|      0|                RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
  ------------------
  |  |  120|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|      0|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|      0|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|      0|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|      0|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|      0|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|      0|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 0, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1544:17): [True: 0, False: 0]
  ------------------
 1545|      0|            }
 1546|      0|        }
 1547|    724|        else
 1548|    724|            RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
  ------------------
  |  |  120|  1.44k|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|    724|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|  1.44k|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|    724|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|    724|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|    724|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|    724|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|    724|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|    724|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|    724|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|    724|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 724]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|  1.44k|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|    724|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|  1.44k|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|    724|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|  1.44k|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|    724|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 724, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|  1.44k|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|    724|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|    724|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|    724|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|    724|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|    724|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1548:13): [True: 724, False: 0]
  ------------------
 1549|       |
 1550|       |        // Parse 64bit int
 1551|  13.1M|        bool useDouble = false;
 1552|  13.1M|        if (use64bit) {
  ------------------
  |  Branch (1552:13): [True: 74.7k, False: 13.1M]
  ------------------
 1553|  74.7k|            if (minus)
  ------------------
  |  Branch (1553:17): [True: 10.6k, False: 64.1k]
  ------------------
 1554|  94.5k|                while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
  ------------------
  |  |  492|   182k|#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (492:29): [True: 88.0k, False: 6.45k]
  |  |  |  Branch (492:49): [True: 88.2k, False: 6.29k]
  |  |  |  Branch (492:49): [True: 88.0k, False: 167]
  |  |  ------------------
  ------------------
 1555|  88.0k|                     if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC))) // 2^63 = 9223372036854775808
  ------------------
  |  |  505|  88.0k|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 8.41k, False: 79.6k]
  |  |  ------------------
  ------------------
 1556|  8.41k|                        if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8')) {
  ------------------
  |  |  492|  12.9k|#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (492:29): [True: 4.14k, False: 4.26k]
  |  |  |  Branch (492:49): [True: 3.91k, False: 4.49k]
  |  |  |  Branch (492:49): [True: 234, False: 4.26k]
  |  |  ------------------
  ------------------
 1557|  4.14k|                            d = static_cast<double>(i64);
 1558|  4.14k|                            useDouble = true;
 1559|  4.14k|                            break;
 1560|  4.14k|                        }
 1561|  83.8k|                    i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
 1562|  83.8k|                    significandDigit++;
 1563|  83.8k|                }
 1564|  64.1k|            else
 1565|   534k|                while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
  ------------------
  |  |  492|  1.02M|#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (492:29): [True: 489k, False: 44.3k]
  |  |  |  Branch (492:49): [True: 492k, False: 41.1k]
  |  |  |  Branch (492:49): [True: 489k, False: 3.26k]
  |  |  ------------------
  ------------------
 1566|   489k|                    if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999))) // 2^64 - 1 = 18446744073709551615
  ------------------
  |  |  505|   489k|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 27.5k, False: 462k]
  |  |  ------------------
  ------------------
 1567|  27.5k|                        if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5')) {
  ------------------
  |  |  492|  36.0k|#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (492:29): [True: 19.7k, False: 7.78k]
  |  |  |  Branch (492:49): [True: 19.0k, False: 8.45k]
  |  |  |  Branch (492:49): [True: 669, False: 7.78k]
  |  |  ------------------
  ------------------
 1568|  19.7k|                            d = static_cast<double>(i64);
 1569|  19.7k|                            useDouble = true;
 1570|  19.7k|                            break;
 1571|  19.7k|                        }
 1572|   469k|                    i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
 1573|   469k|                    significandDigit++;
 1574|   469k|                }
 1575|  74.7k|        }
 1576|       |
 1577|       |        // Force double for big integer
 1578|  13.1M|        if (useDouble) {
  ------------------
  |  Branch (1578:13): [True: 23.9k, False: 13.1M]
  ------------------
 1579|  5.87M|            while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
  ------------------
  |  |  492|  11.7M|#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (492:29): [True: 5.85M, False: 23.9k]
  |  |  |  Branch (492:49): [True: 5.85M, False: 23.1k]
  |  |  |  Branch (492:49): [True: 5.85M, False: 744]
  |  |  ------------------
  ------------------
 1580|  5.85M|                d = d * 10 + (s.TakePush() - '0');
 1581|  5.85M|            }
 1582|  23.9k|        }
 1583|       |
 1584|       |        // Parse frac = decimal-point 1*DIGIT
 1585|  13.1M|        int expFrac = 0;
 1586|  13.1M|        size_t decimalPosition;
 1587|  13.1M|        if (Consume(s, '.')) {
  ------------------
  |  Branch (1587:13): [True: 884k, False: 12.3M]
  ------------------
 1588|   884k|            decimalPosition = s.Length();
 1589|       |
 1590|   884k|            if (RAPIDJSON_UNLIKELY(!(s.Peek() >= '0' && s.Peek() <= '9')))
  ------------------
  |  |  505|  1.76M|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 18, False: 884k]
  |  |  |  Branch (505:51): [True: 884k, False: 18]
  |  |  |  Branch (505:51): [True: 884k, False: 0]
  |  |  ------------------
  ------------------
 1591|   884k|                RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell());
  ------------------
  |  |  120|     36|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|     18|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|     36|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|     18|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|     18|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|     18|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|     18|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|     18|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|     18|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|     18|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|     18|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 18]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|     36|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|     18|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|     36|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|     18|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|     36|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|     18|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 18, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|     36|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|     18|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|     18|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|     18|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|     18|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|     18|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1591:17): [True: 18, False: 0]
  ------------------
 1592|       |
 1593|   884k|            if (!useDouble) {
  ------------------
  |  Branch (1593:17): [True: 881k, False: 3.64k]
  ------------------
 1594|   881k|#if RAPIDJSON_64BIT
 1595|       |                // Use i64 to store significand in 64-bit architecture
 1596|   881k|                if (!use64bit)
  ------------------
  |  Branch (1596:21): [True: 878k, False: 2.77k]
  ------------------
 1597|   878k|                    i64 = i;
 1598|       |
 1599|  11.0M|                while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
  ------------------
  |  |  492|  21.3M|#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (492:29): [True: 10.1M, False: 876k]
  |  |  |  Branch (492:49): [True: 10.3M, False: 763k]
  |  |  |  Branch (492:49): [True: 10.1M, False: 113k]
  |  |  ------------------
  ------------------
 1600|  10.1M|                    if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path
  ------------------
  |  |  320|  10.1M|#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32))
  ------------------
  |  Branch (1600:25): [True: 4.72k, False: 10.1M]
  ------------------
 1601|  4.72k|                        break;
 1602|  10.1M|                    else {
 1603|  10.1M|                        i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
 1604|  10.1M|                        --expFrac;
 1605|  10.1M|                        if (i64 != 0)
  ------------------
  |  Branch (1605:29): [True: 8.56M, False: 1.62M]
  ------------------
 1606|  8.56M|                            significandDigit++;
 1607|  10.1M|                    }
 1608|  10.1M|                }
 1609|       |
 1610|   881k|                d = static_cast<double>(i64);
 1611|       |#else
 1612|       |                // Use double to store significand in 32-bit architecture
 1613|       |                d = static_cast<double>(use64bit ? i64 : i);
 1614|       |#endif
 1615|   881k|                useDouble = true;
 1616|   881k|            }
 1617|       |
 1618|   967k|            while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
  ------------------
  |  |  492|  1.16M|#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (492:29): [True: 82.3k, False: 884k]
  |  |  |  Branch (492:49): [True: 198k, False: 768k]
  |  |  |  Branch (492:49): [True: 82.3k, False: 116k]
  |  |  ------------------
  ------------------
 1619|  82.3k|                if (significandDigit < 17) {
  ------------------
  |  Branch (1619:21): [True: 2.55k, False: 79.7k]
  ------------------
 1620|  2.55k|                    d = d * 10.0 + (s.TakePush() - '0');
 1621|  2.55k|                    --expFrac;
 1622|  2.55k|                    if (RAPIDJSON_LIKELY(d > 0.0))
  ------------------
  |  |  492|  2.55k|#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (492:29): [True: 2.55k, False: 0]
  |  |  ------------------
  ------------------
 1623|  2.55k|                        significandDigit++;
 1624|  2.55k|                }
 1625|  79.7k|                else
 1626|  79.7k|                    s.TakePush();
 1627|  82.3k|            }
 1628|   884k|        }
 1629|  12.3M|        else
 1630|  12.3M|            decimalPosition = s.Length(); // decimal position at the end of integer.
 1631|       |
 1632|       |        // Parse exp = e [ minus / plus ] 1*DIGIT
 1633|  13.1M|        int exp = 0;
 1634|  13.1M|        if (Consume(s, 'e') || Consume(s, 'E')) {
  ------------------
  |  Branch (1634:13): [True: 115k, False: 13.0M]
  |  Branch (1634:32): [True: 46.3k, False: 13.0M]
  ------------------
 1635|   161k|            if (!useDouble) {
  ------------------
  |  Branch (1635:17): [True: 69.3k, False: 92.1k]
  ------------------
 1636|  69.3k|                d = static_cast<double>(use64bit ? i64 : i);
  ------------------
  |  Branch (1636:41): [True: 3.29k, False: 66.0k]
  ------------------
 1637|  69.3k|                useDouble = true;
 1638|  69.3k|            }
 1639|       |
 1640|   161k|            bool expMinus = false;
 1641|   161k|            if (Consume(s, '+'))
  ------------------
  |  Branch (1641:17): [True: 385, False: 161k]
  ------------------
 1642|    385|                ;
 1643|   161k|            else if (Consume(s, '-'))
  ------------------
  |  Branch (1643:22): [True: 99.2k, False: 61.9k]
  ------------------
 1644|  99.2k|                expMinus = true;
 1645|       |
 1646|   161k|            if (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
  ------------------
  |  |  492|   322k|#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (492:29): [True: 161k, False: 64]
  |  |  |  Branch (492:49): [True: 161k, False: 48]
  |  |  |  Branch (492:49): [True: 161k, False: 16]
  |  |  ------------------
  ------------------
 1647|   161k|                exp = static_cast<int>(s.Take() - '0');
 1648|   161k|                if (expMinus) {
  ------------------
  |  Branch (1648:21): [True: 99.1k, False: 62.2k]
  ------------------
 1649|       |                    // (exp + expFrac) must not underflow int => we're detecting when -exp gets
 1650|       |                    // dangerously close to INT_MIN (a pessimistic next digit 9 would push it into
 1651|       |                    // underflow territory):
 1652|       |                    //
 1653|       |                    //        -(exp * 10 + 9) + expFrac >= INT_MIN
 1654|       |                    //   <=>  exp <= (expFrac - INT_MIN - 9) / 10
 1655|  99.1k|                    RAPIDJSON_ASSERT(expFrac <= 0);
  ------------------
  |  |  437|  99.1k|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (1655:21): [True: 99.1k, False: 0]
  ------------------
 1656|  99.1k|                    int maxExp = (expFrac + 2147483639) / 10;
 1657|       |
 1658|   176k|                    while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
  ------------------
  |  |  492|   255k|#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (492:29): [True: 77.5k, False: 99.1k]
  |  |  |  Branch (492:49): [True: 78.5k, False: 98.1k]
  |  |  |  Branch (492:49): [True: 77.5k, False: 1.02k]
  |  |  ------------------
  ------------------
 1659|  77.5k|                        exp = exp * 10 + static_cast<int>(s.Take() - '0');
 1660|  77.5k|                        if (RAPIDJSON_UNLIKELY(exp > maxExp)) {
  ------------------
  |  |  505|  77.5k|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 2.11k, False: 75.3k]
  |  |  ------------------
  ------------------
 1661|  22.3k|                            while (RAPIDJSON_UNLIKELY(s.Peek() >= '0' && s.Peek() <= '9'))  // Consume the rest of exponent
  ------------------
  |  |  505|  42.5k|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 20.1k, False: 2.11k]
  |  |  |  Branch (505:51): [True: 20.2k, False: 2.10k]
  |  |  |  Branch (505:51): [True: 20.1k, False: 16]
  |  |  ------------------
  ------------------
 1662|  20.1k|                                s.Take();
 1663|  2.11k|                        }
 1664|  77.5k|                    }
 1665|  99.1k|                }
 1666|  62.2k|                else {  // positive exp
 1667|  62.2k|                    int maxExp = 308 - expFrac;
 1668|  89.3k|                    while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
  ------------------
  |  |  492|   116k|#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (492:29): [True: 27.0k, False: 62.2k]
  |  |  |  Branch (492:49): [True: 27.2k, False: 62.1k]
  |  |  |  Branch (492:49): [True: 27.0k, False: 134]
  |  |  ------------------
  ------------------
 1669|  27.0k|                        exp = exp * 10 + static_cast<int>(s.Take() - '0');
 1670|  27.0k|                        if (RAPIDJSON_UNLIKELY(exp > maxExp))
  ------------------
  |  |  505|  27.0k|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 18, False: 27.0k]
  |  |  ------------------
  ------------------
 1671|  27.0k|                            RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset);
  ------------------
  |  |  120|     36|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|     18|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|     36|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|     18|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|     18|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|     18|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|     18|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|     18|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|     18|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|     18|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|     18|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 18]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|     36|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|     18|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|     36|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|     18|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|     36|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|     18|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 18, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|     36|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|     18|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|     18|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|     18|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|     18|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|     18|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1671:29): [True: 18, False: 0]
  ------------------
 1672|  27.0k|                    }
 1673|  62.2k|                }
 1674|   161k|            }
 1675|     64|            else
 1676|   161k|                RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissExponent, s.Tell());
  ------------------
  |  |  120|    128|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|     64|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|    128|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|     64|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|     64|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|     64|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|     64|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|     64|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|     64|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|     64|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|     64|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 64]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|    128|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|     64|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|    128|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|     64|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|    128|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|     64|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 64, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|    128|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|     64|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|     64|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|     64|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|     64|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|     64|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1676:17): [True: 64, False: 0]
  ------------------
 1677|       |
 1678|   161k|            if (expMinus)
  ------------------
  |  Branch (1678:17): [True: 99.1k, False: 62.2k]
  ------------------
 1679|  99.1k|                exp = -exp;
 1680|   161k|        }
 1681|       |
 1682|       |        // Finish parsing, call event according to the type of number.
 1683|  13.1M|        bool cont = true;
 1684|       |
 1685|  13.1M|        if (parseFlags & kParseNumbersAsStringsFlag) {
  ------------------
  |  Branch (1685:13): [Folded, False: 13.1M]
  ------------------
 1686|      0|            if (parseFlags & kParseInsituFlag) {
  ------------------
  |  Branch (1686:17): [True: 0, Folded]
  ------------------
 1687|      0|                s.Pop();  // Pop stack no matter if it will be used or not.
 1688|      0|                typename InputStream::Ch* head = is.PutBegin();
 1689|      0|                const size_t length = s.Tell() - startOffset;
 1690|      0|                RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
  ------------------
  |  |  437|      0|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (1690:17): [True: 0, False: 0]
  ------------------
 1691|       |                // unable to insert the \0 character here, it will erase the comma after this number
 1692|      0|                const typename TargetEncoding::Ch* const str = reinterpret_cast<typename TargetEncoding::Ch*>(head);
 1693|      0|                cont = handler.RawNumber(str, SizeType(length), false);
 1694|      0|            }
 1695|      0|            else {
 1696|      0|                SizeType numCharsToCopy = static_cast<SizeType>(s.Length());
 1697|      0|                GenericStringStream<UTF8<NumberCharacter> > srcStream(s.Pop());
 1698|      0|                StackStream<typename TargetEncoding::Ch> dstStream(stack_);
 1699|      0|                while (numCharsToCopy--) {
  ------------------
  |  Branch (1699:24): [True: 0, False: 0]
  ------------------
 1700|      0|                    Transcoder<UTF8<typename TargetEncoding::Ch>, TargetEncoding>::Transcode(srcStream, dstStream);
 1701|      0|                }
 1702|      0|                dstStream.Put('\0');
 1703|      0|                const typename TargetEncoding::Ch* str = dstStream.Pop();
 1704|      0|                const SizeType length = static_cast<SizeType>(dstStream.Length()) - 1;
 1705|      0|                cont = handler.RawNumber(str, SizeType(length), true);
 1706|      0|            }
 1707|      0|        }
 1708|  13.1M|        else {
 1709|  13.1M|           size_t length = s.Length();
 1710|  13.1M|           const NumberCharacter* decimal = s.Pop();  // Pop stack no matter if it will be used or not.
 1711|       |
 1712|  13.1M|           if (useDouble) {
  ------------------
  |  Branch (1712:16): [True: 974k, False: 12.2M]
  ------------------
 1713|   974k|               int p = exp + expFrac;
 1714|   974k|               if (parseFlags & kParseFullPrecisionFlag)
  ------------------
  |  Branch (1714:20): [Folded, False: 974k]
  ------------------
 1715|      0|                   d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp);
 1716|   974k|               else
 1717|   974k|                   d = internal::StrtodNormalPrecision(d, p);
 1718|       |
 1719|       |               // Use > max, instead of == inf, to fix bogus warning -Wfloat-equal
 1720|   974k|               if (d > (std::numeric_limits<double>::max)()) {
  ------------------
  |  Branch (1720:20): [True: 10, False: 974k]
  ------------------
 1721|       |                   // Overflow
 1722|       |                   // TODO: internal::StrtodX should report overflow (or underflow)
 1723|     10|                   RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset);
  ------------------
  |  |  120|     10|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|     10|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|     10|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|     10|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|     10|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|     10|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|     10|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|     10|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|     10|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|     10|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|     10|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 10]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|     10|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|     10|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|     20|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|     10|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|     20|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|     10|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 10, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|     20|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|     10|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|     10|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|     10|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|     10|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|     10|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1723:20): [True: 10, False: 0]
  ------------------
 1724|     10|               }
 1725|       |
 1726|   974k|               cont = handler.Double(minus ? -d : d);
  ------------------
  |  Branch (1726:38): [True: 297k, False: 677k]
  ------------------
 1727|   974k|           }
 1728|  12.2M|           else if (useNanOrInf) {
  ------------------
  |  Branch (1728:21): [True: 0, False: 12.2M]
  ------------------
 1729|      0|               cont = handler.Double(d);
 1730|      0|           }
 1731|  12.2M|           else {
 1732|  12.2M|               if (use64bit) {
  ------------------
  |  Branch (1732:20): [True: 44.7k, False: 12.1M]
  ------------------
 1733|  44.7k|                   if (minus)
  ------------------
  |  Branch (1733:24): [True: 5.54k, False: 39.2k]
  ------------------
 1734|  5.54k|                       cont = handler.Int64(static_cast<int64_t>(~i64 + 1));
 1735|  39.2k|                   else
 1736|  39.2k|                       cont = handler.Uint64(i64);
 1737|  44.7k|               }
 1738|  12.1M|               else {
 1739|  12.1M|                   if (minus)
  ------------------
  |  Branch (1739:24): [True: 37.3k, False: 12.1M]
  ------------------
 1740|  37.3k|                       cont = handler.Int(static_cast<int32_t>(~i + 1));
 1741|  12.1M|                   else
 1742|  12.1M|                       cont = handler.Uint(i);
 1743|  12.1M|               }
 1744|  12.2M|           }
 1745|  13.1M|        }
 1746|  13.1M|        if (RAPIDJSON_UNLIKELY(!cont))
  ------------------
  |  |  505|  13.1M|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (505:31): [True: 0, False: 13.1M]
  |  |  ------------------
  ------------------
 1747|       |            RAPIDJSON_PARSE_ERROR(kParseErrorTermination, startOffset);
  ------------------
  |  |  120|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  ------------------
  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  ------------------
  |  |  121|      0|    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
  |  |  ------------------
  |  |  |  |  101|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  ------------------
  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  ------------------
  |  |  |  |  102|      0|    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
  |  |  |  |  ------------------
  |  |  |  |  |  |  437|      0|#define RAPIDJSON_ASSERT(x) assert(x)
  |  |  |  |  ------------------
  |  |  |  |  103|      0|    SetParseError(parseErrorCode, offset); \
  |  |  |  |  104|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  ------------------
  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  122|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
  |  |  ------------------
  |  |  |  |   66|      0|    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
  |  |  |  |  ------------------
  |  |  |  |  |  |   61|      0|    RAPIDJSON_MULTILINEMACRO_BEGIN \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  516|      0|#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   62|      0|    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  505|      0|#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (505:31): [True: 0, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   63|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  123|      0|    RAPIDJSON_MULTILINEMACRO_END
  |  |  ------------------
  |  |  |  |  517|      0|#define RAPIDJSON_MULTILINEMACRO_END \
  |  |  |  |  518|      0|} while((void)0, 0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (518:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1747:13): [True: 0, False: 0]
  ------------------
 1748|  13.1M|    }
_ZN9rapidjson13GenericReaderINS_4UTF8IcEES2_NS_12CrtAllocatorEE12NumberStreamINS_25GenericInsituStringStreamIS2_EEcLb0ELb0EE4TellEv:
 1422|  13.1M|        size_t Tell() { return is.Tell(); }
_ZN9rapidjson13GenericReaderINS_4UTF8IcEES2_NS_12CrtAllocatorEE7ConsumeINS4_12NumberStreamINS_25GenericInsituStringStreamIS2_EEcLb0ELb0EEEEEbRT_NSA_2ChE:
  895|  52.9M|    RAPIDJSON_FORCEINLINE static bool Consume(InputStream& is, typename InputStream::Ch expect) {
  896|  52.9M|        if (RAPIDJSON_LIKELY(is.Peek() == expect)) {
  ------------------
  |  |  492|  52.9M|#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (492:29): [True: 1.48M, False: 51.4M]
  |  |  ------------------
  ------------------
  897|  1.48M|            is.Take();
  898|  1.48M|            return true;
  899|  1.48M|        }
  900|  51.4M|        else
  901|  51.4M|            return false;
  902|  52.9M|    }
_ZNK9rapidjson13GenericReaderINS_4UTF8IcEES2_NS_12CrtAllocatorEE12NumberStreamINS_25GenericInsituStringStreamIS2_EEcLb0ELb0EE4PeekEv:
 1417|   135M|        RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); }
_ZN9rapidjson13GenericReaderINS_4UTF8IcEES2_NS_12CrtAllocatorEE12NumberStreamINS_25GenericInsituStringStreamIS2_EEcLb0ELb0EE8TakePushEv:
 1418|  31.9M|        RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); }
_ZN9rapidjson13GenericReaderINS_4UTF8IcEES2_NS_12CrtAllocatorEE12NumberStreamINS_25GenericInsituStringStreamIS2_EEcLb0ELb0EE6LengthEv:
 1423|  26.3M|        size_t Length() { return 0; }
_ZN9rapidjson13GenericReaderINS_4UTF8IcEES2_NS_12CrtAllocatorEE12NumberStreamINS_25GenericInsituStringStreamIS2_EEcLb0ELb0EE4TakeEv:
 1419|  1.77M|        RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); }
_ZN9rapidjson13GenericReaderINS_4UTF8IcEES2_NS_12CrtAllocatorEE12NumberStreamINS_25GenericInsituStringStreamIS2_EEcLb0ELb0EE3PopEv:
 1424|  13.1M|        const StackCharacter* Pop() { return 0; }
_ZN9rapidjson13GenericReaderINS_4UTF8IcEES2_NS_12CrtAllocatorEEC2EPS3_m:
  548|  14.0k|        stack_(stackAllocator, stackCapacity), parseResult_(), state_(IterativeParsingStartState) {}
_ZN9rapidjson13GenericReaderINS_4UTF8IcEES2_NS_12CrtAllocatorEE16ClearStackOnExitC2ERS4_:
  702|  14.0k|        explicit ClearStackOnExit(GenericReader& r) : r_(r) {}
_ZN9rapidjson8internal15StreamLocalCopyINS_25GenericInsituStringStreamINS_4UTF8IcEEEELi1EEC2ERS5_:
  233|  65.0M|    StreamLocalCopy(Stream& original) : s(original), original_(original) {}
_ZN9rapidjson8internal15StreamLocalCopyINS_25GenericInsituStringStreamINS_4UTF8IcEEEELi1EED2Ev:
  234|  65.0M|    ~StreamLocalCopy() { original_ = s; }
_ZN9rapidjson13GenericReaderINS_4UTF8IcEES2_NS_12CrtAllocatorEE12NumberStreamINS_25GenericInsituStringStreamIS2_EEcLb0ELb0EEC2ERS4_RS7_:
 1415|  13.1M|        NumberStream(GenericReader& reader, InputStream& s) : is(s) { (void)reader;  }
_ZN9rapidjson13GenericReaderINS_4UTF8IcEES2_NS_12CrtAllocatorEE16ClearStackOnExitD2Ev:
  703|  14.0k|        ~ClearStackOnExit() { r_.ClearStack(); }

_ZN9rapidjson25GenericInsituStringStreamINS_4UTF8IcEEE4TakeEv:
  195|   170M|    Ch Take() { return *src_++; }
_ZN9rapidjson25GenericInsituStringStreamINS_4UTF8IcEEE8PutBeginEv:
  201|  5.97M|    Ch* PutBegin() { return dst_ = src_; }
_ZN9rapidjson25GenericInsituStringStreamINS_4UTF8IcEEE3PutEc:
  199|  76.8M|    void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; }
  ------------------
  |  |  437|  76.8M|#define RAPIDJSON_ASSERT(x) assert(x)
  ------------------
  |  Branch (199:22): [True: 76.8M, False: 0]
  ------------------
_ZN9rapidjson25GenericInsituStringStreamINS_4UTF8IcEEE6PutEndEPc:
  202|  5.97M|    size_t PutEnd(Ch* begin) { return static_cast<size_t>(dst_ - begin); }
_ZN9rapidjson25GenericInsituStringStreamINS_4UTF8IcEEE4PeekEv:
  194|   350M|    Ch Peek() { return *src_; }
_ZN9rapidjson25GenericInsituStringStreamINS_4UTF8IcEEE4TellEv:
  196|  84.0M|    size_t Tell() { return static_cast<size_t>(src_ - head_); }
_ZN9rapidjson25GenericInsituStringStreamINS_4UTF8IcEEEC2EPc:
  191|  14.0k|    GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {}

LLVMFuzzerTestOneInput:
   48|  5.13k|extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t dataSize) {
   49|  5.13k|    if (dataSize > 1024 * 1024) {
  ------------------
  |  Branch (49:9): [True: 0, False: 5.13k]
  ------------------
   50|      0|        return 0;
   51|      0|    }
   52|       |
   53|  5.13k|    Importer importer;
   54|       |    // Force glTF text format only (see assimp_fuzzer_glb.cc for binary GLB)
   55|  5.13k|    if (!AssimpFuzz::ForceFormat(importer, "gltf")) {
  ------------------
  |  Branch (55:9): [True: 0, False: 5.13k]
  ------------------
   56|      0|        return 0;
   57|      0|    }
   58|       |
   59|  5.13k|    unsigned int flags = aiProcessPreset_TargetRealtime_Quality | aiProcess_ValidateDataStructure;
   60|  5.13k|    const aiScene *sc = importer.ReadFileFromMemory(data, dataSize, flags, "gltf");
   61|       |
   62|  5.13k|    return 0;
   63|  5.13k|}

_ZN10AssimpFuzz11ForceFormatERN6Assimp8ImporterEPKc:
   53|  5.13k|inline bool ForceFormat(Assimp::Importer& importer, const char* targetExtension) {
   54|  5.13k|    size_t count = importer.GetImporterCount();
   55|  5.13k|    std::vector<Assimp::BaseImporter*> toRemove;
   56|  5.13k|    bool found = false;
   57|       |
   58|   251k|    for (size_t i = 0; i < count; ++i) {
  ------------------
  |  Branch (58:24): [True: 246k, False: 5.13k]
  ------------------
   59|   246k|        const aiImporterDesc* desc = importer.GetImporterInfo(i);
   60|   246k|        Assimp::BaseImporter* imp = importer.GetImporter(i);
   61|       |        
   62|   246k|        if (!desc || !imp) continue;
  ------------------
  |  Branch (62:13): [True: 0, False: 246k]
  |  Branch (62:22): [True: 0, False: 246k]
  ------------------
   63|       |
   64|       |        // Check if the importer supports the target extension
   65|       |        // mFileExtensions is a space-separated list (e.g., "obj mod")
   66|       |        // We wrap target in spaces or check bounds to be precise, 
   67|       |        // but for fuzzing, a simple strstr is usually sufficient 
   68|       |        // if the target string is unique enough (e.g. "gltf", "obj").
   69|       |        // A more robust check:
   70|       |        
   71|   246k|        bool isTarget = false;
   72|   246k|        const char* extList = desc->mFileExtensions;
   73|   246k|        if (!extList) {
  ------------------
  |  Branch (73:13): [True: 0, False: 246k]
  ------------------
   74|      0|            toRemove.push_back(imp);
   75|      0|            continue;
   76|      0|        }
   77|   246k|        const size_t targetLen = strlen(targetExtension);
   78|       |
   79|   246k|        const char* p = extList;
   80|   246k|        while ((p = strstr(p, targetExtension)) != nullptr) {
  ------------------
  |  Branch (80:16): [True: 10.2k, False: 236k]
  ------------------
   81|       |            // Check boundaries
   82|  10.2k|            const char prev = (p == extList) ? ' ' : *(p - 1);
  ------------------
  |  Branch (82:31): [True: 10.2k, False: 0]
  ------------------
   83|  10.2k|            const char next = *(p + targetLen);
   84|       |            
   85|  10.2k|            if (prev == ' ' && (next == ' ' || next == '\0')) {
  ------------------
  |  Branch (85:17): [True: 10.2k, False: 0]
  |  Branch (85:33): [True: 10.2k, False: 0]
  |  Branch (85:48): [True: 0, False: 0]
  ------------------
   86|  10.2k|                isTarget = true;
   87|  10.2k|                break;
   88|  10.2k|            }
   89|      0|            p++;
   90|      0|        }
   91|       |
   92|   246k|        if (isTarget) {
  ------------------
  |  Branch (92:13): [True: 10.2k, False: 236k]
  ------------------
   93|  10.2k|            found = true;
   94|   236k|        } else {
   95|   236k|            toRemove.push_back(imp);
   96|   236k|        }
   97|   246k|    }
   98|       |
   99|   236k|    for (auto* imp : toRemove) {
  ------------------
  |  Branch (99:20): [True: 236k, False: 5.13k]
  ------------------
  100|   236k|        importer.UnregisterLoader(imp);
  101|   236k|        delete imp;  // Free the unregistered importer to prevent memory leaks
  102|   236k|    }
  103|       |
  104|  5.13k|    return found;
  105|  5.13k|}

_ZN6Assimp10TXmlParserIN4pugi8xml_nodeEEC2Ev:
  256|  10.2k|        mDoc(nullptr),
  257|  10.2k|        mData() {
  258|       |    // empty
  259|  10.2k|}
_ZN6Assimp10TXmlParserIN4pugi8xml_nodeEE5clearEv:
  267|  10.2k|inline void TXmlParser<TNodeType>::clear() {
  268|  10.2k|    if (mData.empty()) {
  ------------------
  |  Branch (268:9): [True: 10.2k, False: 0]
  ------------------
  269|  10.2k|        if (mDoc) {
  ------------------
  |  Branch (269:13): [True: 0, False: 10.2k]
  ------------------
  270|      0|            delete mDoc;
  271|      0|        }
  272|  10.2k|        mDoc = nullptr;
  273|  10.2k|        return;
  274|  10.2k|    }
  275|       |
  276|      0|    mData.clear();
  277|      0|    delete mDoc;
  278|      0|    mDoc = nullptr;
  279|      0|}
_ZN6Assimp10TXmlParserIN4pugi8xml_nodeEED2Ev:
  262|  10.2k|inline TXmlParser<TNodeType>::~TXmlParser() {
  263|  10.2k|    clear();
  264|  10.2k|}

