Skip to content

Commit

Permalink
Refactor|libdeng2|Info: Info keeps track of the source path
Browse files Browse the repository at this point in the history
When an Info document is parsed from a file, Info itself keeps track of
the source path so that @includes can be done relative to the document
where the @include is in.
  • Loading branch information
skyjake committed Apr 8, 2014
1 parent e9dc2e5 commit 5511841
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 12 deletions.
33 changes: 32 additions & 1 deletion doomsday/libdeng2/include/de/data/info.h
Expand Up @@ -27,6 +27,8 @@

namespace de {

class File;

/**
* Key/value tree. The tree is parsed from the "Snowberry" Info file format.
*
Expand Down Expand Up @@ -256,12 +258,18 @@ class DENG2_PUBLIC Info

/**
* Finds an Info document.
*
* @param includeName Name of the Info document as specified in an \@include
* directive.
* @param from Info document where the inclusion occurs.
* @param sourcePath Optionally, the path of the Info source is returned
* here (if the content was read from a file). This can
* be NULL if the caller doesn't need to know the path.
*
* @return Content of the included document.
*/
virtual String findIncludedInfoSource(String const &includeName, Info const &from) const = 0;
virtual String findIncludedInfoSource(String const &includeName, Info const &from,
String *sourcePath) const = 0;

/// The included document could not be found. @ingroup errors
DENG2_ERROR(NotFoundError);
Expand Down Expand Up @@ -291,6 +299,13 @@ class DENG2_PUBLIC Info
*/
Info(String const &source);

/**
* Parses a file containing Info source.
*
* @param source Info source text.
*/
Info(File const &file);

Info(String const &source, IIncludeFinder const &finder);

/**
Expand All @@ -310,6 +325,13 @@ class DENG2_PUBLIC Info
*/
void parse(String const &infoSource);

/**
* Parses the Info source read from a file.
*
* @param file File containing an Info document.
*/
void parse(File const &file);

/**
* Parses the Info contents from a native text file.
*
Expand All @@ -319,6 +341,15 @@ class DENG2_PUBLIC Info

void clear();

void setSourcePath(String const &path);

/**
* Path of the source, if it has been read from a file.
*
* @return Source path in the file system.
*/
String sourcePath() const;

BlockElement const &root() const;

/**
Expand Down
45 changes: 42 additions & 3 deletions doomsday/libdeng2/src/data/info.cpp
Expand Up @@ -38,14 +38,18 @@ DENG2_PIMPL(Info)

struct DefaultIncludeFinder : public IIncludeFinder
{
String findIncludedInfoSource(String const &includeName, Info const &) const
String findIncludedInfoSource(String const &includeName, Info const &info,
String *sourcePath) const
{
return String::fromUtf8(Block(App::rootFolder().locate<File const>(includeName)));
String path = info.sourcePath().fileNamePath() / includeName;
if(sourcePath) *sourcePath = path;
return String::fromUtf8(Block(App::rootFolder().locate<File const>(path)));
}
};

QStringList scriptBlockTypes;
QStringList allowDuplicateBlocksOfType;
String sourcePath; ///< May be unknown (empty).
String content;
int currentLine;
int cursor; ///< Index of the next character from the source.
Expand Down Expand Up @@ -567,7 +571,13 @@ success:;
{
DENG2_ASSERT(finder != 0);

Info included(finder->findIncludedInfoSource(includeName, self), *finder);
String includePath;
String content = finder->findIncludedInfoSource(includeName, self, &includePath);

Info included;
included.setFinder(*finder); // use ours
included.setSourcePath(includePath);
included.parse(content);

// Move the contents of the resulting root block to our root block.
included.d->rootBlock.moveContents(rootBlock);
Expand Down Expand Up @@ -602,6 +612,12 @@ success:;
rootBlock.add(e);
}
}

void parse(File const &file)
{
sourcePath = file.path();
parse(String::fromUtf8(Block(file)));
}
};

Info::BlockElement::~BlockElement()
Expand Down Expand Up @@ -695,6 +711,13 @@ Info::Info(String const &source)
d.reset(inst.take());
}

Info::Info(File const &file)
{
QScopedPointer<Instance> inst(new Instance(this)); // parsing may throw exception
inst->parse(file);
d.reset(inst.take());
}

Info::Info(String const &source, IIncludeFinder const &finder)
{
QScopedPointer<Instance> inst(new Instance(this)); // parsing may throw exception
Expand Down Expand Up @@ -728,6 +751,11 @@ void Info::parse(String const &infoSource)
d->parse(infoSource);
}

void Info::parse(File const &file)
{
d->parse(file);
}

void Info::parseNativeFile(NativePath const &nativePath)
{
QFile file(nativePath);
Expand All @@ -739,9 +767,20 @@ void Info::parseNativeFile(NativePath const &nativePath)

void Info::clear()
{
d->sourcePath.clear();
parse("");
}

void Info::setSourcePath(String const &path)
{
d->sourcePath = path;
}

String Info::sourcePath() const
{
return d->sourcePath;
}

Info::BlockElement const &Info::root() const
{
return d->rootBlock;
Expand Down
18 changes: 10 additions & 8 deletions doomsday/libdeng2/src/scriptsys/scriptedinfo.cpp
Expand Up @@ -31,19 +31,18 @@ static String const KEY_BLOCK_TYPE = "__type__";
static String const KEY_INHERIT = "inherits";

DENG2_PIMPL(ScriptedInfo)
, public Info::IIncludeFinder
//, public Info::IIncludeFinder
{
typedef Info::Element::Value InfoValue;

Info info; ///< Original full parsed contents.
QScopedPointer<Script> script; ///< Current script being executed.
Process process; ///< Execution context.
String sourcePath;
String currentNamespace;

Instance(Public *i) : Base(i)
{
info.setFinder(*this); // finding includes based on sourcePath
//info.setFinder(*this); // finding includes based on sourcePath

// No limitation on duplicates for the special block types.
info.setAllowDuplicateBlocksOfType(
Expand All @@ -57,11 +56,13 @@ DENG2_PIMPL(ScriptedInfo)
script.reset();
}

/*
String findIncludedInfoSource(String const &includeName, Info const &) const
{
return String::fromUtf8(Block(App::rootFolder().locate<File const>
(sourcePath.fileNamePath() / includeName)));
(info.sourcePath().fileNamePath() / includeName)));
}
*/

/**
* Iterates through the parsed Info contents and processes each element.
Expand Down Expand Up @@ -213,7 +214,7 @@ DENG2_PIMPL(ScriptedInfo)
DENG2_ASSERT(process.state() == Process::Stopped);

script.reset(new Script(block.find("script")->values().first()));
script->setPath(sourcePath); // where the source comes from
script->setPath(info.sourcePath()); // where the source comes from
process.run(*script);
executeWithContext(block.parent());
}
Expand Down Expand Up @@ -326,7 +327,7 @@ DENG2_PIMPL(ScriptedInfo)
Value *evaluate(String const &source, Info::BlockElement const *context)
{
script.reset(new Script(source));
script->setPath(sourcePath); // where the source comes from
script->setPath(info.sourcePath()); // where the source comes from
process.run(*script);
executeWithContext(context);
return process.context().evaluator().result().duplicate();
Expand Down Expand Up @@ -402,8 +403,9 @@ void ScriptedInfo::parse(String const &source)

void ScriptedInfo::parse(File const &file)
{
d->sourcePath = file.path();
parse(String::fromUtf8(Block(file)));
d->clear();
d->info.parse(file);
d->processAll();
}

Value *ScriptedInfo::evaluate(String const &source)
Expand Down

0 comments on commit 5511841

Please sign in to comment.