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:
Florent Rougon
2017-10-07 00:41:02 +02:00
parent e5e112c3c2
commit 2200fad30e
4 changed files with 107 additions and 86 deletions

View File

@@ -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}")

View File

@@ -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() == '/') {

View File

@@ -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

View File

@@ -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;
}