Skip to content

Commit 99c5f70

Browse files
author
devsh
committed
get rid of CElementFactory, rewrite ParserUtil to be threadsafe and DLL Delay Load compatible
1 parent 1ab734c commit 99c5f70

File tree

7 files changed

+288
-313
lines changed

7 files changed

+288
-313
lines changed

include/nbl/ext/MitsubaLoader/CElementFactory.h

Lines changed: 0 additions & 41 deletions
This file was deleted.

include/nbl/ext/MitsubaLoader/IElement.h

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,15 @@
1-
// Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O.
1+
// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O.
22
// This file is part of the "Nabla Engine".
33
// For conditions of distribution and use, see copyright notice in nabla.h
4+
#ifndef _NBL_EXT_MISTUBA_LOADER_I_ELEMENT_H_INCLUDED_
5+
#define _NBL_EXT_MISTUBA_LOADER_I_ELEMENT_H_INCLUDED_
46

5-
#ifndef __I_ELEMENT_H_INCLUDED__
6-
#define __I_ELEMENT_H_INCLUDED__
77

88
#include "nbl/asset/interchange/IAssetLoader.h"
99
#include "nbl/ext/MitsubaLoader/PropertyElement.h"
1010

11-
12-
namespace nbl
13-
{
14-
namespace ext
11+
namespace nbl::ext::MitsubaLoader
1512
{
16-
namespace MitsubaLoader
17-
{
18-
19-
2013
class CMitsubaMetadata;
2114

2215
class IElement
@@ -114,7 +107,4 @@ class IElement
114107
};
115108

116109
}
117-
}
118-
}
119-
120110
#endif

include/nbl/ext/MitsubaLoader/ParserUtil.h

Lines changed: 94 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77

88
#include "nbl/asset/interchange/IAssetLoader.h"
99

10-
//#include "nbl/ext/MitsubaLoader/CElementFactory.h"
10+
#include "nbl/ext/MitsubaLoader/PropertyElement.h"
11+
#include "nbl/ext/MitsubaLoader/CElementShape.h"
1112
#include "nbl/ext/MitsubaLoader/CMitsubaMetadata.h"
1213

1314
#include "expat/lib/expat.h"
@@ -36,89 +37,112 @@ class ElementPool // similar to : public std::tuple<core::vector<types>...>
3637
};
3738

3839
//struct, which will be passed to expat handlers as user data (first argument) see: XML_StartElementHandler or XML_EndElementHandler in expat.h
39-
class ParserManager
40+
class ParserManager final
4041
{
41-
protected:
42-
// TODO: need per-file/per-parse contexts and per-load (one shapegroup, one metadata, one stack, etc. - basically the members of `ParserManager` now)
43-
struct Context
42+
public:
43+
//! Constructor
44+
ParserManager();
45+
46+
//
47+
static void elementHandlerStart(void* _data, const char* _el, const char** _atts);
48+
static void elementHandlerEnd(void* _data, const char* _el);
49+
50+
struct Params
51+
{
52+
system::logger_opt_ptr logger;
53+
// for opening included XML files
54+
system::ISystem* system;
55+
asset::IAssetLoader::IAssetLoaderOverride* _override;
56+
};
57+
struct Result
58+
{
59+
explicit inline operator bool() const {return bool(metadata);}
60+
61+
// note that its shared between per-file contexts
62+
core::smart_refctd_ptr<CMitsubaMetadata> metadata = nullptr;
63+
//
64+
core::vector<std::pair<CElementShape*,std::string> > shapegroups = {};
65+
};
66+
Result parse(system::IFile* _file, const Params& _params) const;
67+
68+
// Properties are simple XML nodes which are not `IElement` and neither children of an` IElement`
69+
// If we match any `<name` we call the `processProperty` method instead of element creation method
70+
const core::unordered_set<std::string,core::CaseInsensitiveHash,core::CaseInsensitiveEquals> propertyElements;
71+
const CPropertyElementManager propertyElementManager;
72+
73+
private:
74+
struct SNamedElement
4475
{
45-
/*prints this message:
46-
Mitsuba loader error:
47-
Invalid .xml file structure: message */
48-
void invalidXMLFileStructure(const std::string& errorMessage) const;
76+
IElement* element = nullptr;
77+
core::string name = {};
78+
};
79+
// the XMLs can include each other, so this stores the stuff across files
80+
struct SessionContext
81+
{
82+
// prints this message:
83+
// Mitsuba loader error:
84+
// Invalid .xml file structure: message
85+
inline void invalidXMLFileStructure(const std::string& errorMessage) const
86+
{
87+
::nbl::ext::MitsubaLoader::invalidXMLFileStructure(params->logger,errorMessage);
88+
}
89+
// meant for parsing one file in an include chain
90+
bool parse(system::IFile* _file);
4991

92+
Result* const result;
93+
const Params* const params;
94+
const ParserManager* const manager;
95+
//
96+
uint32_t sceneDeclCount = 0;
97+
// TODO: This leaks memory all over the place because destructors are not ran!
98+
ElementPool</*
99+
CElementIntegrator,
100+
CElementSensor,
101+
CElementFilm,
102+
CElementRFilter,
103+
CElementSampler,
104+
CElementShape,
105+
CElementBSDF,
106+
CElementTexture,
107+
CElementEmitter*/
108+
> objects = {};
109+
// aliases and names (in Mitsbua XML you can give nodes names and `ref` them)
110+
core::unordered_map<core::string,IElement*,core::CaseInsensitiveHash,core::CaseInsensitiveEquals> handles = {};
111+
// stack of currently processed elements, each element of index N is parent of the element of index N+1
112+
// the scene element is a parent of all elements of index 0
113+
core::stack<SNamedElement> elements = {};
114+
};
115+
// This is for a single XML File
116+
struct XMLContext
117+
{
50118
//
51119
inline void killParseWithError(const std::string& message) const
52120
{
53-
invalidXMLFileStructure(message);
121+
session->invalidXMLFileStructure(message);
54122
XML_StopParser(parser,false);
55123
}
124+
void parseElement(const char* _el, const char** _atts);
125+
void onEnd(const char* _el);
56126

57-
system::path currentXMLDir;
127+
SessionContext* const session;
58128
//
59-
ParserManager* manager;
60-
system::logger_opt_ptr logger;
129+
const system::path currentXMLDir;
61130
//
62131
XML_Parser parser;
63132
};
64-
65-
public:
66-
//! Constructor
67-
inline ParserManager(system::ISystem* _system, asset::IAssetLoader::IAssetLoaderOverride* _override) :
68-
propertyElements({
69-
"float", "string", "boolean", "integer",
70-
"rgb", "srgb", "spectrum", "blackbody",
71-
"point", "vector",
72-
"matrix", "rotate", "translate", "scale", "lookat"
73-
}), m_system(_system), m_override(_override), m_metadata(core::make_smart_refctd_ptr<CMitsubaMetadata>()) {}
74-
75-
//
76-
static void elementHandlerStart(void* _data, const char* _el, const char** _atts);
77-
static void elementHandlerEnd(void* _data, const char* _el);
78-
79-
bool parse(system::IFile* _file, const system::logger_opt_ptr& _logger);
80-
81-
void parseElement(const Context& ctx, const char* _el, const char** _atts);
82-
83-
void onEnd(const Context& ctx, const char* _el);
84-
85-
#if 0
86-
//
87-
core::vector<std::pair<CElementShape*,std::string> > shapegroups;
88-
#endif
89-
// note that its shared between per-file contexts
90-
core::smart_refctd_ptr<CMitsubaMetadata> m_metadata;
91-
92-
private:
93-
//
94-
void processProperty(const Context& ctx, const char* _el, const char** _atts);
95-
96-
const core::unordered_set<std::string,core::CaseInsensitiveHash,core::CaseInsensitiveEquals> propertyElements;
97-
// TODO: re-architect this and move into context so the PArserManager can be persistent
98-
system::ISystem* m_system;
99-
asset::IAssetLoader::IAssetLoaderOverride* m_override;
133+
134+
struct SElementCreator
135+
{
136+
// we still push nullptr (failed creation) onto the stack, we only stop parse on catastrphic failure later on if a use of the element pops up
137+
// this is why we don't need XMLCOntext for `killParseWithError`
138+
using func_t = SNamedElement(*)(const char**/*attributes*/,SessionContext*);
139+
func_t create;
140+
bool retvalGoesOnStack;
141+
};
142+
const core::unordered_map<std::string/*elementName*/,SElementCreator,core::CaseInsensitiveHash,core::CaseInsensitiveEquals> createElementTable;
100143
//
101-
uint32_t m_sceneDeclCount = 0;
102-
// TODO: This leaks memory all over the place because destructors are not ran!
103-
ElementPool</*
104-
CElementIntegrator,
105-
CElementSensor,
106-
CElementFilm,
107-
CElementRFilter,
108-
CElementSampler,
109-
CElementShape,
110-
CElementBSDF,
111-
CElementTexture,
112-
CElementEmitter*/
113-
> objects;
114-
// aliases and names
115-
core::unordered_map<std::string,IElement*,core::CaseInsensitiveHash,core::CaseInsensitiveEquals> handles;
116-
/*stack of currently processed elements
117-
each element of index N is parent of the element of index N+1
118-
the scene element is a parent of all elements of index 0 */
119-
core::stack<std::pair<IElement*,std::string> > elements;
120-
121-
friend class CElementFactory;
144+
static SNamedElement processAlias(const char** _atts, SessionContext* ctx);
145+
static SNamedElement processRef(const char** _atts, SessionContext* ctx);
122146
};
123147

124148
}

include/nbl/ext/MitsubaLoader/PropertyElement.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ template<> const SPropertyElementData::get_type_t<SPropertyElementData::Type::LO
364364
{ return mvalue; }
365365

366366

367-
class CPropertyElementManager final
367+
class CPropertyElementManager final : public core::Unmovable
368368
{
369369
const core::unordered_map<std::string,SPropertyElementData::Type,core::CaseInsensitiveHash,core::CaseInsensitiveEquals> StringToType;
370370

src/nbl/ext/MitsubaLoader/CElementFactory.cpp

Lines changed: 0 additions & 80 deletions
This file was deleted.

0 commit comments

Comments
 (0)