Fixed issue by providing a compatibility bridge between tl::Stream (abstract paths) and tl::URI (#734)

This commit is contained in:
Matthias Köfferlein 2021-02-25 21:28:48 +01:00 committed by GitHub
parent 483f67307c
commit 8b2ecf41df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 70 additions and 17 deletions

View File

@ -395,7 +395,7 @@ void NetlistSpiceReader::push_stream (const std::string &path)
istream = new tl::InputStream (tl::combine_path (tl::dirname (mp_stream->source ()), path));
}
} else {
istream = new tl::InputStream (current_uri.resolved (new_uri).to_string ());
istream = new tl::InputStream (current_uri.resolved (new_uri).to_abstract_path ());
}
m_streams.push_back (std::make_pair (istream, mp_stream.release ()));

View File

@ -1343,7 +1343,7 @@ Object::from_string (const char *str, const char *base_dir)
tl::URI fp_uri (m_filename);
if (base_dir && ! tl::is_absolute (fp_uri.path ())) {
m_filename = tl::URI (base_dir).resolved (fp_uri).to_string ();
m_filename = tl::URI (base_dir).resolved (fp_uri).to_abstract_path ();
}
read_file ();

View File

@ -145,7 +145,7 @@ Session::make_absolute (const std::string &fp) const
{
tl::URI fp_uri (fp);
if (! m_base_dir.empty () && ! tl::is_absolute (fp_uri.path ())) {
return tl::URI (m_base_dir).resolved (fp_uri).to_string ();
return tl::URI (m_base_dir).resolved (fp_uri).to_abstract_path ();
} else {
return fp;
}

View File

@ -211,7 +211,7 @@ static bool find_and_normalize_file (const tl::URI &uri, std::string &path)
// TODO: this is not quite efficient, but the only thing we can do for now
tl::URI uri_with_ext = uri;
uri_with_ext.set_path (uri_with_ext.path () + extensions[e]);
std::string us = uri_with_ext.to_string ();
std::string us = uri_with_ext.to_abstract_path ();
if (tl::verbosity () >= 30) {
tl::log << tl::to_string (tr ("Trying layout URI: ")) << us;

View File

@ -97,7 +97,7 @@ IncludeExpander::read (const std::string &path, tl::InputStream &is, std::string
include_path = tl::combine_path (tl::dirname (path), include_path);
}
} else {
include_path = current_uri.resolved (new_uri).to_string ();
include_path = current_uri.resolved (new_uri).to_abstract_path ();
}
tl::InputStream is (include_path);

View File

@ -167,9 +167,10 @@ InputStream::InputStream (const std::string &abstract_path)
tl::Extractor ex (abstract_path.c_str ());
#if defined(HAVE_QT)
if (ex.test (":")) {
#if defined(HAVE_QT)
QResource res (tl::to_qstring (abstract_path));
if (res.size () > 0) {
@ -189,20 +190,32 @@ InputStream::InputStream (const std::string &abstract_path)
}
} else
#else
throw tl::Exception (tl::to_string (tr ("Qt not enabled - resource paths are not available")));
#endif
#if defined(HAVE_CURL) || defined(HAVE_QT)
if (ex.test ("http:") || ex.test ("https:")) {
mp_delegate = new InputHttpStream (abstract_path);
} else
#endif
if (ex.test ("pipe:")) {
} else if (ex.test ("pipe:")) {
mp_delegate = new InputPipe (ex.get ());
} else if (ex.test ("file:")) {
tl::URI uri (abstract_path);
mp_delegate = new InputZLibFile (uri.path ());
} else {
mp_delegate = new InputZLibFile (abstract_path);
tl::URI uri (abstract_path);
if (uri.scheme () == "http" || uri.scheme () == "https") {
#if defined(HAVE_CURL) || defined(HAVE_QT)
mp_delegate = new InputHttpStream (abstract_path);
#else
throw tl::Exception (tl::to_string (tr ("HTTP support not enabled - HTTP/HTTPS paths are not available")));
#endif
} else if (uri.scheme () == "file") {
mp_delegate = new InputZLibFile (uri.path ());
} else if (! uri.scheme ().empty ()) {
throw tl::Exception (tl::to_string (tr ("URI scheme not supported: ")) + uri.scheme ());
} else {
mp_delegate = new InputZLibFile (abstract_path);
}
}
if (! mp_buffer) {

View File

@ -398,6 +398,8 @@ public:
*
* This will automatically create the appropriate delegate and
* delete it later.
*
* The abstract path
*/
InputStream (const std::string &abstract_path);

View File

@ -209,6 +209,16 @@ URI::to_string () const
return res;
}
std::string
URI::to_abstract_path () const
{
if (m_scheme.empty ()) {
return path ();
} else {
return to_string ();
}
}
URI
URI::resolved (const URI &other) const
{

View File

@ -144,6 +144,19 @@ public:
*/
std::string to_string () const;
/**
* @brief Turns the URI into an "abstract path"
*
* The "abstract path" is a concept provided by "tl::InputStream".
* URIs with scheme "file", "http" and "https" are equivalent to their abstract path.
* URIs without a scheme turn into system file paths.
* Other schemes are not allowed.
*
* Abstract paths are more powerful as they support pipes and Qt resource access.
* These modes are not supported by URIs.
*/
std::string to_abstract_path () const;
/**
* @brief Resolves an URI relative to this one
*/

View File

@ -164,6 +164,8 @@ TEST(2)
// use case taken from Magic writer:
tl::URI uri ("c:\\users\\myself\\path.txt");
EXPECT_EQ (uri.scheme (), "");
EXPECT_EQ (uri.path (), "c:\\users\\myself\\path.txt");
std::string ext = tl::extension (uri.path ());
EXPECT_EQ (ext, "txt");
@ -178,3 +180,16 @@ TEST(2)
throw;
}
}
// issue #733
TEST(3_pathsWithPlus)
{
EXPECT_EQ (tl::URI ("/users/a_plus_b").resolved (tl::URI ("file.txt")).to_string (), "/users/a_plus_b/file.txt");
EXPECT_EQ (tl::URI ("/users/a+b").resolved (tl::URI ("file.txt")).to_string (), "/users/a%2Bb/file.txt");
EXPECT_EQ (tl::URI ("/users/a+b").resolved (tl::URI ("file.txt")).to_abstract_path (), "/users/a+b/file.txt");
EXPECT_EQ (tl::URI ("file://users/a+b").resolved (tl::URI ("file.txt")).to_string (), "file://users/a%2Bb/file.txt");
EXPECT_EQ (tl::URI ("file://users/a+b").resolved (tl::URI ("file.txt")).to_abstract_path (), "file://users/a%2Bb/file.txt");
// drive-letter paths
EXPECT_EQ (tl::URI ("c:/users/a+b").resolved (tl::URI ("file.txt")).to_string (), "c:/users/a%2Bb/file.txt");
EXPECT_EQ (tl::URI ("c:/users/a+b").resolved (tl::URI ("file.txt")).to_abstract_path (), "c:/users/a+b/file.txt");
}