diff options
Diffstat (limited to 'src/core/resource')
| -rw-r--r-- | src/core/resource/ResourceLocator.cpp | 39 | ||||
| -rw-r--r-- | src/core/resource/ResourceLocator.hpp | 58 | ||||
| -rw-r--r-- | src/core/resource/ResourceManager.cpp | 4 | ||||
| -rw-r--r-- | src/core/resource/ResourceRequest.cpp | 63 | ||||
| -rw-r--r-- | src/core/resource/ResourceRequest.hpp | 15 | 
5 files changed, 149 insertions, 30 deletions
diff --git a/src/core/resource/ResourceLocator.cpp b/src/core/resource/ResourceLocator.cpp index b19542e..da38cbd 100644 --- a/src/core/resource/ResourceLocator.cpp +++ b/src/core/resource/ResourceLocator.cpp @@ -25,6 +25,37 @@ namespace ousia {  /* Class ResourceLocator */ +std::vector<std::string> ResourceLocator::autocomplete( +    const std::string &path, const ResourceType type, +    const Resource &relativeTo) const +{ +	// If the locator of the given relative resource is this locator instance, +	// use the location specified in the resource, otherwise just use no +	// "relativeTo" path. +	if (&relativeTo.getLocator() == this) { +		return autocomplete(path, type, relativeTo.getLocation()); +	} +	return autocomplete(path, type, ""); +} + +std::vector<std::string> ResourceLocator::autocomplete( +    const std::string &path, const ResourceType type, +    const std::string &relativeTo) const +{ +	// Try to locate the resource for the specified type, if not found, use +	// the "UNKNOWN" type. +	std::vector<std::string> res = doAutocomplete(path, type, relativeTo); +	if (!res.empty()) { +		return res; +	} + +	// Use the "UNKNOWN" type +	if (type != ResourceType::UNKNOWN) { +		return doAutocomplete(path, ResourceType::UNKNOWN, relativeTo); +	} +	return std::vector<std::string>{}; +} +  bool ResourceLocator::locate(Resource &resource, const std::string &path,                               const ResourceType type,                               const Resource &relativeTo) const @@ -59,6 +90,14 @@ std::unique_ptr<std::istream> ResourceLocator::stream(  	return doStream(location);  } +std::vector<std::string> ResourceLocator::doAutocomplete( +    const std::string &path, const ResourceType type, +    const std::string &relativeTo) const +{ +	// Default implementation +	return std::vector<std::string>{}; +} +  /* Class StaticResourceLocator */  bool StaticResourceLocator::doLocate(Resource &resource, diff --git a/src/core/resource/ResourceLocator.hpp b/src/core/resource/ResourceLocator.hpp index c1d0807..d6a2ffc 100644 --- a/src/core/resource/ResourceLocator.hpp +++ b/src/core/resource/ResourceLocator.hpp @@ -21,6 +21,7 @@  #include <istream>  #include <memory> +#include <vector>  #include "Resource.hpp" @@ -60,6 +61,23 @@ protected:  	                      const std::string &relativeTo) const = 0;  	/** +	 * Tries to autocomplete the given filename by searching for files with this +	 * basename but different extensions. Returns a list of possible extended +	 * paths. May return an empty list if this function is not supported. +	 * +	 * @param path is the given filename for which versions with extension +	 * should be searched. +	 * @param type is the resource type, determining the search paths in which +	 * the resource is looked up. +	 * @param relativeTo is an already resolved Resource relative to which the +	 * file should be searched. +	 * @return a list of matching, autocompleted file paths. +	 */ +	virtual std::vector<std::string> doAutocomplete( +	    const std::string &path, const ResourceType type, +	    const std::string &relativeTo) const; + +	/**  	 * This method returns a stream containing the data of the resource at the  	 * given location.  	 * @@ -80,6 +98,41 @@ public:  	virtual ~ResourceLocator() {}  	/** +	 * Tries to autocomplete the given filename by searching for files with this +	 * basename but different extensions. Returns a list of possible extended +	 * paths. May return an empty list if this function is not supported. +	 * +	 * @param path is the given filename for which versions with extension +	 * should be searched. +	 * @param type is the resource type, determining the search paths in which +	 * the resource is looked up. +	 * @param relativeTo is an already resolved Resource relative to which the +	 * file should be searched. +	 * @return a list of matching, autocompleted file paths. +	 */ +	std::vector<std::string> autocomplete( +	    const std::string &path, +	    const ResourceType type = ResourceType::UNKNOWN, +	    const Resource &relativeTo = NullResource) const; + +	/** +	 * Tries to autocomplete the given filename by searching for files with this +	 * basename but different extensions. Returns a list of possible extended +	 * paths. May return an empty list if this function is not supported. +	 * +	 * @param path is the given filename for which versions with extension +	 * should be searched. +	 * @param type is the resource type, determining the search paths in which +	 * the resource is looked up. +	 * @param relativeTo is the location of an already resolved resource +	 * relative to which this resource should be located. +	 * @return a list of matching, autocompleted file paths. +	 */ +	std::vector<std::string> autocomplete(const std::string &path, +	                                      const ResourceType type, +	                                      const std::string &relativeTo) const; + +	/**  	 * The locate function uses this ResourceLocator to search for a given  	 * Resource name (path parameter).  	 * @@ -109,8 +162,7 @@ public:  	 * @return true if a resource could be found, false otherwise.  	 */  	bool locate(Resource &resource, const std::string &path, -	            const ResourceType type, -	            const std::string &relativeTo) const; +	            const ResourceType type, const std::string &relativeTo) const;  	/**  	 * This method returns a stream containing the data of the resource at the @@ -123,7 +175,7 @@ public:  	 *         C++11 compiler does not yet support move semantics for  	 *         streams.  	 */ -	std::unique_ptr<std::istream> stream(const std::string &location) const;	 +	std::unique_ptr<std::istream> stream(const std::string &location) const;  };  /** diff --git a/src/core/resource/ResourceManager.cpp b/src/core/resource/ResourceManager.cpp index 74fd5ad..e3edfc8 100644 --- a/src/core/resource/ResourceManager.cpp +++ b/src/core/resource/ResourceManager.cpp @@ -101,10 +101,10 @@ NodeVector<Node> ResourceManager::parse(  	// Locate the resource relative to the old resource, abort if this did not  	// work -	ResourceRequest req{path, mimetype, rel, supportedTypes}; +	ResourceRequest req{path, mimetype, rel, supportedTypes, relativeTo};  	Resource resource;  	if (!req.deduce(registry, logger) || -	    !req.locate(registry, logger, resource, relativeTo)) { +	    !req.locate(registry, logger, resource)) {  		return NodeVector<Node>{};  	} diff --git a/src/core/resource/ResourceRequest.cpp b/src/core/resource/ResourceRequest.cpp index 0803208..0216388 100644 --- a/src/core/resource/ResourceRequest.cpp +++ b/src/core/resource/ResourceRequest.cpp @@ -136,11 +136,13 @@ static RttiSet limitSupportedTypes(ResourceType resourceType,  ResourceRequest::ResourceRequest(const std::string &path,                                   const std::string &mimetype,                                   const std::string &rel, -                                 const RttiSet &supportedTypes) +                                 const RttiSet &supportedTypes, +                                 const Resource &relativeTo)      : path(path),        mimetype(mimetype),        rel(rel),        supportedTypes(supportedTypes), +      relativeTo(relativeTo),        resourceType(ResourceType::UNKNOWN),        parser(nullptr)  { @@ -156,11 +158,49 @@ bool ResourceRequest::deduce(Registry ®istry, Logger &logger)  		return false;  	} +	// Try to deduce the ResourceType from the "rel" string +	if (!rel.empty()) { +		resourceType = Resource::getResourceTypeByName(rel); +		if (resourceType == ResourceType::UNKNOWN) { +			logger.error(std::string("Unknown relation \"") + rel + +			             std::string("\", expected one of ") + +			             supportedResourceTypesString(supportedTypes)); +			ok = false; +		} +	} + +	// Try to deduce the ResourceType from the supportedTypes +	if (resourceType == ResourceType::UNKNOWN) { +		resourceType = deduceResourceType(supportedTypes); +	} + +	// If the given file has no extension, try to complete it +	std::string ext = Utils::extractFileExtension(path); +	if (ext.empty()) { +		std::vector<std::string> paths = +		    registry.autocompleteResource(path, resourceType, relativeTo); +		if (paths.size() > 1U) { +			// There are multiple possible files +			// TODO: Select the one which matches the other parameters +			logger.error(std::string("Resource \"") + path + +			             std::string("\" is ambiguous.")); +			logger.note(std::string("Possibly referenced files are:"), +			            SourceLocation{}, MessageMode::NO_CONTEXT); +			for (const auto &p : paths) { +				logger.note(p, SourceLocation{}, MessageMode::NO_CONTEXT); +			} +			ok = false; +		} else if (paths.size() == 1U) { +			// Otherwise just copy the first resolved element +			path = paths[0]; +		} +	} +  	// Try to deduce the mimetype if none was given  	if (mimetype.empty()) {  		mimetype = registry.getMimetypeForFilename(path);  		if (mimetype.empty()) { -			logger.error(std::string("Filename \"") + path + +			logger.error(std::string("Resource \"") + path +  			             std::string(  			                 "\" has an unknown file extension. Explicitly "  			                 "specify a mimetype.")); @@ -187,22 +227,6 @@ bool ResourceRequest::deduce(Registry ®istry, Logger &logger)  		}  	} -	// Try to deduce the ResourceType from the "rel" string -	if (!rel.empty()) { -		resourceType = Resource::getResourceTypeByName(rel); -		if (resourceType == ResourceType::UNKNOWN) { -			logger.error(std::string("Unknown relation \"") + rel + -			             std::string("\", expected one of ") + -			             supportedResourceTypesString(supportedTypes)); -			ok = false; -		} -	} - -	// Try to deduce the ResourceType from the supportedTypes -	if (resourceType == ResourceType::UNKNOWN) { -		resourceType = deduceResourceType(supportedTypes); -	} -  	// Further limit the supportedTypes to those types that correspond to the  	// specified resource type.  	if (resourceType != ResourceType::UNKNOWN) { @@ -227,8 +251,7 @@ bool ResourceRequest::deduce(Registry ®istry, Logger &logger)  }  bool ResourceRequest::locate(Registry ®istry, Logger &logger, -                             Resource &resource, -                             const Resource &relativeTo) const +                             Resource &resource) const  {  	if (!registry.locateResource(resource, path, resourceType, relativeTo)) {  		logger.error(std::string("File not found: ") + path); diff --git a/src/core/resource/ResourceRequest.hpp b/src/core/resource/ResourceRequest.hpp index 9d5728f..a06d360 100644 --- a/src/core/resource/ResourceRequest.hpp +++ b/src/core/resource/ResourceRequest.hpp @@ -77,6 +77,11 @@ private:  	RttiSet parserTypes;  	/** +	 * The resource relative to which this resource is to be located. +	 */ +	Resource relativeTo; + +	/**  	 * ResourceType as deduced from the user provided values.  	 */  	ResourceType resourceType; @@ -101,9 +106,12 @@ public:  	 * @param supportedTypes specifies the types of the Node that may result  	 * from the resource once it has been parsed. This value is not directly  	 * provided by the user, but by the calling code. +	 * @param relativeTo is another resource relative to which the Resource +	 * should be looked up.  	 */  	ResourceRequest(const std::string &path, const std::string &mimetype, -	                const std::string &rel, const RttiSet &supportedTypes); +	                const std::string &rel, const RttiSet &supportedTypes, +	                const Resource &relativeTo = NullResource);  	/**  	 * Tries to deduce all possible information and produces log messages for @@ -127,13 +135,10 @@ public:  	 * logged.  	 * @param resource is the Resource descriptor that should be filled with the  	 * actual location. -	 * @param relativeTo is another resource relative to which the Resource -	 * should be looked up.  	 * @return true if a resource was found, false otherwise. Equivalent to  	 * the value of resource.isValid().  	 */ -	bool locate(Registry ®istry, Logger &logger, Resource &resource, -	            const Resource &relativeTo = NullResource) const; +	bool locate(Registry ®istry, Logger &logger, Resource &resource) const;  	/**  	 * Returns the requested path of the file that should be included.  | 
