Rename the ResourceProxy class to EmbeddedResourceProxy
This is done so as to avoid confusion with the unrelated classes ResourceProvider and ResourceManager already present in SimGear. Despite this new name, EmbeddedResourceProxy is a proxy not only for embedded resources, but also for real files (hence the initial name choice): its purpose is precisely to allow zero-work switching from one data source to the other.
This commit is contained in:
@@ -1,7 +1,11 @@
|
||||
include (SimGearComponent)
|
||||
|
||||
set(HEADERS EmbeddedResource.hxx EmbeddedResourceManager.hxx ResourceProxy.hxx)
|
||||
set(SOURCES EmbeddedResource.cxx EmbeddedResourceManager.cxx ResourceProxy.cxx)
|
||||
set(HEADERS EmbeddedResource.hxx
|
||||
EmbeddedResourceManager.hxx
|
||||
EmbeddedResourceProxy.hxx)
|
||||
set(SOURCES EmbeddedResource.cxx
|
||||
EmbeddedResourceManager.cxx
|
||||
EmbeddedResourceProxy.cxx)
|
||||
|
||||
simgear_component(embedded_resources embedded_resources
|
||||
"${SOURCES}" "${HEADERS}")
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// -*- coding: utf-8 -*-
|
||||
//
|
||||
// ResourceProxy.cxx --- Unified access to real files or embedded resources
|
||||
// EmbeddedResourceProxy.cxx --- Unified access to real files or embedded
|
||||
// resources
|
||||
// Copyright (C) 2017 Florent Rougon
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
@@ -35,7 +36,7 @@
|
||||
#include <simgear/io/iostreams/sgstream.hxx>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
#include "EmbeddedResourceManager.hxx"
|
||||
#include "ResourceProxy.hxx"
|
||||
#include "EmbeddedResourceProxy.hxx"
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
@@ -46,35 +47,36 @@ using std::unique_ptr;
|
||||
namespace simgear
|
||||
{
|
||||
|
||||
ResourceProxy::ResourceProxy(const SGPath& realRoot, const string& virtualRoot,
|
||||
bool useEmbeddedResourcesByDefault)
|
||||
EmbeddedResourceProxy::EmbeddedResourceProxy(const SGPath& realRoot,
|
||||
const string& virtualRoot,
|
||||
bool useEmbeddedResourcesByDefault)
|
||||
: _realRoot(realRoot),
|
||||
_virtualRoot(normalizeVirtualRoot(virtualRoot)),
|
||||
_useEmbeddedResourcesByDefault(useEmbeddedResourcesByDefault)
|
||||
{ }
|
||||
|
||||
SGPath
|
||||
ResourceProxy::getRealRoot() const
|
||||
EmbeddedResourceProxy::getRealRoot() const
|
||||
{ return _realRoot; }
|
||||
|
||||
void
|
||||
ResourceProxy::setRealRoot(const SGPath& realRoot)
|
||||
EmbeddedResourceProxy::setRealRoot(const SGPath& realRoot)
|
||||
{ _realRoot = realRoot; }
|
||||
|
||||
string
|
||||
ResourceProxy::getVirtualRoot() const
|
||||
EmbeddedResourceProxy::getVirtualRoot() const
|
||||
{ return _virtualRoot; }
|
||||
|
||||
void
|
||||
ResourceProxy::setVirtualRoot(const string& virtualRoot)
|
||||
EmbeddedResourceProxy::setVirtualRoot(const string& virtualRoot)
|
||||
{ _virtualRoot = normalizeVirtualRoot(virtualRoot); }
|
||||
|
||||
bool
|
||||
ResourceProxy::getUseEmbeddedResources() const
|
||||
EmbeddedResourceProxy::getUseEmbeddedResources() const
|
||||
{ return _useEmbeddedResourcesByDefault; }
|
||||
|
||||
void
|
||||
ResourceProxy::setUseEmbeddedResources(bool useEmbeddedResources)
|
||||
EmbeddedResourceProxy::setUseEmbeddedResources(bool useEmbeddedResources)
|
||||
{ _useEmbeddedResourcesByDefault = useEmbeddedResources; }
|
||||
|
||||
// Static method: normalize the 'virtualRoot' argument of the constructor
|
||||
@@ -82,9 +84,10 @@ ResourceProxy::setUseEmbeddedResources(bool useEmbeddedResources)
|
||||
// The argument must start with a slash and mustn't contain any '.' or '..'
|
||||
// component. The return value never ends with a slash.
|
||||
string
|
||||
ResourceProxy::normalizeVirtualRoot(const string& path)
|
||||
EmbeddedResourceProxy::normalizeVirtualRoot(const string& path)
|
||||
{
|
||||
ResourceProxy::checkPath(__func__, path, false /* allowStartWithColon */);
|
||||
EmbeddedResourceProxy::checkPath(__func__, path,
|
||||
false /* allowStartWithColon */);
|
||||
string res = path;
|
||||
|
||||
// Make sure 'res' doesn't end with a '/'.
|
||||
@@ -97,21 +100,22 @@ ResourceProxy::normalizeVirtualRoot(const string& path)
|
||||
|
||||
// Static method
|
||||
void
|
||||
ResourceProxy::checkPath(const string& callerMethod, const string& path,
|
||||
bool allowStartWithColon) {
|
||||
EmbeddedResourceProxy::checkPath(const string& callerMethod, const string& path,
|
||||
bool allowStartWithColon)
|
||||
{
|
||||
if (path.empty()) {
|
||||
throw sg_format_exception(
|
||||
"Invalid empty path for ResourceProxy::" + callerMethod + "(): '" +
|
||||
path + "'", path);
|
||||
"Invalid empty path for EmbeddedResourceProxy::" +
|
||||
callerMethod + "(): '" + path + "'", path);
|
||||
} else if (allowStartWithColon &&
|
||||
!simgear::strutils::starts_with(path, ":/") && path[0] != '/') {
|
||||
throw sg_format_exception(
|
||||
"Invalid path for ResourceProxy::" + callerMethod + "(): it should "
|
||||
"start with either ':/' or '/'", path);
|
||||
"Invalid path for EmbeddedResourceProxy::" + callerMethod + "(): "
|
||||
"it should start with either ':/' or '/'", path);
|
||||
} else if (!allowStartWithColon && path[0] != '/') {
|
||||
throw sg_format_exception(
|
||||
"Invalid path for ResourceProxy::" + callerMethod + "(): it should "
|
||||
"start with a slash ('/')", path);
|
||||
"Invalid path for EmbeddedResourceProxy::" + callerMethod + "(): "
|
||||
"it should start with a slash ('/')", path);
|
||||
} else {
|
||||
const vector<string> components = simgear::strutils::split(path, "/");
|
||||
auto find = [&components](const string& s) -> bool {
|
||||
@@ -121,16 +125,18 @@ ResourceProxy::checkPath(const string& callerMethod, const string& path,
|
||||
|
||||
if (find(".") || find("..")) {
|
||||
throw sg_format_exception(
|
||||
"Invalid path for ResourceProxy::" + callerMethod + "(): "
|
||||
"Invalid path for EmbeddedResourceProxy::" + callerMethod + "(): "
|
||||
"'.' and '..' components are not allowed", path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unique_ptr<std::istream>
|
||||
ResourceProxy::getIStream(const string& path, bool fromEmbeddedResource) const
|
||||
EmbeddedResourceProxy::getIStream(const string& path, bool fromEmbeddedResource)
|
||||
const
|
||||
{
|
||||
ResourceProxy::checkPath(__func__, path, false /* allowStartWithColon */);
|
||||
EmbeddedResourceProxy::checkPath(__func__, path,
|
||||
false /* allowStartWithColon */);
|
||||
assert(!path.empty() && path.front() == '/');
|
||||
|
||||
if (fromEmbeddedResource) {
|
||||
@@ -145,15 +151,16 @@ ResourceProxy::getIStream(const string& path, bool fromEmbeddedResource) const
|
||||
}
|
||||
|
||||
unique_ptr<std::istream>
|
||||
ResourceProxy::getIStream(const string& path) const
|
||||
EmbeddedResourceProxy::getIStream(const string& path) const
|
||||
{
|
||||
return getIStream(path, _useEmbeddedResourcesByDefault);
|
||||
}
|
||||
|
||||
unique_ptr<std::istream>
|
||||
ResourceProxy::getIStreamDecideOnPrefix(const string& path) const
|
||||
EmbeddedResourceProxy::getIStreamDecideOnPrefix(const string& path) const
|
||||
{
|
||||
ResourceProxy::checkPath(__func__, path, true /* allowStartWithColon */);
|
||||
EmbeddedResourceProxy::checkPath(__func__, path,
|
||||
true /* allowStartWithColon */);
|
||||
|
||||
// 'path' is non-empty
|
||||
if (path.front() == '/') {
|
||||
@@ -170,11 +177,13 @@ ResourceProxy::getIStreamDecideOnPrefix(const string& path) const
|
||||
}
|
||||
|
||||
string
|
||||
ResourceProxy::getString(const string& path, bool fromEmbeddedResource) const
|
||||
EmbeddedResourceProxy::getString(const string& path, bool fromEmbeddedResource)
|
||||
const
|
||||
{
|
||||
string result;
|
||||
|
||||
ResourceProxy::checkPath(__func__, path, false /* allowStartWithColon */);
|
||||
EmbeddedResourceProxy::checkPath(__func__, path,
|
||||
false /* allowStartWithColon */);
|
||||
assert(!path.empty() && path.front() == '/');
|
||||
|
||||
if (fromEmbeddedResource) {
|
||||
@@ -216,17 +225,18 @@ ResourceProxy::getString(const string& path, bool fromEmbeddedResource) const
|
||||
}
|
||||
|
||||
string
|
||||
ResourceProxy::getString(const string& path) const
|
||||
EmbeddedResourceProxy::getString(const string& path) const
|
||||
{
|
||||
return getString(path, _useEmbeddedResourcesByDefault);
|
||||
}
|
||||
|
||||
string
|
||||
ResourceProxy::getStringDecideOnPrefix(const string& path) const
|
||||
EmbeddedResourceProxy::getStringDecideOnPrefix(const string& path) const
|
||||
{
|
||||
string result;
|
||||
|
||||
ResourceProxy::checkPath(__func__, path, true /* allowStartWithColon */);
|
||||
EmbeddedResourceProxy::checkPath(__func__, path,
|
||||
true /* allowStartWithColon */);
|
||||
|
||||
// 'path' is non-empty
|
||||
if (path.front() == '/') {
|
||||
@@ -1,6 +1,7 @@
|
||||
// -*- coding: utf-8 -*-
|
||||
//
|
||||
// ResourceProxy.hxx --- Unified access to real files or embedded resources
|
||||
// EmbeddedResourceProxy.hxx --- Unified access to real files or embedded
|
||||
// resources
|
||||
// Copyright (C) 2017 Florent Rougon
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
@@ -18,8 +19,8 @@
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301 USA.
|
||||
|
||||
#ifndef FG_RESOURCEPROXY_HXX
|
||||
#define FG_RESOURCEPROXY_HXX
|
||||
#ifndef FG_EMBEDDEDRESOURCEPROXY_HXX
|
||||
#define FG_EMBEDDEDRESOURCEPROXY_HXX
|
||||
|
||||
#include <istream>
|
||||
#include <memory>
|
||||
@@ -27,26 +28,27 @@
|
||||
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
|
||||
// The ResourceProxy class allows one to access real files or embedded
|
||||
// The EmbeddedResourceProxy class allows one to access real files or embedded
|
||||
// resources in a unified way. When using it, one can switch from one data
|
||||
// source to the other with minimal code changes, possibly even at runtime (in
|
||||
// which case there is obviously no code change at all).
|
||||
//
|
||||
// Sample usage of the ResourceProxy class (from FlightGear):
|
||||
// Sample usage of the EmbeddedResourceProxy class (from FlightGear):
|
||||
//
|
||||
// simgear::ResourceProxy proxy(globals->get_fg_root(), "/FGData");
|
||||
// simgear::EmbeddedResourceProxy proxy(globals->get_fg_root(), "/FGData");
|
||||
// std::string s = proxy.getString("/some/path");
|
||||
// std::unique_ptr<std::istream> streamp = proxy.getIStream("/some/path");
|
||||
//
|
||||
// The methods ResourceProxy::getString(const std::string& path) and
|
||||
// ResourceProxy::getIStream(const std::string& path) decide whether to use
|
||||
// embedded resources or real files depending on the boolean value passed to
|
||||
// ResourceProxy::setUseEmbeddedResources() (also available as an optional
|
||||
// parameter to the ResourceProxy constructor, defaulting to true). It is
|
||||
// often most convenient to set this boolean once and then don't worry about
|
||||
// it anymore (it is stored inside ResourceProxy). Otherwise, if you want to
|
||||
// fetch resources some times from real files, other times from embedded
|
||||
// resources, you may use the following methods:
|
||||
// The methods getString(const std::string& path) and
|
||||
// getIStream(const std::string& path) of EmbeddedResourceProxy decide whether
|
||||
// to use embedded resources or real files depending on the boolean value
|
||||
// passed to EmbeddedResourceProxy::setUseEmbeddedResources() (also available
|
||||
// as an optional parameter to the EmbeddedResourceProxy constructor,
|
||||
// defaulting to true). It is often most convenient to set this boolean once
|
||||
// and then don't worry about it anymore (it is stored as a data member of
|
||||
// EmbeddedResourceProxy). Otherwise, if you want to fetch resources some
|
||||
// times from real files, other times from embedded resources, you may use the
|
||||
// following methods:
|
||||
//
|
||||
// // Retrieve contents using embedded resources
|
||||
// std:string s = proxy.getString("/some/path", true);
|
||||
@@ -56,8 +58,8 @@
|
||||
// std:string s = proxy.getString("/some/path", false);
|
||||
// std:string s = proxy.getStringDecideOnPrefix("/some/path");
|
||||
//
|
||||
// You can do exactly the same with ResourceProxy::getIStream() and
|
||||
// ResourceProxy::getIStreamDecideOnPrefix(), except they return an
|
||||
// You can do exactly the same with EmbeddedResourceProxy::getIStream() and
|
||||
// EmbeddedResourceProxy::getIStreamDecideOnPrefix(), except they return an
|
||||
// std::unique_ptr<std::istream> instead of an std::string.
|
||||
//
|
||||
// Given how the 'proxy' object was constructed above, each of these calls
|
||||
@@ -65,8 +67,9 @@
|
||||
// embedded resource whose virtual path is '/FGData/some/path' (more
|
||||
// precisely: the default-locale version of this resource).
|
||||
//
|
||||
// The 'path' argument of ResourceProxy's methods getString(), getIStream(),
|
||||
// getStringDecideOnPrefix() and getIStreamDecideOnPrefix() must:
|
||||
// The 'path' argument of EmbeddedResourceProxy's methods getString(),
|
||||
// getIStream(), getStringDecideOnPrefix() and getIStreamDecideOnPrefix()
|
||||
// must:
|
||||
//
|
||||
// - use UTF-8 encoding;
|
||||
//
|
||||
@@ -82,21 +85,21 @@
|
||||
//
|
||||
// - if the path starts with a slash ('/'), a real file access is done;
|
||||
//
|
||||
// - if, on the other hand, it starts with ':/', ResourceProxy uses the
|
||||
// embedded resource whose virtual path is the specified path without its
|
||||
// leading ':' (more precisely: the default-locale version of this
|
||||
// - if, on the other hand, it starts with ':/', EmbeddedResourceProxy uses
|
||||
// the embedded resource whose virtual path is the specified path without
|
||||
// its leading ':' (more precisely: the default-locale version of this
|
||||
// resource).
|
||||
namespace simgear
|
||||
{
|
||||
|
||||
class ResourceProxy
|
||||
class EmbeddedResourceProxy
|
||||
{
|
||||
public:
|
||||
// 'virtualRoot' must start with a '/', e.g: '/FGData'. Whether it ends
|
||||
// with a '/' doesn't make a difference.
|
||||
explicit ResourceProxy(const SGPath& realRoot,
|
||||
const std::string& virtualRoot,
|
||||
bool useEmbeddedResourcesByDefault = true);
|
||||
explicit EmbeddedResourceProxy(const SGPath& realRoot,
|
||||
const std::string& virtualRoot,
|
||||
bool useEmbeddedResourcesByDefault = true);
|
||||
|
||||
// Getters and setters for the corresponding data members
|
||||
SGPath getRealRoot() const;
|
||||
@@ -149,4 +152,4 @@ private:
|
||||
|
||||
} // of namespace simgear
|
||||
|
||||
#endif // of FG_RESOURCEPROXY_HXX
|
||||
#endif // of FG_EMBEDDEDRESOURCEPROXY_HXX
|
||||
@@ -40,7 +40,7 @@
|
||||
#include <simgear/io/iostreams/zlibstream.hxx>
|
||||
#include "EmbeddedResource.hxx"
|
||||
#include "EmbeddedResourceManager.hxx"
|
||||
#include "ResourceProxy.hxx"
|
||||
#include "EmbeddedResourceProxy.hxx"
|
||||
|
||||
using std::cout;
|
||||
using std::cerr;
|
||||
@@ -398,11 +398,11 @@ void test_getLocaleAndSelectLocale()
|
||||
}
|
||||
}
|
||||
|
||||
// Auxiliary function for test_ResourceProxy()
|
||||
void auxTest_ResourceProxy_getIStream(unique_ptr<std::istream> iStream,
|
||||
const string& contents)
|
||||
// Auxiliary function for test_EmbeddedResourceProxy()
|
||||
void auxTest_EmbeddedResourceProxy_getIStream(unique_ptr<std::istream> iStream,
|
||||
const string& contents)
|
||||
{
|
||||
cout << "Testing ResourceProxy::getIStream()" << endl;
|
||||
cout << "Testing EmbeddedResourceProxy::getIStream()" << endl;
|
||||
|
||||
iStream->exceptions(std::ios_base::badbit);
|
||||
static constexpr std::size_t bufSize = 65536;
|
||||
@@ -421,9 +421,9 @@ void auxTest_ResourceProxy_getIStream(unique_ptr<std::istream> iStream,
|
||||
SG_CHECK_EQUAL(result, contents);
|
||||
}
|
||||
|
||||
void test_ResourceProxy()
|
||||
void test_EmbeddedResourceProxy()
|
||||
{
|
||||
cout << "Testing the ResourceProxy class" << endl;
|
||||
cout << "Testing the EmbeddedResourceProxy class" << endl;
|
||||
|
||||
// Initialize stuff we need and create two files containing the contents of
|
||||
// the default-locale version of two embedded resources: those with virtual
|
||||
@@ -456,14 +456,14 @@ void test_ResourceProxy()
|
||||
}
|
||||
|
||||
// 'proxy' defaults to using embedded resources
|
||||
const simgear::ResourceProxy proxy(tmpDir.path(),
|
||||
"/path/to",
|
||||
true /* useEmbeddedResourcesByDefault */);
|
||||
simgear::ResourceProxy rproxy(tmpDir.path(), "/path/to");
|
||||
const simgear::EmbeddedResourceProxy proxy(tmpDir.path(), "/path/to",
|
||||
/* useEmbeddedResourcesByDefault */
|
||||
true);
|
||||
simgear::EmbeddedResourceProxy rproxy(tmpDir.path(), "/path/to");
|
||||
// 'rproxy' defaults to using real files
|
||||
rproxy.setUseEmbeddedResources(false); // could be done from the ctor too
|
||||
|
||||
// Test ResourceProxy::getString()
|
||||
// Test EmbeddedResourceProxy::getString()
|
||||
SG_CHECK_EQUAL(proxy.getStringDecideOnPrefix("/resource1"), rs1);
|
||||
SG_CHECK_EQUAL(proxy.getStringDecideOnPrefix(":/resource1"), s1);
|
||||
SG_CHECK_EQUAL(proxy.getString("/resource1", false), rs1);
|
||||
@@ -478,20 +478,24 @@ void test_ResourceProxy()
|
||||
SG_CHECK_EQUAL(proxy.getString("/resource2"), lipsum);
|
||||
SG_CHECK_EQUAL(rproxy.getString("/resource2"), rlipsum);
|
||||
|
||||
// Test ResourceProxy::getIStream()
|
||||
auxTest_ResourceProxy_getIStream(proxy.getIStreamDecideOnPrefix("/resource1"),
|
||||
rs1);
|
||||
auxTest_ResourceProxy_getIStream(proxy.getIStreamDecideOnPrefix(":/resource1"),
|
||||
s1);
|
||||
auxTest_ResourceProxy_getIStream(proxy.getIStream("/resource1"), s1);
|
||||
auxTest_ResourceProxy_getIStream(rproxy.getIStream("/resource1"), rs1);
|
||||
// Test EmbeddedResourceProxy::getIStream()
|
||||
auxTest_EmbeddedResourceProxy_getIStream(
|
||||
proxy.getIStreamDecideOnPrefix("/resource1"),
|
||||
rs1);
|
||||
auxTest_EmbeddedResourceProxy_getIStream(
|
||||
proxy.getIStreamDecideOnPrefix(":/resource1"),
|
||||
s1);
|
||||
auxTest_EmbeddedResourceProxy_getIStream(proxy.getIStream("/resource1"), s1);
|
||||
auxTest_EmbeddedResourceProxy_getIStream(rproxy.getIStream("/resource1"), rs1);
|
||||
|
||||
auxTest_ResourceProxy_getIStream(proxy.getIStream("/resource2", false),
|
||||
rlipsum);
|
||||
auxTest_ResourceProxy_getIStream(proxy.getIStream("/resource2", true),
|
||||
lipsum);
|
||||
auxTest_ResourceProxy_getIStream(proxy.getIStream("/resource2"), lipsum);
|
||||
auxTest_ResourceProxy_getIStream(rproxy.getIStream("/resource2"), rlipsum);
|
||||
auxTest_EmbeddedResourceProxy_getIStream(proxy.getIStream("/resource2", false),
|
||||
rlipsum);
|
||||
auxTest_EmbeddedResourceProxy_getIStream(proxy.getIStream("/resource2", true),
|
||||
lipsum);
|
||||
auxTest_EmbeddedResourceProxy_getIStream(proxy.getIStream("/resource2"),
|
||||
lipsum);
|
||||
auxTest_EmbeddedResourceProxy_getIStream(rproxy.getIStream("/resource2"),
|
||||
rlipsum);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
@@ -506,7 +510,7 @@ int main(int argc, char **argv)
|
||||
test_addAlreadyExistingResource();
|
||||
test_localeDependencyOfResourceFetching();
|
||||
test_getLocaleAndSelectLocale();
|
||||
test_ResourceProxy();
|
||||
test_EmbeddedResourceProxy();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user