mirror of https://github.com/KLayout/klayout.git
Removed some further Qt dependencies. For example, HTTPS access now is possible without Qt through Curl only.
This commit is contained in:
parent
9ea24cb6a0
commit
8f04fc5358
|
|
@ -37,6 +37,7 @@
|
|||
#include "edtConfig.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
|
||||
namespace db {
|
||||
class Manager;
|
||||
|
|
|
|||
|
|
@ -55,7 +55,9 @@ SOURCES = \
|
|||
tlXMLParser.cc \
|
||||
tlXMLWriter.cc \
|
||||
tlThreadedWorkers.cc \
|
||||
tlThreads.cc
|
||||
tlThreads.cc \
|
||||
tlDeferredExecution.cc \
|
||||
tlUri.cc
|
||||
|
||||
HEADERS = \
|
||||
tlAlgorithm.h \
|
||||
|
|
@ -104,7 +106,9 @@ HEADERS = \
|
|||
tlXMLParser.h \
|
||||
tlXMLWriter.h \
|
||||
tlThreadedWorkers.h \
|
||||
tlThreads.h
|
||||
tlThreads.h \
|
||||
tlDeferredExecution.h \
|
||||
tlUri.h
|
||||
|
||||
equals(HAVE_CURL, "1") {
|
||||
|
||||
|
|
@ -134,11 +138,11 @@ equals(HAVE_CURL, "1") {
|
|||
!equals(HAVE_QT, "0") {
|
||||
|
||||
HEADERS += \
|
||||
tlDeferredExecution.h \
|
||||
tlDeferredExecutionQt.h \
|
||||
tlFileSystemWatcher.h \
|
||||
|
||||
SOURCES += \
|
||||
tlDeferredExecution.cc \
|
||||
tlDeferredExecutionQt.cc \
|
||||
tlFileSystemWatcher.cc \
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,31 +22,21 @@
|
|||
|
||||
#include "tlDeferredExecution.h"
|
||||
#include "tlAssert.h"
|
||||
#include "tlLog.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <QApplication>
|
||||
#if defined(HAVE_QT)
|
||||
# include "tlDeferredExecutionQt.h"
|
||||
#endif
|
||||
|
||||
namespace tl
|
||||
{
|
||||
|
||||
static DeferredMethodScheduler *s_inst = 0;
|
||||
|
||||
DeferredMethodScheduler::DeferredMethodScheduler (QObject *parent)
|
||||
: QObject (parent),
|
||||
m_disabled (0), m_scheduled (false)
|
||||
DeferredMethodScheduler::DeferredMethodScheduler ()
|
||||
: m_disabled (0), m_scheduled (false)
|
||||
{
|
||||
connect (&m_timer, SIGNAL (timeout ()), this, SLOT (timer ()));
|
||||
|
||||
m_timer.setInterval (0); // immediately
|
||||
m_timer.setSingleShot (true); // just once
|
||||
|
||||
// set up a fallback timer that cleans up pending execute jobs if something goes wrong
|
||||
connect (&m_fallback_timer, SIGNAL (timeout ()), this, SLOT (timer ()));
|
||||
m_fallback_timer.setInterval (500);
|
||||
m_fallback_timer.setSingleShot (false);
|
||||
|
||||
tl_assert (! s_inst);
|
||||
s_inst = this;
|
||||
}
|
||||
|
|
@ -59,31 +49,33 @@ DeferredMethodScheduler::~DeferredMethodScheduler ()
|
|||
DeferredMethodScheduler *
|
||||
DeferredMethodScheduler::instance ()
|
||||
{
|
||||
if (! s_inst && qApp) {
|
||||
new DeferredMethodScheduler (qApp);
|
||||
// TODO: provide a way to register non-Qt schedulers
|
||||
#if defined(HAVE_QT)
|
||||
if (! s_inst) {
|
||||
new DeferredMethodSchedulerQt ();
|
||||
}
|
||||
#endif
|
||||
return s_inst;
|
||||
}
|
||||
|
||||
void
|
||||
DeferredMethodScheduler::schedule (DeferredMethodBase *method)
|
||||
{
|
||||
m_lock.lock ();
|
||||
tl::MutexLocker locker (&m_lock);
|
||||
if (! method->m_scheduled || ! method->m_compressed) {
|
||||
m_methods.push_back (method);
|
||||
if (! m_scheduled) {
|
||||
qApp->postEvent (this, new QEvent (QEvent::User));
|
||||
queue_event ();
|
||||
m_scheduled = true;
|
||||
}
|
||||
method->m_scheduled = true;
|
||||
}
|
||||
m_lock.unlock ();
|
||||
}
|
||||
|
||||
void
|
||||
DeferredMethodScheduler::unqueue (DeferredMethodBase *method)
|
||||
{
|
||||
m_lock.lock ();
|
||||
tl::MutexLocker locker (&m_lock);
|
||||
for (std::list<DeferredMethodBase *>::iterator m = m_methods.begin (); m != m_methods.end (); ) {
|
||||
std::list<DeferredMethodBase *>::iterator mm = m;
|
||||
++mm;
|
||||
|
|
@ -93,50 +85,18 @@ DeferredMethodScheduler::unqueue (DeferredMethodBase *method)
|
|||
}
|
||||
m = mm;
|
||||
}
|
||||
m_lock.unlock ();
|
||||
}
|
||||
|
||||
void
|
||||
DeferredMethodScheduler::do_enable (bool en)
|
||||
{
|
||||
m_lock.lock ();
|
||||
tl::MutexLocker locker (&m_lock);
|
||||
if (en) {
|
||||
tl_assert (m_disabled > 0);
|
||||
--m_disabled;
|
||||
} else {
|
||||
++m_disabled;
|
||||
}
|
||||
m_lock.unlock ();
|
||||
}
|
||||
|
||||
bool
|
||||
DeferredMethodScheduler::event (QEvent *event)
|
||||
{
|
||||
if (event->type () == QEvent::User) {
|
||||
timer ();
|
||||
return true;
|
||||
} else {
|
||||
return QObject::event (event);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DeferredMethodScheduler::timer ()
|
||||
{
|
||||
if (m_disabled) {
|
||||
// start again if disabled
|
||||
m_timer.start ();
|
||||
} else {
|
||||
try {
|
||||
do_execute ();
|
||||
} catch (tl::Exception &ex) {
|
||||
tl::error << tl::to_string (QObject::tr ("Exception caught: ")) << ex.msg ();
|
||||
} catch (std::exception &ex) {
|
||||
tl::error << tl::to_string (QObject::tr ("Exception caught: ")) << ex.what ();
|
||||
} catch (...) {
|
||||
tl::error << tl::to_string (QObject::tr ("Unspecific exception caught"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -23,16 +23,9 @@
|
|||
#ifndef HDR_tlDeferredExecution
|
||||
#define HDR_tlDeferredExecution
|
||||
|
||||
#if !defined(HAVE_QT)
|
||||
# error tl::DeferredExecution not available without Qt
|
||||
#endif
|
||||
|
||||
#include "tlCommon.h"
|
||||
#include "tlObject.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
#include <QMutex>
|
||||
#include "tlThreads.h"
|
||||
|
||||
#include <list>
|
||||
|
||||
|
|
@ -69,9 +62,7 @@ template <class T> class DeferredMethod;
|
|||
* @brief The deferred method scheduler
|
||||
*/
|
||||
class TL_PUBLIC DeferredMethodScheduler
|
||||
: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* @brief The singleton instance of the scheduler
|
||||
|
|
@ -117,29 +108,43 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
private slots:
|
||||
void timer ();
|
||||
/**
|
||||
* @brief Gets a value indicating whether the scheduler is disabled
|
||||
*/
|
||||
bool is_disabled () const
|
||||
{
|
||||
return m_disabled;
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Reimplementation of the interface: queue an event
|
||||
* In effect, the event should later trigger a call to do_execute ().
|
||||
*/
|
||||
virtual void queue_event () = 0;
|
||||
|
||||
/**
|
||||
* @brief Executes the pending methods
|
||||
*/
|
||||
void do_execute ();
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
DeferredMethodScheduler (QObject *parent);
|
||||
DeferredMethodScheduler ();
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~DeferredMethodScheduler ();
|
||||
virtual ~DeferredMethodScheduler ();
|
||||
|
||||
private:
|
||||
int m_disabled;
|
||||
bool m_scheduled;
|
||||
std::list<DeferredMethodBase *> m_methods;
|
||||
QTimer m_timer, m_fallback_timer;
|
||||
QMutex m_lock;
|
||||
tl::Mutex m_lock;
|
||||
|
||||
virtual bool event (QEvent *event);
|
||||
void do_enable (bool en);
|
||||
void do_execute ();
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -0,0 +1,87 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2018 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include "tlDeferredExecutionQt.h"
|
||||
#include "tlException.h"
|
||||
#include "tlLog.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
||||
namespace tl
|
||||
{
|
||||
|
||||
DeferredMethodSchedulerQt::DeferredMethodSchedulerQt ()
|
||||
: QObject (qApp), DeferredMethodScheduler ()
|
||||
{
|
||||
connect (&m_timer, SIGNAL (timeout ()), this, SLOT (timer ()));
|
||||
|
||||
m_timer.setInterval (0); // immediately
|
||||
m_timer.setSingleShot (true); // just once
|
||||
|
||||
// set up a fallback timer that cleans up pending execute jobs if something goes wrong
|
||||
connect (&m_fallback_timer, SIGNAL (timeout ()), this, SLOT (timer ()));
|
||||
m_fallback_timer.setInterval (500);
|
||||
m_fallback_timer.setSingleShot (false);
|
||||
}
|
||||
|
||||
DeferredMethodSchedulerQt::~DeferredMethodSchedulerQt ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void
|
||||
DeferredMethodSchedulerQt::queue_event ()
|
||||
{
|
||||
qApp->postEvent (this, new QEvent (QEvent::User));
|
||||
}
|
||||
|
||||
bool
|
||||
DeferredMethodSchedulerQt::event (QEvent *event)
|
||||
{
|
||||
if (event->type () == QEvent::User) {
|
||||
timer ();
|
||||
return true;
|
||||
} else {
|
||||
return QObject::event (event);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DeferredMethodSchedulerQt::timer ()
|
||||
{
|
||||
if (is_disabled ()) {
|
||||
// start again if disabled
|
||||
m_timer.start ();
|
||||
} else {
|
||||
try {
|
||||
do_execute ();
|
||||
} catch (tl::Exception &ex) {
|
||||
tl::error << tl::to_string (QObject::tr ("Exception caught: ")) << ex.msg ();
|
||||
} catch (std::exception &ex) {
|
||||
tl::error << tl::to_string (QObject::tr ("Exception caught: ")) << ex.what ();
|
||||
} catch (...) {
|
||||
tl::error << tl::to_string (QObject::tr ("Unspecific exception caught"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2018 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef HDR_tlDeferredExecutionQt
|
||||
#define HDR_tlDeferredExecutionQt
|
||||
|
||||
#include "tlCommon.h"
|
||||
#include "tlDeferredExecution.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
#include <QMutex>
|
||||
|
||||
#include <list>
|
||||
|
||||
namespace tl
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief The deferred method scheduler
|
||||
*/
|
||||
class TL_PUBLIC DeferredMethodSchedulerQt
|
||||
: public QObject, public DeferredMethodScheduler
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
DeferredMethodSchedulerQt ();
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~DeferredMethodSchedulerQt ();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Reimplementation of the interface: queue an event
|
||||
* In effect, the event should later trigger a call to do_execute ().
|
||||
*/
|
||||
void queue_event ();
|
||||
|
||||
private slots:
|
||||
void timer ();
|
||||
|
||||
private:
|
||||
QTimer m_timer, m_fallback_timer;
|
||||
|
||||
virtual bool event (QEvent *event);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -139,6 +139,15 @@ std::vector<std::string> split_path (const std::string &p, bool keep_last)
|
|||
}
|
||||
parts.push_back (tl::normalized_part (std::string (cp0, 0, cp - cp0)));
|
||||
|
||||
} else if ((*cp == '\\' || *cp == '/') && cp[1] && isalpha (cp[1]) && cp[2] == ':') {
|
||||
|
||||
// drive name in the form "/c:" or "\c:"
|
||||
parts.push_back (std::string ());
|
||||
parts.back () += toupper (cp[1]);
|
||||
parts.back () += ":";
|
||||
|
||||
cp += 3;
|
||||
|
||||
}
|
||||
|
||||
while (*cp) {
|
||||
|
|
@ -646,6 +655,18 @@ bool file_exists (const std::string &p)
|
|||
return stat_func (p, st) == 0;
|
||||
}
|
||||
|
||||
bool is_writable (const std::string &p)
|
||||
{
|
||||
stat_struct st;
|
||||
return stat_func (p, st) == 0 && (st.st_mode & S_IWUSR) != 0;
|
||||
}
|
||||
|
||||
bool is_readable (const std::string &p)
|
||||
{
|
||||
stat_struct st;
|
||||
return stat_func (p, st) == 0 && (st.st_mode & S_IRUSR) != 0;
|
||||
}
|
||||
|
||||
bool is_dir (const std::string &p)
|
||||
{
|
||||
stat_struct st;
|
||||
|
|
|
|||
|
|
@ -96,6 +96,16 @@ std::string TL_PUBLIC extension (const std::string &s);
|
|||
*/
|
||||
bool TL_PUBLIC file_exists (const std::string &s);
|
||||
|
||||
/**
|
||||
* @brief Returns true, if the given path is writable
|
||||
*/
|
||||
bool TL_PUBLIC is_writable (const std::string &s);
|
||||
|
||||
/**
|
||||
* @brief Returns true, if the given path is readable
|
||||
*/
|
||||
bool TL_PUBLIC is_readable (const std::string &s);
|
||||
|
||||
/**
|
||||
* @brief Returns true, if the given path is a directory
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -29,11 +29,8 @@
|
|||
#include "tlAssert.h"
|
||||
#include "tlStaticObjects.h"
|
||||
#include "tlProgress.h"
|
||||
#include "tlDeferredExecution.h"
|
||||
|
||||
#include <QUrl>
|
||||
#include <QFileInfo>
|
||||
#include <QCoreApplication>
|
||||
#include "tlFileUtils.h"
|
||||
#include "tlUri.h"
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
|
@ -58,8 +55,8 @@ namespace tl
|
|||
|
||||
std::string server_from_url (const std::string &url)
|
||||
{
|
||||
QUrl qurl (tl::to_qstring (url));
|
||||
return tl::to_string (qurl.scheme ()) + ":" + tl::to_string (qurl.host ());
|
||||
tl::URI uri (url);
|
||||
return uri.scheme () + "://" + uri.authority ();
|
||||
}
|
||||
|
||||
std::string parse_realm (const std::string &header)
|
||||
|
|
@ -750,7 +747,7 @@ void CurlConnection::check () const
|
|||
|
||||
} else if (m_status != 0) {
|
||||
|
||||
throw tl::HttpErrorException (tl::to_string (QObject::tr ("Connection error (%1)").arg (QString::fromLatin1 (m_error_msg))), m_status, m_url);
|
||||
throw tl::HttpErrorException (tl::sprintf (tl::to_string (tr ("Connection error (%s)")), m_error_msg), m_status, m_url);
|
||||
|
||||
} else if (m_http_status < 200 || m_http_status >= 300) {
|
||||
|
||||
|
|
@ -776,7 +773,7 @@ void CurlConnection::check () const
|
|||
if (error_text) {
|
||||
throw tl::HttpErrorException (error_text, m_http_status, m_url);
|
||||
} else {
|
||||
throw tl::HttpErrorException (tl::to_string (QObject::tr ("HTTP error")), m_http_status, m_url);
|
||||
throw tl::HttpErrorException (tl::to_string (tr ("HTTP error")), m_http_status, m_url);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1013,7 +1010,7 @@ int CurlNetworkManager::tick ()
|
|||
mc = curl_multi_fdset (mp_multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
|
||||
|
||||
if (mc != CURLM_OK) {
|
||||
throw tl::HttpErrorException (tl::to_string (QObject::tr ("Connection error (curl_multi_fdset() failed)")), mc, std::string ());
|
||||
throw tl::HttpErrorException (tl::to_string (tr ("Connection error (curl_multi_fdset() failed)")), mc, std::string ());
|
||||
}
|
||||
|
||||
/* On success the value of maxfd is guaranteed to be >= -1. We call
|
||||
|
|
@ -1170,7 +1167,7 @@ InputHttpStream::read (char *b, size_t n)
|
|||
tl::NoDeferredMethods silent;
|
||||
|
||||
if (! m_progress.get ()) {
|
||||
m_progress.reset (new tl::AbsoluteProgress (tl::to_string (QObject::tr ("Downloading")) + " " + m_connection->url (), 1));
|
||||
m_progress.reset (new tl::AbsoluteProgress (tl::to_string (tr ("Downloading")) + " " + m_connection->url (), 1));
|
||||
}
|
||||
|
||||
while (n > m_connection->read_available () && ! m_connection->finished () && CurlNetworkManager::instance ()->tick ()) {
|
||||
|
|
@ -1200,13 +1197,13 @@ InputHttpStream::close ()
|
|||
void
|
||||
InputHttpStream::reset ()
|
||||
{
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("'reset' is not supported on HTTP input streams")));
|
||||
throw tl::Exception (tl::to_string (tr ("'reset' is not supported on HTTP input streams")));
|
||||
}
|
||||
|
||||
std::string
|
||||
InputHttpStream::filename () const
|
||||
{
|
||||
return tl::to_string (QFileInfo (QUrl (tl::to_qstring (m_connection->url ())).path ()).fileName ());
|
||||
return tl::filename (tl::URI (m_connection->url ()).path ());
|
||||
}
|
||||
|
||||
std::string
|
||||
|
|
|
|||
|
|
@ -41,11 +41,7 @@
|
|||
|
||||
#include "tlException.h"
|
||||
#include "tlString.h"
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
# include <QUrl>
|
||||
# include <QFileInfo>
|
||||
#endif
|
||||
#include "tlUri.h"
|
||||
|
||||
namespace tl
|
||||
{
|
||||
|
|
@ -157,18 +153,13 @@ InputStream::InputStream (const std::string &abstract_path)
|
|||
mp_delegate = new InputHttpStream (abstract_path);
|
||||
} else
|
||||
#endif
|
||||
#if !defined (_WIN32) // not available on Windows
|
||||
if (ex.test ("pipe:")) {
|
||||
mp_delegate = new InputPipe (ex.get ());
|
||||
} else
|
||||
#endif
|
||||
#if defined(HAVE_QT)
|
||||
// TODO: provide a substitute for QUrl
|
||||
if (ex.test ("file:")) {
|
||||
QUrl url (tl::to_qstring (abstract_path));
|
||||
mp_delegate = new InputZLibFile (tl::to_string (url.toLocalFile ()));
|
||||
tl::URI uri (abstract_path);
|
||||
mp_delegate = new InputZLibFile (uri.path ());
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
mp_delegate = new InputZLibFile (abstract_path);
|
||||
}
|
||||
|
|
@ -183,16 +174,11 @@ std::string InputStream::absolute_path (const std::string &abstract_path)
|
|||
tl::Extractor ex (abstract_path.c_str ());
|
||||
if (ex.test ("http:") || ex.test ("https:")) {
|
||||
return abstract_path;
|
||||
#if !defined(_WIN32) // not available on Windows
|
||||
} else if (ex.test ("pipe:")) {
|
||||
return abstract_path;
|
||||
#endif
|
||||
#if defined(HAVE_QT)
|
||||
// TODO: provide a substitute for QUrl
|
||||
} else if (ex.test ("file:")) {
|
||||
QUrl url (tl::to_qstring (abstract_path));
|
||||
return tl::to_string (QFileInfo (url.toLocalFile ()).absoluteFilePath ());
|
||||
#endif
|
||||
tl::URI uri (abstract_path);
|
||||
return tl::absolute_path (uri.path ());
|
||||
} else {
|
||||
return tl::absolute_file_path (abstract_path);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,240 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2018 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "tlUri.h"
|
||||
#include "tlString.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
|
||||
namespace tl
|
||||
{
|
||||
|
||||
static bool is_hex (char c)
|
||||
{
|
||||
return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
|
||||
}
|
||||
|
||||
static char hex2int (char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9') {
|
||||
return c - '0';
|
||||
} else if (c >= 'A' && c <= 'F') {
|
||||
return (c - 'A') + 10;
|
||||
} else if (c >= 'a' || c <= 'f') {
|
||||
return (c - 'a') + 10;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static char int2hex (char c)
|
||||
{
|
||||
c &= 0xf;
|
||||
if (c < 10) {
|
||||
return c + '0';
|
||||
} else {
|
||||
return c - 10 + 'A';
|
||||
}
|
||||
}
|
||||
|
||||
static std::string unescape (const std::string &s)
|
||||
{
|
||||
std::string res;
|
||||
for (const char *cp = s.c_str (); *cp; ++cp) {
|
||||
if (*cp == '%' && is_hex (cp [1]) && is_hex (cp [2])) {
|
||||
res += hex2int (cp[1]) * 16 + hex2int (cp[2]);
|
||||
cp += 2;
|
||||
} else {
|
||||
res += *cp;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static std::string escape (const std::string &s)
|
||||
{
|
||||
const char *special = "?#[]$&'()*+,;";
|
||||
|
||||
std::string res;
|
||||
for (const char *cp = s.c_str (); *cp; ++cp) {
|
||||
if ((unsigned char) *cp <= 32 || (unsigned char) *cp >= 128 || strchr (special, *cp) != 0) {
|
||||
res += "%";
|
||||
res += int2hex (*cp >> 4);
|
||||
res += int2hex (*cp);
|
||||
} else {
|
||||
res += *cp;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
URI::URI ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
|
||||
URI::URI (const std::string &uri)
|
||||
{
|
||||
tl::Extractor ex0 (uri.c_str ());
|
||||
tl::Extractor ex = ex0;
|
||||
|
||||
if (ex.try_read_word (m_scheme) && *ex == ':') {
|
||||
// got scheme
|
||||
++ex;
|
||||
} else {
|
||||
m_scheme.clear ();
|
||||
ex = ex0;
|
||||
}
|
||||
m_scheme = unescape (m_scheme);
|
||||
|
||||
bool prefer_authority = true;
|
||||
if (m_scheme == "file") {
|
||||
prefer_authority = false;
|
||||
// other schemes?
|
||||
} else if (m_scheme.empty ()) {
|
||||
prefer_authority = false;
|
||||
}
|
||||
|
||||
ex0 = ex;
|
||||
if (ex.test ("//") || (ex.test ("/") ? prefer_authority : prefer_authority)) {
|
||||
// definitely an authority
|
||||
while (! ex.at_end () && *ex != '/') {
|
||||
m_authority += *ex;
|
||||
++ex;
|
||||
}
|
||||
} else {
|
||||
ex = ex0;
|
||||
}
|
||||
m_authority = unescape (m_authority);
|
||||
|
||||
// parse path
|
||||
while (! ex.at_end () && *ex != '?' && *ex != '#') {
|
||||
m_path += *ex;
|
||||
++ex;
|
||||
}
|
||||
m_path = unescape (m_path);
|
||||
|
||||
// parse parameters
|
||||
if (*ex == '?') {
|
||||
++ex;
|
||||
while (! ex.at_end () && *ex != '#') {
|
||||
std::string k, v;
|
||||
while (! ex.at_end () && *ex != '=' && *ex != '&' && *ex != '#') {
|
||||
k += *ex;
|
||||
++ex;
|
||||
}
|
||||
if (*ex == '=') {
|
||||
++ex;
|
||||
while (! ex.at_end () && *ex != '&' && *ex != '#') {
|
||||
v += *ex;
|
||||
++ex;
|
||||
}
|
||||
}
|
||||
m_query[unescape (k)] = unescape (v);
|
||||
if (*ex == '&') {
|
||||
++ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (*ex == '#') {
|
||||
++ex;
|
||||
while (! ex.at_end ()) {
|
||||
m_fragment += *ex;
|
||||
++ex;
|
||||
}
|
||||
}
|
||||
m_fragment = unescape (m_fragment);
|
||||
}
|
||||
|
||||
std::string
|
||||
URI::to_string () const
|
||||
{
|
||||
std::string res;
|
||||
|
||||
if (! m_scheme.empty ()) {
|
||||
res += escape (m_scheme);
|
||||
res += ":";
|
||||
}
|
||||
|
||||
if (! m_authority.empty ()) {
|
||||
res += "//";
|
||||
res += escape (m_authority);
|
||||
}
|
||||
|
||||
if (! m_path.empty ()) {
|
||||
res += escape (m_path);
|
||||
}
|
||||
|
||||
if (! m_query.empty ()) {
|
||||
for (std::map<std::string, std::string>::const_iterator p = m_query.begin (); p != m_query.end (); ++p) {
|
||||
res += (p == m_query.begin () ? "?" : "&");
|
||||
res += escape (p->first);
|
||||
if (! p->second.empty ()) {
|
||||
res += "=";
|
||||
res += escape (p->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! m_fragment.empty ()) {
|
||||
res += "#";
|
||||
res += m_fragment;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
URI
|
||||
URI::resolved (const URI &other) const
|
||||
{
|
||||
if (! other.scheme ().empty () && other.scheme () != scheme ()) {
|
||||
return other;
|
||||
}
|
||||
if (! other.authority ().empty () && other.authority () != authority ()) {
|
||||
return other;
|
||||
}
|
||||
|
||||
URI res = *this;
|
||||
|
||||
// combine paths
|
||||
// TODO: normalize? I.e. replace "x/y/../z" by "x/z"?
|
||||
if (! other.path ().empty ()) {
|
||||
if (other.path ()[0] == '/') {
|
||||
res.m_path = other.path ();
|
||||
} else {
|
||||
res.m_path += "/";
|
||||
res.m_path += other.path ();
|
||||
}
|
||||
}
|
||||
|
||||
res.m_query = other.query ();
|
||||
res.m_fragment = other.fragment ();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2018 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HDR_tlURI
|
||||
#define HDR_tlURI
|
||||
|
||||
#include "tlCommon.h"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
namespace tl
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief A class representing a URI
|
||||
*
|
||||
* This class is able to parse the URI and deliver the parts.
|
||||
*/
|
||||
|
||||
class TL_PUBLIC URI
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Creates an empty URI
|
||||
*/
|
||||
URI ();
|
||||
|
||||
/**
|
||||
* @brief Creates an URI from the given string
|
||||
*/
|
||||
URI (const std::string &uri);
|
||||
|
||||
/**
|
||||
* @brief Returns the scheme part or an empty string if there is no scheme
|
||||
*/
|
||||
const std::string &scheme () const
|
||||
{
|
||||
return m_scheme;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the authority part or an empty string if there is no authority
|
||||
* The leading slashes and not part of the authority.
|
||||
* Percent escaping is undone already.
|
||||
*/
|
||||
const std::string &authority () const
|
||||
{
|
||||
return m_authority;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the path part or an empty string if there is no path
|
||||
* The path contains the leading slash if there is a path.
|
||||
* Percent escaping is undone already.
|
||||
*/
|
||||
const std::string &path () const
|
||||
{
|
||||
return m_path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the query part or an empty map if there is no query
|
||||
* The map is a map of keys vs. values. Percent escaping is undone
|
||||
* in the keys and values.
|
||||
*/
|
||||
const std::map<std::string, std::string> &query () const
|
||||
{
|
||||
return m_query;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the fragment or an empty string if there is none
|
||||
* Percent escaping is undone on the fragment already.
|
||||
*/
|
||||
const std::string &fragment () const
|
||||
{
|
||||
return m_fragment;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Turns the URI into a string
|
||||
* Percent escaping is employed to escape special characters
|
||||
*/
|
||||
std::string to_string () const;
|
||||
|
||||
/**
|
||||
* @brief Resolves an URI relative to this one
|
||||
*/
|
||||
URI resolved (const URI &other) const;
|
||||
|
||||
private:
|
||||
std::string m_scheme;
|
||||
std::string m_authority;
|
||||
std::string m_path;
|
||||
std::map<std::string, std::string> m_query;
|
||||
std::string m_fragment;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -28,10 +28,10 @@
|
|||
#include "tlInternational.h"
|
||||
#include "tlProgress.h"
|
||||
#include "tlLog.h"
|
||||
#include "tlUri.h"
|
||||
#include "tlFileUtils.h"
|
||||
|
||||
#include <memory>
|
||||
#include <QUrl>
|
||||
#include <QDir>
|
||||
|
||||
namespace tl
|
||||
{
|
||||
|
|
@ -125,15 +125,15 @@ tl::XMLStruct<MultiStatus> xml_struct ("multistatus",
|
|||
)
|
||||
);
|
||||
|
||||
static std::string item_name (const QString &path1, const QString &path2)
|
||||
static std::string item_name (const std::string &path1, const std::string &path2)
|
||||
{
|
||||
QStringList sl1 = path1.split (QChar ('/'));
|
||||
if (! sl1.empty () && sl1.back ().isEmpty ()) {
|
||||
std::vector <std::string> sl1 = tl::split (path1, "/");
|
||||
if (! sl1.empty () && sl1.back ().empty ()) {
|
||||
sl1.pop_back ();
|
||||
}
|
||||
|
||||
QStringList sl2 = path2.split (QChar ('/'));
|
||||
if (! sl2.empty () && sl2.back ().isEmpty ()) {
|
||||
std::vector <std::string> sl2 = tl::split (path2, "/");
|
||||
if (! sl2.empty () && sl2.back ().empty ()) {
|
||||
sl2.pop_back ();
|
||||
}
|
||||
|
||||
|
|
@ -141,16 +141,16 @@ static std::string item_name (const QString &path1, const QString &path2)
|
|||
// This is the top-level item (echoed in the PROPFIND response)
|
||||
return std::string ();
|
||||
} else if (! sl2.empty ()) {
|
||||
return tl::to_string (sl2.back ());
|
||||
return sl2.back ();
|
||||
} else {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Invalid WebDAV response: %1 is not a collection sub-item of %2").arg (path2).arg (path1)));
|
||||
throw tl::Exception (tl::to_string (tr ("Invalid WebDAV response: %s is not a collection sub-item of %s")), path2, path1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebDAVObject::read (const std::string &url, int depth)
|
||||
{
|
||||
QUrl base_url = QUrl (tl::to_qstring (url));
|
||||
tl::URI base_uri (url);
|
||||
|
||||
tl::InputHttpStream http (url);
|
||||
http.add_header ("User-Agent", "SVN");
|
||||
|
|
@ -169,10 +169,10 @@ WebDAVObject::read (const std::string &url, int depth)
|
|||
for (MultiStatus::iterator r = multistatus.begin (); r != multistatus.end (); ++r) {
|
||||
|
||||
bool is_collection = r->propstat.prop.resourcetype.is_collection;
|
||||
QUrl item_url = base_url.resolved (QUrl (tl::to_qstring (r->href)));
|
||||
tl::URI item_url = base_uri.resolved (tl::URI (r->href));
|
||||
|
||||
std::string n = item_name (base_url.path (), item_url.path ());
|
||||
std::string item_url_string = tl::to_string (item_url.toString ());
|
||||
std::string n = item_name (base_uri.path (), item_url.path ());
|
||||
std::string item_url_string = item_url.to_string ();
|
||||
|
||||
if (! n.empty ()) {
|
||||
m_items.push_back (WebDAVItem (is_collection, item_url_string, n));
|
||||
|
|
@ -211,36 +211,35 @@ void fetch_download_items (const std::string &url, const std::string &target, st
|
|||
|
||||
if (object.is_collection ()) {
|
||||
|
||||
QDir dir (tl::to_qstring (target));
|
||||
if (! dir.exists ()) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Download failed: target directory '%1' does not exists").arg (dir.path ())));
|
||||
if (! tl::file_exists (target)) {
|
||||
throw tl::Exception (tl::to_string (tr ("Download failed: target directory '%s' does not exists")), target);
|
||||
}
|
||||
|
||||
for (WebDAVObject::iterator i = object.begin (); i != object.end (); ++i) {
|
||||
|
||||
QFileInfo new_item (dir.absoluteFilePath (tl::to_qstring (i->name ())));
|
||||
std::string item_path = tl::absolute_file_path (tl::combine_path (target, i->name ()));
|
||||
|
||||
if (i->is_collection ()) {
|
||||
|
||||
if (! new_item.exists ()) {
|
||||
if (! dir.mkdir (tl::to_qstring (i->name ()))) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Download failed: unable to create subdirectory '%2' in '%1'").arg (dir.path ()).arg (tl::to_qstring (i->name ()))));
|
||||
if (! tl::file_exists (item_path)) {
|
||||
if (! tl::mkpath (item_path)) {
|
||||
throw tl::Exception (tl::to_string (tr ("Download failed: unable to create subdirectory '%s' in '%s'")), i->name (), target);
|
||||
}
|
||||
} else if (! new_item.isDir ()) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Download failed: unable to create subdirectory '%2' in '%1' - is already a file").arg (dir.path ()).arg (tl::to_qstring (i->name ()))));
|
||||
} else if (! new_item.isWritable ()) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Download failed: unable to create subdirectory '%2' in '%1' - no write permissions").arg (dir.path ()).arg (tl::to_qstring (i->name ()))));
|
||||
} else if (! tl::is_dir (item_path)) {
|
||||
throw tl::Exception (tl::to_string (tr ("Download failed: unable to create subdirectory '%s' in '%s' - is already a file")), i->name (), target);
|
||||
} else if (! tl::is_writable (item_path)) {
|
||||
throw tl::Exception (tl::to_string (tr ("Download failed: unable to create subdirectory '%s' in '%s' - no write permissions")), i->name (), target);
|
||||
}
|
||||
|
||||
fetch_download_items (i->url (), tl::to_string (new_item.filePath ()), items, progress);
|
||||
fetch_download_items (i->url (), item_path, items, progress);
|
||||
|
||||
} else {
|
||||
|
||||
if (new_item.exists () && ! new_item.isWritable ()) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Download failed: file is '%2' in '%1' - already exists, but no write permissions").arg (dir.path ()).arg (tl::to_qstring (i->name ()))));
|
||||
if (tl::file_exists (item_path) && ! tl::is_writable (item_path)) {
|
||||
throw tl::Exception (tl::to_string (tr ("Download failed: file is '%s' in '%s' - already exists, but no write permissions")), i->name (), target);
|
||||
}
|
||||
|
||||
items.push_back (DownloadItem (i->url (), tl::to_string (dir.absoluteFilePath (tl::to_qstring (i->name ())))));
|
||||
items.push_back (DownloadItem (i->url (), item_path));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -266,25 +265,25 @@ WebDAVObject::download (const std::string &url, const std::string &target)
|
|||
|
||||
try {
|
||||
|
||||
tl::info << QObject::tr ("Fetching file structure from ") << url;
|
||||
tl::AbsoluteProgress progress (tl::to_string (QObject::tr ("Fetching directory structure from %1").arg (tl::to_qstring (url))));
|
||||
tl::info << tr ("Fetching file structure from ") << url;
|
||||
tl::AbsoluteProgress progress (tl::sprintf (tl::to_string (tr ("Fetching directory structure from %s")), url));
|
||||
fetch_download_items (url, target, items, progress);
|
||||
|
||||
} catch (tl::Exception &ex) {
|
||||
tl::error << QObject::tr ("Error downloading file structure from '") << url << "':" << tl::endl << ex.msg ();
|
||||
tl::error << tr ("Error downloading file structure from '") << url << "':" << tl::endl << ex.msg ();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool has_errors = false;
|
||||
|
||||
{
|
||||
tl::info << tl::to_string (QObject::tr ("Downloading %1 file(s) now ..").arg (items.size ()));
|
||||
tl::info << tl::sprintf (tl::to_string (tr ("Downloading %d file(s) now ..")), items.size ());
|
||||
|
||||
tl::RelativeProgress progress (tl::to_string (QObject::tr ("Downloading file(s) from %1").arg (tl::to_qstring (url))), items.size (), 1);
|
||||
tl::RelativeProgress progress (tl::sprintf (tl::to_string (tr ("Downloading file(s) from %s")), url), items.size (), 1);
|
||||
|
||||
for (std::list<DownloadItem>::const_iterator i = items.begin (); i != items.end (); ++i) {
|
||||
|
||||
tl::info << QObject::tr ("Downloading '%1' to '%2' ..").arg (tl::to_qstring (i->url)).arg (tl::to_qstring (i->path));
|
||||
tl::info << tl::sprintf (tr ("Downloading '%s' to '%s' .."), i->url, i->path);
|
||||
|
||||
try {
|
||||
|
||||
|
|
@ -293,7 +292,7 @@ WebDAVObject::download (const std::string &url, const std::string &target)
|
|||
is->copy_to (os);
|
||||
|
||||
} catch (tl::Exception &ex) {
|
||||
tl::error << QObject::tr ("Error downloading file from '") << i->url << "':" << tl::endl << ex.msg ();
|
||||
tl::error << tr ("Error downloading file from '") << i->url << "':" << tl::endl << ex.msg ();
|
||||
has_errors = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -215,6 +215,16 @@ void XMLCALL start_element_handler (void *user_data, const XML_Char *name, const
|
|||
void XMLCALL end_element_handler (void *user_data, const XML_Char *name);
|
||||
void XMLCALL cdata_handler (void *user_data, const XML_Char *s, int len);
|
||||
|
||||
static std::string get_lname (const std::string &name)
|
||||
{
|
||||
size_t colon = name.find (':');
|
||||
if (colon != std::string::npos) {
|
||||
return std::string (name, colon + 1, name.size () - colon - 1);
|
||||
} else {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
class XMLParserPrivateData
|
||||
{
|
||||
public:
|
||||
|
|
@ -235,8 +245,8 @@ public:
|
|||
void start_element (const std::string &name)
|
||||
{
|
||||
try {
|
||||
// TODO: separate qname and lname?
|
||||
mp_struct_handler->start_element (std::string (), name, name);
|
||||
// TODO: Provide namespace URI?
|
||||
mp_struct_handler->start_element (std::string (), get_lname (name), name);
|
||||
} catch (tl::Exception &ex) {
|
||||
error (ex);
|
||||
}
|
||||
|
|
@ -245,8 +255,8 @@ public:
|
|||
void end_element (const std::string &name)
|
||||
{
|
||||
try {
|
||||
// TODO: separate qname and lname?
|
||||
mp_struct_handler->end_element (std::string (), name, name);
|
||||
// TODO: Provide namespace URI?
|
||||
mp_struct_handler->end_element (std::string (), get_lname (name), name);
|
||||
} catch (tl::Exception &ex) {
|
||||
error (ex);
|
||||
}
|
||||
|
|
@ -861,6 +871,10 @@ XMLStructureHandler::start_element (const std::string &uri, const std::string &l
|
|||
void
|
||||
XMLStructureHandler::end_element (const std::string &uri, const std::string &lname, const std::string &qname)
|
||||
{
|
||||
if (m_stack.empty ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const XMLElementBase *element = m_stack.back ();
|
||||
m_stack.pop_back ();
|
||||
|
||||
|
|
@ -876,7 +890,7 @@ XMLStructureHandler::end_element (const std::string &uri, const std::string &lna
|
|||
void
|
||||
XMLStructureHandler::characters (const std::string &t)
|
||||
{
|
||||
if (m_stack.back ()) {
|
||||
if (! m_stack.empty () && m_stack.back ()) {
|
||||
m_stack.back ()->cdata (t, *mp_state);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,6 +168,8 @@ TEST (3)
|
|||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Secret mode switchers for testing
|
||||
namespace tl
|
||||
{
|
||||
|
|
@ -225,6 +227,8 @@ TEST (10)
|
|||
EXPECT_EQ (tl::normalize_path ("\\"), "\\");
|
||||
EXPECT_EQ (tl::normalize_path ("/"), "\\");
|
||||
EXPECT_EQ (tl::normalize_path ("d:"), "D:");
|
||||
EXPECT_EQ (tl::normalize_path ("/d:"), "D:");
|
||||
EXPECT_EQ (tl::normalize_path ("\\d:"), "D:");
|
||||
EXPECT_EQ (tl::normalize_path ("\\\\"), "\\\\");
|
||||
EXPECT_EQ (tl::normalize_path ("//"), "\\\\");
|
||||
EXPECT_EQ (tl::normalize_path ("d:\\"), "D:\\");
|
||||
|
|
@ -370,8 +374,12 @@ TEST(13)
|
|||
tl::rm_dir_recursive (tt);
|
||||
|
||||
EXPECT_EQ (tl::file_exists (tt), false);
|
||||
EXPECT_EQ (tl::is_readable (tt), false);
|
||||
EXPECT_EQ (tl::is_writable (tt), false);
|
||||
EXPECT_EQ (tl::mkpath (tt), true);
|
||||
EXPECT_EQ (tl::file_exists (tt), true);
|
||||
EXPECT_EQ (tl::is_readable (tt), true);
|
||||
EXPECT_EQ (tl::is_writable (tt), true);
|
||||
tl::rm_dir_recursive (tt);
|
||||
|
||||
EXPECT_EQ (tl::file_exists (tt), false);
|
||||
|
|
@ -393,6 +401,8 @@ TEST(13)
|
|||
EXPECT_EQ (tl::file_exists (tt), false);
|
||||
}
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
|
||||
// absolute_path, relative_path and absolute_file_path
|
||||
TEST(14)
|
||||
{
|
||||
|
|
@ -412,6 +422,8 @@ TEST(14)
|
|||
EXPECT_EQ (tl::relative_path (xpath2, tl::combine_path (xpath, "a")), "doesnotexist/a");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// dir_entries
|
||||
TEST(15)
|
||||
{
|
||||
|
|
@ -497,4 +509,3 @@ TEST(15)
|
|||
EXPECT_EQ (tl::rm_dir (tt), false); // not empty
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,144 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2018 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include "tlUri.h"
|
||||
#include "tlUnitTest.h"
|
||||
|
||||
std::string uri2string (const tl::URI &uri)
|
||||
{
|
||||
std::string res;
|
||||
|
||||
if (! uri.scheme ().empty ()) {
|
||||
res += "<" + uri.scheme () + ">";
|
||||
res += ":";
|
||||
}
|
||||
|
||||
if (! uri.authority ().empty ()) {
|
||||
res += "//<";
|
||||
res += uri.authority ();
|
||||
res += ">";
|
||||
}
|
||||
|
||||
if (! uri.path ().empty ()) {
|
||||
res += "<" + uri.path () + ">";
|
||||
}
|
||||
|
||||
if (! uri.query ().empty ()) {
|
||||
for (std::map<std::string, std::string>::const_iterator p = uri.query ().begin (); p != uri.query ().end (); ++p) {
|
||||
res += (p == uri.query ().begin () ? "?<" : "&<");
|
||||
res += p->first;
|
||||
res += ">";
|
||||
if (! p->second.empty ()) {
|
||||
res += "=<";
|
||||
res += p->second;
|
||||
res += ">";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! uri.fragment ().empty ()) {
|
||||
res += "#<";
|
||||
res += uri.fragment ();
|
||||
res += ">";
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// basic parsing ability
|
||||
TEST(1)
|
||||
{
|
||||
tl::URI uri;
|
||||
EXPECT_EQ (uri2string (uri), "");
|
||||
|
||||
uri = tl::URI ("scheme:");
|
||||
EXPECT_EQ (uri2string (uri), "<scheme>:");
|
||||
|
||||
uri = tl::URI ("http:www.klayout.de/path/to/file");
|
||||
EXPECT_EQ (uri2string (uri), "<http>://<www.klayout.de></path/to/file>");
|
||||
|
||||
uri = tl::URI ("http:/www.klayout.de/path/to/file");
|
||||
EXPECT_EQ (uri2string (uri), "<http>://<www.klayout.de></path/to/file>");
|
||||
|
||||
uri = tl::URI ("http://www.klayout.de/path/to/file");
|
||||
EXPECT_EQ (uri2string (uri), "<http>://<www.klayout.de></path/to/file>");
|
||||
EXPECT_EQ (uri.to_string (), "http://www.klayout.de/path/to/file");
|
||||
|
||||
uri = tl::URI ("www.klayout.de/path/to/file");
|
||||
EXPECT_EQ (uri2string (uri), "<www.klayout.de/path/to/file>");
|
||||
|
||||
uri = tl::URI ("/www.klayout.de/path/to/file");
|
||||
EXPECT_EQ (uri2string (uri), "</www.klayout.de/path/to/file>");
|
||||
|
||||
uri = tl::URI ("//www.klayout.de/path/to/file");
|
||||
EXPECT_EQ (uri2string (uri), "//<www.klayout.de></path/to/file>");
|
||||
EXPECT_EQ (uri.to_string (), "//www.klayout.de/path/to/file");
|
||||
|
||||
uri = tl::URI ("file:www.klayout.de/path/to/file");
|
||||
EXPECT_EQ (uri2string (uri), "<file>:<www.klayout.de/path/to/file>");
|
||||
|
||||
uri = tl::URI ("file:/www.klayout.de/path/to/file");
|
||||
EXPECT_EQ (uri2string (uri), "<file>:</www.klayout.de/path/to/file>");
|
||||
|
||||
uri = tl::URI ("file://www.klayout.de/path/to/file");
|
||||
EXPECT_EQ (uri2string (uri), "<file>://<www.klayout.de></path/to/file>");
|
||||
|
||||
uri = tl::URI ("file:///path/to/file");
|
||||
EXPECT_EQ (uri2string (uri), "<file>:</path/to/file>");
|
||||
|
||||
uri = tl::URI ("file:///c:/path/to/file");
|
||||
EXPECT_EQ (uri2string (uri), "<file>:</c:/path/to/file>");
|
||||
EXPECT_EQ (uri2string (uri.resolved (tl::URI ("http://www.klayout.de"))), "<http>://<www.klayout.de>");
|
||||
EXPECT_EQ (uri2string (uri.resolved (tl::URI ("http:///other"))), "<http>:</other>");
|
||||
EXPECT_EQ (uri2string (uri.resolved (tl::URI ("../other"))), "<file>:</c:/path/to/file/../other>");
|
||||
EXPECT_EQ (uri2string (uri.resolved (tl::URI ("/other"))), "<file>:</other>");
|
||||
EXPECT_EQ (uri2string (uri.resolved (tl::URI ("file:../other"))), "<file>:</c:/path/to/file/../other>");
|
||||
EXPECT_EQ (uri2string (uri.resolved (tl::URI ("file:../other?a=b#frag"))), "<file>:</c:/path/to/file/../other>?<a>=<b>#<frag>");
|
||||
EXPECT_EQ (uri2string (uri.resolved (tl::URI ("file:/other"))), "<file>:</other>");
|
||||
EXPECT_EQ (uri2string (uri.resolved (tl::URI ("file:/other?a=b#frag"))), "<file>:</other>?<a>=<b>#<frag>");
|
||||
|
||||
uri = tl::URI ("//www.klayout.de/path/to/file?a=b");
|
||||
EXPECT_EQ (uri2string (uri), "//<www.klayout.de></path/to/file>?<a>=<b>");
|
||||
|
||||
uri = tl::URI ("/path/to/file?a=b");
|
||||
EXPECT_EQ (uri2string (uri), "</path/to/file>?<a>=<b>");
|
||||
|
||||
uri = tl::URI ("/path/to/file?a=v1&c=v3&b=v2");
|
||||
EXPECT_EQ (uri2string (uri), "</path/to/file>?<a>=<v1>&<b>=<v2>&<c>=<v3>");
|
||||
|
||||
uri = tl::URI ("/path/to/file?a=v1&c=v3&b=v2#fragment");
|
||||
EXPECT_EQ (uri2string (uri), "</path/to/file>?<a>=<v1>&<b>=<v2>&<c>=<v3>#<fragment>");
|
||||
EXPECT_EQ (uri.to_string (), "/path/to/file?a=v1&b=v2&c=v3#fragment");
|
||||
|
||||
uri = tl::URI ("/path/to/file#fragment");
|
||||
EXPECT_EQ (uri2string (uri), "</path/to/file>#<fragment>");
|
||||
EXPECT_EQ (uri.to_string (), "/path/to/file#fragment");
|
||||
|
||||
uri = tl::URI ("/path/to/%2c%2C%20%file#fragment");
|
||||
EXPECT_EQ (uri2string (uri), "</path/to/,, %file>#<fragment>");
|
||||
EXPECT_EQ (uri.to_string (), "/path/to/%2C%2C%20%file#fragment");
|
||||
EXPECT_EQ (tl::URI (uri.to_string ()).to_string (), "/path/to/%2C%2C%20%file#fragment");
|
||||
|
||||
uri = tl::URI ("/path/to/file?%61=v%31&%63=v%33&%62=v%32#fragment");
|
||||
EXPECT_EQ (uri2string (uri), "</path/to/file>?<a>=<v1>&<b>=<v2>&<c>=<v3>#<fragment>");
|
||||
EXPECT_EQ (uri2string (uri.resolved (tl::URI ("../other"))), "</path/to/file/../other>");
|
||||
}
|
||||
|
|
@ -23,8 +23,7 @@
|
|||
|
||||
#include "tlWebDAV.h"
|
||||
#include "tlUnitTest.h"
|
||||
|
||||
#include <QDir>
|
||||
#include "tlFileUtils.h"
|
||||
|
||||
static std::string test_url1 ("http://www.klayout.org/svn-public/klayout-resources/trunk/testdata");
|
||||
static std::string test_url2 ("http://www.klayout.org/svn-public/klayout-resources/trunk/testdata/text");
|
||||
|
|
@ -96,34 +95,29 @@ TEST(5)
|
|||
{
|
||||
tl::WebDAVObject collection;
|
||||
|
||||
QDir tmp_dir (tl::to_qstring (tmp_file ("tmp")));
|
||||
EXPECT_EQ (tmp_dir.exists (), false);
|
||||
std::string tmp_dir (tmp_file ("tmp"));
|
||||
EXPECT_EQ (tl::file_exists (tmp_dir), false);
|
||||
|
||||
tmp_dir.cdUp ();
|
||||
tmp_dir.mkdir (tl::to_qstring ("tmp"));
|
||||
tmp_dir.cd (tl::to_qstring ("tmp"));
|
||||
tl::mkpath (tmp_dir);
|
||||
EXPECT_EQ (tl::file_exists (tmp_dir), true);
|
||||
|
||||
bool res = collection.download (test_url1, tl::to_string (tmp_dir.absolutePath ()));
|
||||
bool res = collection.download (test_url1, tl::absolute_file_path (tmp_dir));
|
||||
EXPECT_EQ (res, true);
|
||||
|
||||
QDir dir1 (tmp_dir.absoluteFilePath (QString::fromUtf8 ("dir1")));
|
||||
QDir dir2 (tmp_dir.absoluteFilePath (QString::fromUtf8 ("dir2")));
|
||||
QDir dir21 (dir2.absoluteFilePath (QString::fromUtf8 ("dir21")));
|
||||
EXPECT_EQ (dir1.exists (), true);
|
||||
EXPECT_EQ (dir2.exists (), true);
|
||||
EXPECT_EQ (dir21.exists (), true);
|
||||
std::string dir1 (tl::absolute_file_path (tl::combine_path (tmp_dir, "dir1")));
|
||||
std::string dir2 (tl::absolute_file_path (tl::combine_path (tmp_dir, "dir2")));
|
||||
std::string dir21 (tl::absolute_file_path (tl::combine_path (dir2, "dir21")));
|
||||
EXPECT_EQ (tl::file_exists (dir1), true);
|
||||
EXPECT_EQ (tl::file_exists (dir2), true);
|
||||
EXPECT_EQ (tl::file_exists (dir21), true);
|
||||
|
||||
QByteArray ba;
|
||||
|
||||
QFile text1 (dir1.absoluteFilePath (QString::fromUtf8 ("text")));
|
||||
text1.open (QIODevice::ReadOnly);
|
||||
ba = text1.read (10000);
|
||||
EXPECT_EQ (ba.constData (), "A text.\n");
|
||||
tl::InputStream text1 (tl::combine_path (dir1, "text"));
|
||||
std::string ba1 = text1.read_all ();
|
||||
EXPECT_EQ (ba1, "A text.\n");
|
||||
text1.close ();
|
||||
|
||||
QFile text21 (dir21.absoluteFilePath (QString::fromUtf8 ("text")));
|
||||
text21.open (QIODevice::ReadOnly);
|
||||
ba = text21.read (10000);
|
||||
EXPECT_EQ (ba.constData (), "A text II.I.\n");
|
||||
tl::InputStream text21 (tl::combine_path (dir21, "text"));
|
||||
std::string ba21 = text21.read_all ();
|
||||
EXPECT_EQ (ba21, "A text II.I.\n");
|
||||
text21.close ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -195,7 +195,7 @@ TEST (5)
|
|||
#if defined (HAVE_QT)
|
||||
EXPECT_EQ (error, "XML parser error: tag mismatch in line 2, column 33");
|
||||
#else
|
||||
EXPECT_EQ (error, "XML parser error: mismatched tag in line 2, column 29");
|
||||
EXPECT_EQ (error, "XML parser error: mismatched tag in line 2, column 28");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,13 +30,14 @@ SOURCES = \
|
|||
tlVariant.cc \
|
||||
tlInt128Support.cc \
|
||||
tlXMLParser.cc \
|
||||
tlUri.cc \
|
||||
tlWebDAV.cc \
|
||||
|
||||
equals(HAVE_QT, "0") {
|
||||
# nothing
|
||||
} else {
|
||||
|
||||
SOURCES += \
|
||||
tlWebDAV.cc \
|
||||
tlDeferredExecution.cc \
|
||||
tlFileSystemWatcher.cc \
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue