Skip to content

Instantly share code, notes, and snippets.

@webmozart
Last active December 18, 2015 16:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save webmozart/b6c4da31f2f0c0c7ae5c to your computer and use it in GitHub Desktop.
Save webmozart/b6c4da31f2f0c0c7ae5c to your computer and use it in GitHub Desktop.
Puli JSON parsing algorithm
function get(path)
{
if ('undefined' != typeof cache[path]) {
return cache[path]
}
cache[path] = new Resource(getTarget(path))
return cache[path]
}
/**
* @return string
*/
function getTarget(path)
{
// the path is mapped
if ('undefined' != typeof json[path]) {
if (isArray(json[path])) {
return expandMergedDirectory(json[path], true)[0];
}
return expandReference(json[path]);
}
remainder = '';
// the path is not mapped
while (path, filename = splitPath(path)) {
remainder = '/' + filename + remainder;
// check mapped paths only
for (directoryPath in getDirectoryTargets(path, false, true)) {
if (fileExists(directoryPath + remainder)) {
return directoryPath + remainder;
}
}
}
throw 'The path ' + path + ' was not found'
}
/**
* @return string[] may be empty
*/
function getDirectoryTargets(path, firstResultOnly = false, mappedOnly = false)
{
// path is a Puli path
result = []
// the path is mapped
if ('undefined' != typeof json[path]) {
if (isArray(json[path])) {
result.append(expandMergedDirectory(json[path], firstResultOnly));
} else {
result.append(expandDirectoryReference(json[path], firstResultOnly));
}
}
if (!mappedOnly) {
remainder = '';
// the path is not mapped
while (path, filename = splitPath(path)) {
remainder = '/' + filename + remainder;
// check mapped paths only
for (directoryPath in getDirectoryTargets(path, false, true)) {
if (isDirectory(directoryPath + remainder)) {
if (firstResultOnly) {
return directoryPath + remainder;
}
result[] = directoryPath + remainder;
}
}
}
}
return result;
}
/**
* @return string
*/
function expandReference(reference)
{
// reference can be:
// * an absolute path
// * a relative path
// * a link to another resource prefixed with "@"
if (reference.startsWith('@')) {
try {
return getTarget(reference.substr(1));
} catch (e) {
throw 'The target of the link ' + reference.substr(1) + ' was not found'
}
}
// turn into absolute path (if necessary)
return makeAbsolute(reference, basePath);
}
/**
* @return string[] may be empty
*/
function expandDirectoryReference(reference, firstResultOnly = false)
{
// reference can be:
// * an absolute path
// * a relative path
// * a link to another resource prefixed with "@"
if (reference.startsWith('@')) {
return getDirectoryTargets(reference.substr(1), firstResultOnly);
}
// turn into absolute path (if necessary)
absolutePath = makeAbsolute(reference, basePath);
if (!isDirectory(absolutePath)) {
throw "Expected a directory, got: %s";
}
return [absolutePath];
}
/**
* @return string[] empty if references are empty
*/
function expandMergedDirectory(references, firstResultOnly = false)
{
result = []
// first has highest priority
for (i = 0; i < references.length; ++i) {
absolutePaths = expandDirectoryReference(references[i], firstResultOnly);
if (firstResultOnly) {
return [absolutePaths[0]];
}
result.append(absolutePaths);
}
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment