Skip to content

Commit

Permalink
#5977: Change IDeclarationParser to IDeclarationCreator. The declarat…
Browse files Browse the repository at this point in the history
…ion instances will work with the DeclarationBlockSyntax.
  • Loading branch information
codereader committed Jun 25, 2022
1 parent a9896bc commit 43c9214
Show file tree
Hide file tree
Showing 12 changed files with 133 additions and 121 deletions.
27 changes: 15 additions & 12 deletions include/ideclmanager.h
Expand Up @@ -52,24 +52,27 @@ class IDeclaration

// The raw syntax block (without the outer curly braces) used to construct this decl
virtual const DeclarationBlockSyntax& getBlockSyntax() const = 0;

// Parse (or reparse) the declaration contents from the given block syntax
virtual void parseFromBlock(const DeclarationBlockSyntax& block) = 0;
};

using NamedDeclarations = std::map<std::string, IDeclaration::Ptr>;

// Interface of a parser that can handle a single declaration type
class IDeclarationParser
// Factory interface being able to create a single declaration type
class IDeclarationCreator
{
public:
virtual ~IDeclarationParser()
virtual ~IDeclarationCreator()
{}

using Ptr = std::shared_ptr<IDeclarationParser>;
using Ptr = std::shared_ptr<IDeclarationCreator>;

// Returns the declaration type this parser can handle
// Returns the declaration type this creator can handle
virtual Type getDeclType() const = 0;

// Create a new declaration instance from the given block
virtual IDeclaration::Ptr parseFromBlock(const DeclarationBlockSyntax& block) = 0;
// Creates an empty declaration with the given name
virtual IDeclaration::Ptr createDeclaration(const std::string& name) = 0;
};

// Central service class holding all the declarations in the active game,
Expand All @@ -83,16 +86,16 @@ class IDeclarationManager :
virtual ~IDeclarationManager() override
{}

// Registers the declaration typename (e.g. "material") and associates it with the given parser
// It's not allowed to register more than one parser for a single typename
virtual void registerDeclType(const std::string& typeName, const IDeclarationParser::Ptr& parser) = 0;
// Registers the declaration typename (e.g. "material") and associates it with the given creator
// It's not allowed to register more than one creator for a single typename
virtual void registerDeclType(const std::string& typeName, const IDeclarationCreator::Ptr& creator) = 0;

// Unregisters the given typename and the associated parser
// Unregisters the given typename and the associated creator
virtual void unregisterDeclType(const std::string& typeName) = 0;

// Associates the given VFS folder (with trailing slash) to a certain declaration type
// all files matching the given file extension (without dot) will be searched and parsed.
// The folder will not be recursively searched for files, only immediate children will be parsed.
// The folder will not be recursively searched for files, only immediate children will be processed.
// Any untyped declaration blocks found in the files will be assumed to be of the given defaultType.
// All explicitly typed resources will be processed using the parser that has been previously
// associated in registerDeclType()
Expand Down
3 changes: 2 additions & 1 deletion plugins/sound/SoundManager.cpp
Expand Up @@ -69,7 +69,8 @@ SoundManager::SoundManager()
decl::DeclarationBlockSyntax defaultBlock;
defaultBlock.fileInfo = vfs::FileInfo("sounds/", "_autogenerated_by_darkradiant_.sndshd", vfs::Visibility::HIDDEN);

_emptyShader = std::make_unique<SoundShader>(defaultBlock);
_emptyShader = std::make_unique<SoundShader>("");
_emptyShader->parseFromBlock(defaultBlock);
}

void SoundManager::forEachShader(std::function<void(const ISoundShader&)> functor)
Expand Down
17 changes: 11 additions & 6 deletions plugins/sound/SoundShader.cpp
Expand Up @@ -20,11 +20,8 @@ struct SoundShader::ParsedContents
std::string displayFolder;
};

SoundShader::SoundShader(const decl::DeclarationBlockSyntax& block)
: _name(block.name),
_declBlock(block),
_fileInfo(block.fileInfo),
_modName(block.getModName())
SoundShader::SoundShader(const std::string& name)
: _name(name)
{ }

// Destructor must be defined with ParsedContents definition visible, otherwise
Expand All @@ -34,7 +31,7 @@ SoundShader::~SoundShader()

void SoundShader::parseDefinition() const
{
_contents.reset(new ParsedContents);
_contents = std::make_unique<ParsedContents>();

// Get a new tokeniser and parse the block
parser::BasicDefTokeniser<std::string> tok(_declBlock.contents);
Expand Down Expand Up @@ -105,4 +102,12 @@ const decl::DeclarationBlockSyntax& SoundShader::getBlockSyntax() const
return _declBlock;
}

void SoundShader::parseFromBlock(const decl::DeclarationBlockSyntax& block)
{
_declBlock = block;
_fileInfo = block.fileInfo;
_modName = block.getModName();
_contents.reset();
}

} // namespace sound
3 changes: 2 additions & 1 deletion plugins/sound/SoundShader.h
Expand Up @@ -34,7 +34,7 @@ class SoundShader final :
public:
using Ptr = std::shared_ptr<SoundShader>;

SoundShader(const decl::DeclarationBlockSyntax& block);
SoundShader(const std::string& name);

~SoundShader();

Expand All @@ -49,6 +49,7 @@ class SoundShader final :
std::string getDefinition() const override;

const decl::DeclarationBlockSyntax& getBlockSyntax() const override;
void parseFromBlock(const decl::DeclarationBlockSyntax& block) override;
};

}
8 changes: 4 additions & 4 deletions plugins/sound/SoundShaderParser.h
Expand Up @@ -7,20 +7,20 @@ namespace sound
{

/**
* Declaration parser capable of dealing with sound shader blocks
* Declaration creator capable of dealing with sound shader blocks
*/
class SoundShaderParser final :
public decl::IDeclarationParser
public decl::IDeclarationCreator
{
public:
decl::Type getDeclType() const override
{
return decl::Type::SoundShader;
}

decl::IDeclaration::Ptr parseFromBlock(const decl::DeclarationBlockSyntax& block) override
decl::IDeclaration::Ptr createDeclaration(const std::string& name) override
{
return std::make_shared<SoundShader>(block);
return std::make_shared<SoundShader>(name);
}
};

Expand Down
36 changes: 19 additions & 17 deletions radiantcore/decl/DeclarationFileParser.cpp
Expand Up @@ -26,15 +26,15 @@ namespace
}

DeclarationFileParser::DeclarationFileParser(Type declType,
const std::map<std::string, IDeclarationParser::Ptr>& parsersByTypename) :
const std::map<std::string, IDeclarationCreator::Ptr>& creatorsByTypename) :
_defaultDeclType(declType),
_parsersByTypename(parsersByTypename)
_creatorsByTypename(creatorsByTypename)
{
_defaultTypeParser = getParserByType(declType);
_defaultTypeCreator = getCreatorByType(declType);

if (!_defaultTypeParser)
if (!_defaultTypeCreator)
{
throw std::invalid_argument("No parser has been associated to the default type " + getTypeName(declType));
throw std::invalid_argument("No creator has been associated to the default type " + getTypeName(declType));
}
}

Expand Down Expand Up @@ -71,17 +71,17 @@ void DeclarationFileParser::parse(std::istream& stream, const vfs::FileInfo& fil

if (spacePos == std::string::npos)
{
// No type specified, use the default type parser
parseBlock(*_defaultTypeParser, blockSyntax);
// No type specified, use the default type creator
processBlock(*_defaultTypeCreator, blockSyntax);
continue;
}

// Locate a parser capable of handling that block
auto parser = _parsersByTypename.find(block.name.substr(0, spacePos));
// Locate a creator capable of handling that block
auto creator = _creatorsByTypename.find(block.name.substr(0, spacePos));

if (parser != _parsersByTypename.end())
if (creator != _creatorsByTypename.end())
{
parseBlock(*parser->second, blockSyntax);
processBlock(*creator->second, blockSyntax);
continue;
}

Expand All @@ -90,20 +90,22 @@ void DeclarationFileParser::parse(std::istream& stream, const vfs::FileInfo& fil
}
}

void DeclarationFileParser::parseBlock(IDeclarationParser& parser, const DeclarationBlockSyntax& block)
void DeclarationFileParser::processBlock(IDeclarationCreator& creator, const DeclarationBlockSyntax& block)
{
auto declaration = parser.parseFromBlock(block);
auto declaration = creator.createDeclaration(block.name);

auto& declMap = _parsedDecls.try_emplace(parser.getDeclType(), NamedDeclarations()).first->second;
declaration->parseFromBlock(block);

auto& declMap = _parsedDecls.try_emplace(creator.getDeclType(), NamedDeclarations()).first->second;

// Insert into map, emit a warning on duplicates
DeclarationManager::InsertDeclaration(declMap, std::move(declaration));
}

IDeclarationParser::Ptr DeclarationFileParser::getParserByType(Type declType) const
IDeclarationCreator::Ptr DeclarationFileParser::getCreatorByType(Type declType) const
{
// Get the default type parser
for (const auto& pair : _parsersByTypename)
// Get the default type creator
for (const auto& pair : _creatorsByTypename)
{
if (pair.second->getDeclType() == declType)
{
Expand Down
10 changes: 5 additions & 5 deletions radiantcore/decl/DeclarationFileParser.h
Expand Up @@ -13,16 +13,16 @@ class DeclarationFileParser
private:
Type _defaultDeclType;

std::map<std::string, IDeclarationParser::Ptr> _parsersByTypename;
IDeclarationParser::Ptr _defaultTypeParser;
std::map<std::string, IDeclarationCreator::Ptr> _creatorsByTypename;
IDeclarationCreator::Ptr _defaultTypeCreator;

std::set<DeclarationFile> _parsedFiles;
std::map<Type, NamedDeclarations> _parsedDecls;

std::vector<DeclarationBlockSyntax> _unrecognisedBlocks;

public:
DeclarationFileParser(Type declType, const std::map<std::string, IDeclarationParser::Ptr>& parsersByTypename);
DeclarationFileParser(Type declType, const std::map<std::string, IDeclarationCreator::Ptr>& creatorsByTypename);

void parse(std::istream& stream, const vfs::FileInfo& fileInfo, const std::string& modDir);

Expand All @@ -31,8 +31,8 @@ class DeclarationFileParser
const std::vector<DeclarationBlockSyntax>& getUnrecognisedBlocks() const;

private:
void parseBlock(IDeclarationParser& parser, const DeclarationBlockSyntax& block);
IDeclarationParser::Ptr getParserByType(Type declType) const;
void processBlock(IDeclarationCreator& creator, const DeclarationBlockSyntax& block);
IDeclarationCreator::Ptr getCreatorByType(Type declType) const;
};

}
4 changes: 2 additions & 2 deletions radiantcore/decl/DeclarationFolderParser.cpp
Expand Up @@ -7,10 +7,10 @@ namespace decl

DeclarationFolderParser::DeclarationFolderParser(DeclarationManager& owner, Type declType,
const std::string& baseDir, const std::string& extension,
const std::map<std::string, IDeclarationParser::Ptr>& parsersByTypename) :
const std::map<std::string, IDeclarationCreator::Ptr>& creatorsByTypename) :
ThreadedDeclParser<void>(declType, baseDir, extension, 1),
_owner(owner),
_fileParser(declType, parsersByTypename),
_fileParser(declType, creatorsByTypename),
_defaultDeclType(declType)
{}

Expand Down
2 changes: 1 addition & 1 deletion radiantcore/decl/DeclarationFolderParser.h
Expand Up @@ -25,7 +25,7 @@ class DeclarationFolderParser :
public:
DeclarationFolderParser(DeclarationManager& owner, Type declType,
const std::string& baseDir, const std::string& extension,
const std::map<std::string, IDeclarationParser::Ptr>& parsersByTypename);
const std::map<std::string, IDeclarationCreator::Ptr>& creatorsByTypename);

protected:
void parse(std::istream& stream, const vfs::FileInfo& fileInfo, const std::string& modDir) override;
Expand Down
36 changes: 18 additions & 18 deletions radiantcore/decl/DeclarationManager.cpp
Expand Up @@ -10,33 +10,33 @@
namespace decl
{

void DeclarationManager::registerDeclType(const std::string& typeName, const IDeclarationParser::Ptr& parser)
void DeclarationManager::registerDeclType(const std::string& typeName, const IDeclarationCreator::Ptr& parser)
{
std::lock_guard<std::mutex> parserLock(_parserLock);
std::lock_guard<std::mutex> parserLock(_creatorLock);

if (_parsersByTypename.count(typeName) > 0)
if (_creatorsByTypename.count(typeName) > 0)
{
throw std::logic_error("Type name " + typeName + " has already been registered");
}

_parsersByTypename.emplace(typeName, parser);
_creatorsByTypename.emplace(typeName, parser);

// A new parser might be able to parse some of the unrecognised blocks
handleUnrecognisedBlocks();
}

void DeclarationManager::unregisterDeclType(const std::string& typeName)
{
std::lock_guard<std::mutex> parserLock(_parserLock);
std::lock_guard<std::mutex> parserLock(_creatorLock);

auto existing = _parsersByTypename.find(typeName);
auto existing = _creatorsByTypename.find(typeName);

if (existing == _parsersByTypename.end())
if (existing == _creatorsByTypename.end())
{
throw std::logic_error("Type name " + typeName + " has not been registered");
}

_parsersByTypename.erase(existing);
_creatorsByTypename.erase(existing);
}

void DeclarationManager::registerDeclFolder(Type defaultType, const std::string& inputFolder, const std::string& inputExtension)
Expand All @@ -51,7 +51,7 @@ void DeclarationManager::registerDeclFolder(Type defaultType, const std::string&
auto& decls = _declarationsByType.try_emplace(defaultType, Declarations()).first->second;

// Start the parser thread
decls.parser = std::make_unique<DeclarationFolderParser>(*this, defaultType, vfsPath, extension, _parsersByTypename);
decls.parser = std::make_unique<DeclarationFolderParser>(*this, defaultType, vfsPath, extension, _creatorsByTypename);
decls.parser->start();
}

Expand Down Expand Up @@ -110,11 +110,11 @@ void DeclarationManager::doWithDeclarations(Type type, const std::function<void(
void DeclarationManager::reloadDecarations()
{
std::lock_guard<std::mutex> fileLock(_parsedFileLock);
std::lock_guard<std::mutex> parserLock(_parserLock);
std::lock_guard<std::mutex> parserLock(_creatorLock);

for (const auto& [type, files] : _parsedFilesByDefaultType)
{
DeclarationFileParser parser(type, _parsersByTypename);
DeclarationFileParser parser(type, _creatorsByTypename);

for (const auto& file : files)
{
Expand Down Expand Up @@ -185,19 +185,19 @@ void DeclarationManager::handleUnrecognisedBlocks()
std::lock_guard<std::mutex> lock(_unrecognisedBlockLock);

// Check each of the unrecognised blocks
for (auto b = _unrecognisedBlocks.begin(); b != _unrecognisedBlocks.end();)
for (auto block = _unrecognisedBlocks.begin(); block != _unrecognisedBlocks.end();)
{
auto parser = _parsersByTypename.find(b->typeName);
auto parser = _creatorsByTypename.find(block->typeName);

if (parser == _parsersByTypename.end())
if (parser == _creatorsByTypename.end())
{
++b;
++block;
continue; // still not recognised
}

// We found a parser, handle it now
auto declaration = parser->second->parseFromBlock(*b);
_unrecognisedBlocks.erase(b++);
auto declaration = parser->second->createDeclaration(block->name);
_unrecognisedBlocks.erase(block++);

// Insert into our main library
std::lock_guard<std::mutex> declLock(_declarationLock);
Expand Down Expand Up @@ -263,7 +263,7 @@ void DeclarationManager::shutdownModule()
_parsedFilesByDefaultType.clear();
_unrecognisedBlocks.clear();
_declarationsByType.clear();
_parsersByTypename.clear();
_creatorsByTypename.clear();
_declsReloadedSignals.clear();
}

Expand Down
6 changes: 3 additions & 3 deletions radiantcore/decl/DeclarationManager.h
Expand Up @@ -17,8 +17,8 @@ class DeclarationManager :
public IDeclarationManager
{
private:
std::map<std::string, IDeclarationParser::Ptr> _parsersByTypename;
std::mutex _parserLock;
std::map<std::string, IDeclarationCreator::Ptr> _creatorsByTypename;
std::mutex _creatorLock;

struct RegisteredFolder
{
Expand Down Expand Up @@ -51,7 +51,7 @@ class DeclarationManager :
std::map<Type, sigc::signal<void>> _declsReloadedSignals;

public:
void registerDeclType(const std::string& typeName, const IDeclarationParser::Ptr& parser) override;
void registerDeclType(const std::string& typeName, const IDeclarationCreator::Ptr& parser) override;
void unregisterDeclType(const std::string& typeName) override;
void registerDeclFolder(Type defaultType, const std::string& inputFolder, const std::string& inputExtension) override;
IDeclaration::Ptr findDeclaration(Type type, const std::string& name) override;
Expand Down

0 comments on commit 43c9214

Please sign in to comment.