mirror of https://github.com/KLayout/klayout.git
Non-Qt implementations of file utils - needs testing.
This commit is contained in:
parent
239b7ca3ff
commit
7fca6f5f31
|
|
@ -21,6 +21,7 @@
|
|||
*/
|
||||
|
||||
#include "tlFileUtils.h"
|
||||
#include "tlStream.h"
|
||||
#include "tlLog.h"
|
||||
#include "tlInternational.h"
|
||||
|
||||
|
|
@ -28,6 +29,7 @@
|
|||
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
|
||||
namespace tl
|
||||
{
|
||||
|
|
@ -191,35 +193,140 @@ is_parent_path (const std::string &parent, const std::string &path)
|
|||
return (is_same_file (parent, tl::combine_path (tl::join (parts, ""), "")));
|
||||
}
|
||||
|
||||
bool rm_dir_recursive (const std::string &path)
|
||||
std::vector<std::string> dir_entries (const std::string &s, bool with_files, bool with_dirs, bool without_dotfiles)
|
||||
{
|
||||
#if 0 // @@@
|
||||
QDir dir (path);
|
||||
std::vector<std::string> ee;
|
||||
|
||||
QStringList entries = dir.entryList (QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs);
|
||||
for (QStringList::const_iterator e = entries.begin (); e != entries.end (); ++e) {
|
||||
QFileInfo fi (dir.absoluteFilePath (*e));
|
||||
if (fi.isDir ()) {
|
||||
if (! rm_dir_recursive (fi.filePath ())) {
|
||||
return false;
|
||||
#if defined(_WIN32)
|
||||
|
||||
struct _wfinddata_t fileinfo;
|
||||
|
||||
intptr_t h = _wfindfirst (tl::to_wstring (s + "\\*.*").c_str (), &fileinfo);
|
||||
if (h != -1) {
|
||||
|
||||
do {
|
||||
|
||||
std::string e = tl::to_string fileinfo.name);
|
||||
if (e.empty () || e == "." || e == "..") {
|
||||
continue;
|
||||
}
|
||||
} else if (fi.isFile ()) {
|
||||
if (! dir.remove (*e)) {
|
||||
tl::error << tr ("Unable to remove file: %1").arg (dir.absoluteFilePath (*e));
|
||||
|
||||
bool is_dir = ((fileinfo.attrib & _A_SUBDIR) != 0);
|
||||
if ((e[0] != '.' || !without_dotfiles) && ((is_dir && with_dirs) || (!is_dir && with_files))) {
|
||||
ee.push_back (e);
|
||||
}
|
||||
|
||||
} while (_wfindnext (h, &fileinfo) == 0);
|
||||
|
||||
}
|
||||
|
||||
_wfindclose (h);
|
||||
|
||||
#else
|
||||
|
||||
DIR *h = opendir (tl::to_local (s).c_str ());
|
||||
if (h) {
|
||||
|
||||
struct dirent *d;
|
||||
while ((d = readdir (h)) != NULL) {
|
||||
|
||||
std::string e = tl::to_string_from_local (d->d_name);
|
||||
if (e.empty () || e == "." || e == "..") {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool is_dir = (d->d_type == DT_DIR);
|
||||
if ((e[0] != '.' || !without_dotfiles) && ((is_dir && with_dirs) || (!is_dir && with_files))) {
|
||||
ee.push_back (e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
closedir (h);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return ee;
|
||||
}
|
||||
|
||||
bool mkdir (const std::string &path)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
return _wunlink (tl::to_wstring (path).c_str ()) == 0;
|
||||
#else
|
||||
return unlink (tl::to_local (path).c_str ()) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool mkpath (const std::string &p)
|
||||
{
|
||||
std::vector<std::string> parts = split_path (absolute_file_path (p));
|
||||
|
||||
size_t i = 0;
|
||||
std::string front;
|
||||
if (! parts.empty () && is_drive (parts.front ())) {
|
||||
front = parts.front ();
|
||||
++i;
|
||||
}
|
||||
|
||||
while (i < parts.size ()) {
|
||||
front += parts[i++];
|
||||
if (! file_exists (front)) {
|
||||
if (! mkdir (front)) {
|
||||
tl::error << tr ("Unable to create directory: ") << front;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString name = dir.dirName ();
|
||||
if (dir.cdUp ()) {
|
||||
if (! dir.rmdir (name)) {
|
||||
tl::error << tr ("Unable to remove directory: %1").arg (dir.absoluteFilePath (name));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool rm_file (const std::string &path)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
return _wunlink (tl::to_wstring (path).c_str ()) == 0;
|
||||
#else
|
||||
return unlink (tl::to_local (path).c_str ()) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool rm_dir (const std::string &path)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
return _wrmdir (tl::to_wstring (path).c_str ()) == 0;
|
||||
#else
|
||||
return rmdir (tl::to_local (path).c_str ()) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool rm_dir_recursive (const std::string &p)
|
||||
{
|
||||
std::vector<std::string> entries;
|
||||
std::string path = tl::absolute_file_path (p);
|
||||
|
||||
entries = dir_entries (path, false /*without_files*/, true /*with_dirs*/);
|
||||
for (std::vector<std::string>::const_iterator e = entries.begin (); e != entries.end (); ++e) {
|
||||
if (! rm_dir_recursive (tl::combine_path (path, *e))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
entries = dir_entries (path, true /*with_files*/, false /*without_dirs*/);
|
||||
for (std::vector<std::string>::const_iterator e = entries.begin (); e != entries.end (); ++e) {
|
||||
std::string tc = tl::combine_path (path, *e);
|
||||
if (! rm_file (tc)) {
|
||||
tl::error << tr ("Unable to remove file: ") << tc;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (! rm_dir (path)) {
|
||||
tl::error << tr ("Unable to remove directory: ") << path;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -227,72 +334,47 @@ bool rm_dir_recursive (const std::string &path)
|
|||
bool
|
||||
cp_dir_recursive (const std::string &source, const std::string &target)
|
||||
{
|
||||
#if 0 // @@@
|
||||
QDir dir (source);
|
||||
QDir dir_target (target);
|
||||
std::vector<std::string> entries;
|
||||
std::string path = tl::absolute_file_path (source);
|
||||
std::string path_to = tl::absolute_file_path (target);
|
||||
|
||||
QStringList entries = dir.entryList (QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs);
|
||||
for (QStringList::const_iterator e = entries.begin (); e != entries.end (); ++e) {
|
||||
entries = dir_entries (path, false /*without_files*/, true /*with_dirs*/);
|
||||
for (std::vector<std::string>::const_iterator e = entries.begin (); e != entries.end (); ++e) {
|
||||
std::string tc = tl::combine_path (path_to, *e);
|
||||
if (! mkpath (tc)) {
|
||||
tl::error << tr ("Unable to create target directory: ") << tc;
|
||||
return false;
|
||||
}
|
||||
if (! cp_dir_recursive (tl::combine_path (path, *e), tc)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
QFileInfo fi (dir.absoluteFilePath (*e));
|
||||
QFileInfo fi_target (dir_target.absoluteFilePath (*e));
|
||||
|
||||
if (fi.isDir ()) {
|
||||
|
||||
// Copy subdirectory
|
||||
if (! fi_target.exists ()) {
|
||||
if (! dir_target.mkdir (*e)) {
|
||||
tl::error << tr ("Unable to create target directory: %1").arg (dir_target.absoluteFilePath (*e));
|
||||
return false;
|
||||
}
|
||||
} else if (! fi_target.isDir ()) {
|
||||
tl::error << tr ("Unable to create target directory (is a file already): %1").arg (dir_target.absoluteFilePath (*e));
|
||||
return false;
|
||||
}
|
||||
if (! cp_dir_recursive (fi.filePath (), fi_target.filePath ())) {
|
||||
return false;
|
||||
}
|
||||
entries = dir_entries (path, true /*with_files*/, false /*without_dirs*/);
|
||||
for (std::vector<std::string>::const_iterator e = entries.begin (); e != entries.end (); ++e) {
|
||||
|
||||
// TODO: leave symlinks symlinks? How to copy symlinks with Qt?
|
||||
} else if (fi.isFile ()) {
|
||||
|
||||
QFile file (fi.filePath ());
|
||||
QFile file_target (fi_target.filePath ());
|
||||
// copy the files
|
||||
try {
|
||||
|
||||
if (! file.open (QIODevice::ReadOnly)) {
|
||||
tl::error << tr ("Unable to open source file for reading: %1").arg (fi.filePath ());
|
||||
return false;
|
||||
}
|
||||
if (! file_target.open (QIODevice::WriteOnly)) {
|
||||
tl::error << tr ("Unable to open target file for writing: %1").arg (fi_target.filePath ());
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t chunk_size = 64 * 1024;
|
||||
|
||||
while (! file.atEnd ()) {
|
||||
QByteArray data = file.read (chunk_size);
|
||||
file_target.write (data);
|
||||
}
|
||||
|
||||
file.close ();
|
||||
file_target.close ();
|
||||
tl::OutputFile os_file (tl::combine_path (path_to, *e));
|
||||
tl::OutputStream os (os_file);
|
||||
tl::InputFile is_file (tl::combine_path (path, *e));
|
||||
tl::InputStream is (is_file);
|
||||
is.copy_to (os);
|
||||
|
||||
} catch (tl::Exception &ex) {
|
||||
tl::error << tr ("Unable to copy file ") << tl::combine_path (path_to, *e) << tr (" to ") << tl::combine_path (path, *e)
|
||||
<< tr ("(Error ") << ex.msg () << ")";
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mkpath (const std::string &path)
|
||||
{
|
||||
// @@@
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string absolute_path (const std::string &s)
|
||||
{
|
||||
std::vector<std::string> parts = split_path (absolute_file_path (s));
|
||||
|
|
@ -305,39 +387,58 @@ std::string absolute_path (const std::string &s)
|
|||
|
||||
std::string current_dir ()
|
||||
{
|
||||
char *cwd;
|
||||
#if defined(_WIN32)
|
||||
cwd = _getcwd (NULL, 0);
|
||||
#else
|
||||
cwd = getcwd (NULL, 0);
|
||||
#endif
|
||||
|
||||
wchar_t *cwd = _wgetcwd (NULL, 0);
|
||||
if (cwd == NULL) {
|
||||
return std::string ();
|
||||
} else {
|
||||
std::string cwds (cwd);
|
||||
std::string cwds (tl::to_string (std::wstring (cwd)));
|
||||
free (cwd);
|
||||
return cwds;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
char *cwd = getcwd (NULL, 0);
|
||||
if (cwd == NULL) {
|
||||
return std::string ();
|
||||
} else {
|
||||
std::string cwds (tl::to_string_from_local (cwd));
|
||||
free (cwd);
|
||||
return cwds;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static std::pair<std::string, bool> absolute_path_of_existing (const std::string &s)
|
||||
{
|
||||
char *fp;
|
||||
#if defined (_WIN32)
|
||||
fp = _fullpath (NULL, s.c_str (), 0);
|
||||
#else
|
||||
fp = realpath (s.c_str (), NULL);
|
||||
#endif
|
||||
|
||||
wchar_t *fp = _wfullpath (NULL, tl::to_wstring (s).c_str (), 0);
|
||||
if (fp == NULL) {
|
||||
return std::make_pair (std::string (), false);
|
||||
} else {
|
||||
std::string fps (fp);
|
||||
std::string fps (tl::to_string (std::wstring (fp)));
|
||||
free (fp);
|
||||
return std::make_pair (fps, true);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
char *fp;
|
||||
fp = realpath (tl::to_local (s).c_str (), NULL);
|
||||
if (fp == NULL) {
|
||||
return std::make_pair (std::string (), false);
|
||||
} else {
|
||||
std::string fps (tl::to_string_from_local (fp));
|
||||
free (fp);
|
||||
return std::make_pair (fps, true);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string absolute_file_path (const std::string &s)
|
||||
|
|
@ -436,16 +537,25 @@ std::string extension (const std::string &s)
|
|||
return tl::join (fnp, ".");
|
||||
}
|
||||
|
||||
static int stat_func (const std::string &s, struct stat &st)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
return _wstat (tl::to_wstring (s).c_str (), &st);
|
||||
#else
|
||||
return stat (tl::to_local (s).c_str (), &st);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool file_exists (const std::string &p)
|
||||
{
|
||||
struct stat st;
|
||||
return stat (p.c_str (), &st) == 0;
|
||||
return stat_func (p, st) == 0;
|
||||
}
|
||||
|
||||
bool is_dir (const std::string &p)
|
||||
{
|
||||
struct stat st;
|
||||
if (stat (p.c_str (), &st) != 0) {
|
||||
if (stat_func (p, st) != 0) {
|
||||
return false;
|
||||
} else {
|
||||
return !S_ISREG (st.st_mode);
|
||||
|
|
@ -466,8 +576,8 @@ bool is_same_file (const std::string &a, const std::string &b)
|
|||
|
||||
#if defined(_WIN32)
|
||||
|
||||
HANDLE h1 = ::CreateFile (a.c_str (), 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
HANDLE h2 = ::CreateFile (b.c_str (), 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
HANDLE h1 = ::CreateFileW (tl::to_wstring (a).c_str (), 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
HANDLE h2 = ::CreateFileW (tl::to_wstring (b).c_str (), 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
bool result = false;
|
||||
|
||||
|
|
@ -493,10 +603,7 @@ bool is_same_file (const std::string &a, const std::string &b)
|
|||
#else
|
||||
|
||||
struct stat sta, stb;
|
||||
if (stat (a.c_str (), &sta) != 0) {
|
||||
return false;
|
||||
}
|
||||
if (stat (b.c_str (), &stb) != 0) {
|
||||
if (stat_func (a, sta) != 0 || stat_func (b, stb) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -96,6 +96,25 @@ bool TL_PUBLIC file_exists (const std::string &s);
|
|||
*/
|
||||
bool TL_PUBLIC is_dir (const std::string &s);
|
||||
|
||||
/**
|
||||
* @brief Gets the directory entries for the given directory
|
||||
* This method will NEVER return the ".." entry.
|
||||
* @param with_files Includes all files
|
||||
* @param with_dirs Include all directories
|
||||
* @param without_dotfiles Exclude all ".*" files
|
||||
*/
|
||||
std::vector<std::string> TL_PUBLIC dir_entries (const std::string &s, bool with_files = true, bool with_dirs = true, bool without_dotfiles = false);
|
||||
|
||||
/**
|
||||
* @brief Removes the given file and returns true on success
|
||||
*/
|
||||
bool TL_PUBLIC rm_file (const std::string &path);
|
||||
|
||||
/**
|
||||
* @brief Removes the given directory and returns true on success
|
||||
*/
|
||||
bool TL_PUBLIC rm_dir (const std::string &path);
|
||||
|
||||
/**
|
||||
* @brief Returns true, if the given path is the same directory of file than the other one
|
||||
*/
|
||||
|
|
@ -120,7 +139,7 @@ std::string TL_PUBLIC current_dir ();
|
|||
* added if the path terminates with a separator (like "C:\" or "/home/user/").
|
||||
* The idea is that the last element is the file name part.
|
||||
*/
|
||||
static std::vector<std::string> split_path (const std::string &p);
|
||||
std::vector<std::string> split_path (const std::string &p);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -124,185 +124,6 @@ public:
|
|||
{ }
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
// Input file delegate implementations - declaration and implementation
|
||||
|
||||
/**
|
||||
* @brief A zlib input file delegate
|
||||
*
|
||||
* Implements the reader for a zlib stream
|
||||
*/
|
||||
class InputZLibFile
|
||||
: public InputStreamBase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Open a file with the given path
|
||||
*
|
||||
* Opening a file is a prerequisite for reading from the
|
||||
* object. open() will throw a FileOpenErrorException if
|
||||
* an error occurs.
|
||||
*
|
||||
* @param path The (relative) path of the file to open
|
||||
*/
|
||||
InputZLibFile (const std::string &path);
|
||||
|
||||
/**
|
||||
* @brief Close the file
|
||||
*
|
||||
* The destructor will automatically close the file.
|
||||
*/
|
||||
virtual ~InputZLibFile ();
|
||||
|
||||
/**
|
||||
* @brief Read from a file
|
||||
*
|
||||
* Implements the basic read method.
|
||||
* Will throw a ZLibReadErrorException if an error occurs.
|
||||
*/
|
||||
virtual size_t read (char *b, size_t n);
|
||||
|
||||
virtual void reset ();
|
||||
|
||||
virtual void close ();
|
||||
|
||||
virtual std::string source () const
|
||||
{
|
||||
return m_source;
|
||||
}
|
||||
|
||||
virtual std::string absolute_path () const;
|
||||
|
||||
virtual std::string filename () const;
|
||||
|
||||
private:
|
||||
std::string m_source;
|
||||
gzFile m_zs;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A simple input file delegate
|
||||
*
|
||||
* Implements the reader for ordinary files.
|
||||
*/
|
||||
class InputFile
|
||||
: public InputStreamBase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Open a file with the given path
|
||||
*
|
||||
* Opening a file is a prerequisite for reading from the
|
||||
* object. open() will throw a FileOpenErrorException if
|
||||
* an error occurs.
|
||||
*
|
||||
* @param path The (relative) path of the file to open
|
||||
* @param read True, if the file should be read, false on write.
|
||||
*/
|
||||
InputFile (const std::string &path);
|
||||
|
||||
/**
|
||||
* @brief Close the file
|
||||
*
|
||||
* The destructor will automatically close the file.
|
||||
*/
|
||||
virtual ~InputFile ();
|
||||
|
||||
virtual size_t read (char *b, size_t n);
|
||||
|
||||
virtual void reset ();
|
||||
|
||||
virtual void close ();
|
||||
|
||||
virtual std::string source () const
|
||||
{
|
||||
return m_source;
|
||||
}
|
||||
|
||||
virtual std::string absolute_path () const;
|
||||
|
||||
virtual std::string filename () const;
|
||||
|
||||
private:
|
||||
std::string m_source;
|
||||
int m_fd;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A simple pipe input delegate
|
||||
*
|
||||
* Implements the reader for pipe streams
|
||||
*/
|
||||
class InputPipe
|
||||
: public InputStreamBase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Open a stream by connecting with the stdout of a given command
|
||||
*
|
||||
* Opening a pipe is a prerequisite for reading from the
|
||||
* object. open() will throw a FilePOpenErrorException if
|
||||
* an error occurs - commonly if the command cannot be executed.
|
||||
* This implementation is based on popen ().
|
||||
*
|
||||
* @param cmd The command to execute
|
||||
* @param read True, if the file should be read, false on write.
|
||||
*/
|
||||
InputPipe (const std::string &path);
|
||||
|
||||
/**
|
||||
* @brief Close the pipe
|
||||
*
|
||||
* The destructor will automatically close the pipe.
|
||||
*/
|
||||
virtual ~InputPipe ();
|
||||
|
||||
/**
|
||||
* @brief Read from the pipe
|
||||
*
|
||||
* Implements the basic read method.
|
||||
* Will throw a FilePReadErrorException if an error occurs.
|
||||
*/
|
||||
virtual size_t read (char *b, size_t n);
|
||||
|
||||
/**
|
||||
* @brief Reset to the beginning of the file
|
||||
*/
|
||||
virtual void reset ();
|
||||
|
||||
/**
|
||||
* @brief Closes the pipe
|
||||
*/
|
||||
virtual void close ();
|
||||
|
||||
/**
|
||||
* @brief Get the source specification (the file name)
|
||||
*
|
||||
* Returns an empty string if no file name is available.
|
||||
*/
|
||||
virtual std::string source () const
|
||||
{
|
||||
// No source (in the sense of a file name) is available ..
|
||||
return std::string ();
|
||||
}
|
||||
|
||||
virtual std::string absolute_path () const
|
||||
{
|
||||
// No source (in the sense of a file name) is available ..
|
||||
return std::string ();
|
||||
}
|
||||
|
||||
virtual std::string filename () const
|
||||
{
|
||||
// No source (in the sense of a file name) is available ..
|
||||
return std::string ();
|
||||
}
|
||||
|
||||
private:
|
||||
FILE *m_file;
|
||||
std::string m_source;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// InputStream implementation
|
||||
|
||||
|
|
@ -490,8 +311,7 @@ InputStream::read_all ()
|
|||
return str;
|
||||
}
|
||||
|
||||
void
|
||||
InputStream::copy_to (tl::OutputStream &os)
|
||||
void InputStream::copy_to(tl::OutputStream &os)
|
||||
{
|
||||
const size_t chunk = 65536;
|
||||
char b [chunk];
|
||||
|
|
@ -794,147 +614,6 @@ InputZLibFile::filename () const
|
|||
return tl::filename (m_source);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
// OutputStreamBase implementations - declarations and implementation
|
||||
|
||||
/**
|
||||
* @brief A zlib output file delegate
|
||||
*
|
||||
* Implements the writer for a zlib stream
|
||||
*/
|
||||
class OutputZLibFile
|
||||
: public OutputStreamBase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Open a file with the given path
|
||||
*
|
||||
* Opening a file is a prerequisite for reading from the
|
||||
* object. open() will throw a FileOpenErrorException if
|
||||
* an error occurs.
|
||||
*
|
||||
* @param path The (relative) path of the file to open
|
||||
*/
|
||||
OutputZLibFile (const std::string &path);
|
||||
|
||||
/**
|
||||
* @brief Close the file
|
||||
*
|
||||
* The destructor will automatically close the file.
|
||||
*/
|
||||
virtual ~OutputZLibFile ();
|
||||
|
||||
/**
|
||||
* @brief Write to a file
|
||||
*
|
||||
* Implements the basic write method.
|
||||
* Will throw a ZLibWriteErrorException if an error occurs.
|
||||
*/
|
||||
virtual void write (const char *b, size_t n);
|
||||
|
||||
private:
|
||||
std::string m_source;
|
||||
gzFile m_zs;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A simple output file delegate
|
||||
*
|
||||
* Implements the writer for ordinary files.
|
||||
*/
|
||||
class OutputFile
|
||||
: public OutputStreamBase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Open a file with the given path
|
||||
*
|
||||
* Opening a file is a prerequisite for reading from the
|
||||
* object. open() will throw a FileOpenErrorException if
|
||||
* an error occurs.
|
||||
*
|
||||
* @param path The (relative) path of the file to open
|
||||
* @param read True, if the file should be read, false on write.
|
||||
*/
|
||||
OutputFile (const std::string &path);
|
||||
|
||||
/**
|
||||
* @brief Close the file
|
||||
*
|
||||
* The destructor will automatically close the file.
|
||||
*/
|
||||
virtual ~OutputFile ();
|
||||
|
||||
/**
|
||||
* @brief Seek to the specified position
|
||||
*
|
||||
* Writing continues at that position after a seek.
|
||||
*/
|
||||
virtual void seek (size_t s);
|
||||
|
||||
/**
|
||||
* @brief Returns a value indicating whether that stream supports seek
|
||||
*/
|
||||
bool supports_seek ()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write to a file
|
||||
*
|
||||
* Implements the basic write method.
|
||||
* Will throw a FileWriteErrorException if an error occurs.
|
||||
*/
|
||||
virtual void write (const char *b, size_t n);
|
||||
|
||||
private:
|
||||
std::string m_source;
|
||||
int m_fd;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A simple pipe output delegate
|
||||
*
|
||||
* Implements the writer for pipe streams
|
||||
*/
|
||||
class OutputPipe
|
||||
: public OutputStreamBase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Open a stream by connecting with the stdout of a given command
|
||||
*
|
||||
* Opening a pipe is a prerequisite for reading from the
|
||||
* object. open() will throw a FilePOpenErrorException if
|
||||
* an error occurs - commonly if the command cannot be executed.
|
||||
* This implementation is based on popen ().
|
||||
*
|
||||
* @param cmd The command to execute
|
||||
* @param read True, if the file should be read, false on write.
|
||||
*/
|
||||
OutputPipe (const std::string &path);
|
||||
|
||||
/**
|
||||
* @brief Close the pipe
|
||||
*
|
||||
* The destructor will automatically close the pipe.
|
||||
*/
|
||||
virtual ~OutputPipe ();
|
||||
|
||||
/**
|
||||
* @brief Write to a file
|
||||
*
|
||||
* Implements the basic write method.
|
||||
* Will throw a FilePWriteErrorException if an error occurs.
|
||||
*/
|
||||
virtual void write (const char *b, size_t n);
|
||||
|
||||
private:
|
||||
FILE *m_file;
|
||||
std::string m_source;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// OutputStream implementation
|
||||
|
||||
|
|
|
|||
|
|
@ -166,6 +166,182 @@ private:
|
|||
size_t m_length, m_pos;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A zlib input file delegate
|
||||
*
|
||||
* Implements the reader for a zlib stream
|
||||
*/
|
||||
class InputZLibFile
|
||||
: public InputStreamBase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Open a file with the given path
|
||||
*
|
||||
* Opening a file is a prerequisite for reading from the
|
||||
* object. open() will throw a FileOpenErrorException if
|
||||
* an error occurs.
|
||||
*
|
||||
* @param path The (relative) path of the file to open
|
||||
*/
|
||||
InputZLibFile (const std::string &path);
|
||||
|
||||
/**
|
||||
* @brief Close the file
|
||||
*
|
||||
* The destructor will automatically close the file.
|
||||
*/
|
||||
virtual ~InputZLibFile ();
|
||||
|
||||
/**
|
||||
* @brief Read from a file
|
||||
*
|
||||
* Implements the basic read method.
|
||||
* Will throw a ZLibReadErrorException if an error occurs.
|
||||
*/
|
||||
virtual size_t read (char *b, size_t n);
|
||||
|
||||
virtual void reset ();
|
||||
|
||||
virtual void close ();
|
||||
|
||||
virtual std::string source () const
|
||||
{
|
||||
return m_source;
|
||||
}
|
||||
|
||||
virtual std::string absolute_path () const;
|
||||
|
||||
virtual std::string filename () const;
|
||||
|
||||
private:
|
||||
std::string m_source;
|
||||
gzFile m_zs;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A simple input file delegate
|
||||
*
|
||||
* Implements the reader for ordinary files.
|
||||
*/
|
||||
class InputFile
|
||||
: public InputStreamBase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Open a file with the given path
|
||||
*
|
||||
* Opening a file is a prerequisite for reading from the
|
||||
* object. open() will throw a FileOpenErrorException if
|
||||
* an error occurs.
|
||||
*
|
||||
* @param path The (relative) path of the file to open
|
||||
* @param read True, if the file should be read, false on write.
|
||||
*/
|
||||
InputFile (const std::string &path);
|
||||
|
||||
/**
|
||||
* @brief Close the file
|
||||
*
|
||||
* The destructor will automatically close the file.
|
||||
*/
|
||||
virtual ~InputFile ();
|
||||
|
||||
virtual size_t read (char *b, size_t n);
|
||||
|
||||
virtual void reset ();
|
||||
|
||||
virtual void close ();
|
||||
|
||||
virtual std::string source () const
|
||||
{
|
||||
return m_source;
|
||||
}
|
||||
|
||||
virtual std::string absolute_path () const;
|
||||
|
||||
virtual std::string filename () const;
|
||||
|
||||
private:
|
||||
std::string m_source;
|
||||
int m_fd;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A simple pipe input delegate
|
||||
*
|
||||
* Implements the reader for pipe streams
|
||||
*/
|
||||
class InputPipe
|
||||
: public InputStreamBase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Open a stream by connecting with the stdout of a given command
|
||||
*
|
||||
* Opening a pipe is a prerequisite for reading from the
|
||||
* object. open() will throw a FilePOpenErrorException if
|
||||
* an error occurs - commonly if the command cannot be executed.
|
||||
* This implementation is based on popen ().
|
||||
*
|
||||
* @param cmd The command to execute
|
||||
* @param read True, if the file should be read, false on write.
|
||||
*/
|
||||
InputPipe (const std::string &path);
|
||||
|
||||
/**
|
||||
* @brief Close the pipe
|
||||
*
|
||||
* The destructor will automatically close the pipe.
|
||||
*/
|
||||
virtual ~InputPipe ();
|
||||
|
||||
/**
|
||||
* @brief Read from the pipe
|
||||
*
|
||||
* Implements the basic read method.
|
||||
* Will throw a FilePReadErrorException if an error occurs.
|
||||
*/
|
||||
virtual size_t read (char *b, size_t n);
|
||||
|
||||
/**
|
||||
* @brief Reset to the beginning of the file
|
||||
*/
|
||||
virtual void reset ();
|
||||
|
||||
/**
|
||||
* @brief Closes the pipe
|
||||
*/
|
||||
virtual void close ();
|
||||
|
||||
/**
|
||||
* @brief Get the source specification (the file name)
|
||||
*
|
||||
* Returns an empty string if no file name is available.
|
||||
*/
|
||||
virtual std::string source () const
|
||||
{
|
||||
// No source (in the sense of a file name) is available ..
|
||||
return std::string ();
|
||||
}
|
||||
|
||||
virtual std::string absolute_path () const
|
||||
{
|
||||
// No source (in the sense of a file name) is available ..
|
||||
return std::string ();
|
||||
}
|
||||
|
||||
virtual std::string filename () const
|
||||
{
|
||||
// No source (in the sense of a file name) is available ..
|
||||
return std::string ();
|
||||
}
|
||||
|
||||
private:
|
||||
FILE *m_file;
|
||||
std::string m_source;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
|
|
@ -248,8 +424,9 @@ public:
|
|||
|
||||
/**
|
||||
* @brief Copies the content of the stream to the output stream
|
||||
* Throws an exception on error.
|
||||
*/
|
||||
void copy_to (tl::OutputStream &os);
|
||||
void copy_to(tl::OutputStream &os);
|
||||
|
||||
/**
|
||||
* @brief Enable uncompression of the following DEFLATE-compressed block
|
||||
|
|
@ -604,6 +781,144 @@ private:
|
|||
std::ostringstream m_stream;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A zlib output file delegate
|
||||
*
|
||||
* Implements the writer for a zlib stream
|
||||
*/
|
||||
class OutputZLibFile
|
||||
: public OutputStreamBase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Open a file with the given path
|
||||
*
|
||||
* Opening a file is a prerequisite for reading from the
|
||||
* object. open() will throw a FileOpenErrorException if
|
||||
* an error occurs.
|
||||
*
|
||||
* @param path The (relative) path of the file to open
|
||||
*/
|
||||
OutputZLibFile (const std::string &path);
|
||||
|
||||
/**
|
||||
* @brief Close the file
|
||||
*
|
||||
* The destructor will automatically close the file.
|
||||
*/
|
||||
virtual ~OutputZLibFile ();
|
||||
|
||||
/**
|
||||
* @brief Write to a file
|
||||
*
|
||||
* Implements the basic write method.
|
||||
* Will throw a ZLibWriteErrorException if an error occurs.
|
||||
*/
|
||||
virtual void write (const char *b, size_t n);
|
||||
|
||||
private:
|
||||
std::string m_source;
|
||||
gzFile m_zs;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A simple output file delegate
|
||||
*
|
||||
* Implements the writer for ordinary files.
|
||||
*/
|
||||
class OutputFile
|
||||
: public OutputStreamBase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Open a file with the given path
|
||||
*
|
||||
* Opening a file is a prerequisite for reading from the
|
||||
* object. open() will throw a FileOpenErrorException if
|
||||
* an error occurs.
|
||||
*
|
||||
* @param path The (relative) path of the file to open
|
||||
* @param read True, if the file should be read, false on write.
|
||||
*/
|
||||
OutputFile (const std::string &path);
|
||||
|
||||
/**
|
||||
* @brief Close the file
|
||||
*
|
||||
* The destructor will automatically close the file.
|
||||
*/
|
||||
virtual ~OutputFile ();
|
||||
|
||||
/**
|
||||
* @brief Seek to the specified position
|
||||
*
|
||||
* Writing continues at that position after a seek.
|
||||
*/
|
||||
virtual void seek (size_t s);
|
||||
|
||||
/**
|
||||
* @brief Returns a value indicating whether that stream supports seek
|
||||
*/
|
||||
bool supports_seek ()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write to a file
|
||||
*
|
||||
* Implements the basic write method.
|
||||
* Will throw a FileWriteErrorException if an error occurs.
|
||||
*/
|
||||
virtual void write (const char *b, size_t n);
|
||||
|
||||
private:
|
||||
std::string m_source;
|
||||
int m_fd;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A simple pipe output delegate
|
||||
*
|
||||
* Implements the writer for pipe streams
|
||||
*/
|
||||
class OutputPipe
|
||||
: public OutputStreamBase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Open a stream by connecting with the stdout of a given command
|
||||
*
|
||||
* Opening a pipe is a prerequisite for reading from the
|
||||
* object. open() will throw a FilePOpenErrorException if
|
||||
* an error occurs - commonly if the command cannot be executed.
|
||||
* This implementation is based on popen ().
|
||||
*
|
||||
* @param cmd The command to execute
|
||||
* @param read True, if the file should be read, false on write.
|
||||
*/
|
||||
OutputPipe (const std::string &path);
|
||||
|
||||
/**
|
||||
* @brief Close the pipe
|
||||
*
|
||||
* The destructor will automatically close the pipe.
|
||||
*/
|
||||
virtual ~OutputPipe ();
|
||||
|
||||
/**
|
||||
* @brief Write to a file
|
||||
*
|
||||
* Implements the basic write method.
|
||||
* Will throw a FilePWriteErrorException if an error occurs.
|
||||
*/
|
||||
virtual void write (const char *b, size_t n);
|
||||
|
||||
private:
|
||||
FILE *m_file;
|
||||
std::string m_source;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -40,9 +40,9 @@ static std::locale c_locale ("C");
|
|||
// -------------------------------------------------------------------------
|
||||
// Conversion of UTF8 to wchar_t
|
||||
|
||||
static std::vector<wchar_t> utf8_to_wchar (const std::string &s)
|
||||
std::wstring to_wstring (const std::string &s)
|
||||
{
|
||||
std::vector<wchar_t> ws;
|
||||
std::wstring ws;
|
||||
|
||||
const char *cpe = s.c_str () + s.size ();
|
||||
for (const char *cp = s.c_str (); cp < cpe; ) {
|
||||
|
|
@ -61,10 +61,10 @@ static std::vector<wchar_t> utf8_to_wchar (const std::string &s)
|
|||
|
||||
if (c32 >= 0x10000) {
|
||||
c32 -= 0x10000;
|
||||
ws.push_back (wchar_t (0xd800 + (c32 >> 10)));
|
||||
ws.push_back (wchar_t (0xdc00 + (c32 & 0x3ff)));
|
||||
ws += wchar_t (0xd800 + (c32 >> 10));
|
||||
ws += wchar_t (0xdc00 + (c32 & 0x3ff));
|
||||
} else {
|
||||
ws.push_back (wchar_t (c32));
|
||||
ws += wchar_t (c32);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -72,11 +72,11 @@ static std::vector<wchar_t> utf8_to_wchar (const std::string &s)
|
|||
return ws;
|
||||
}
|
||||
|
||||
static std::string wchar_to_utf8 (const std::vector<wchar_t> &ws)
|
||||
std::string to_string (const std::wstring &ws)
|
||||
{
|
||||
std::string s;
|
||||
|
||||
for (std::vector<wchar_t>::const_iterator c = ws.begin (); c != ws.end (); ++c) {
|
||||
for (std::wstring::const_iterator c = ws.begin (); c != ws.end (); ++c) {
|
||||
|
||||
uint32_t c32 = *c;
|
||||
if (c32 >= 0xd800 && c + 1 < ws.end ()) {
|
||||
|
|
@ -140,20 +140,36 @@ std::string tl::db_to_string (double d)
|
|||
|
||||
std::string tl::to_upper_case (const std::string &s)
|
||||
{
|
||||
std::vector<wchar_t> ws = utf8_to_wchar (s);
|
||||
for (std::vector<wchar_t>::iterator c = ws.begin (); c != ws.end (); ++c) {
|
||||
std::wstring ws = to_wstring (s);
|
||||
for (std::wstring::iterator c = ws.begin (); c != ws.end (); ++c) {
|
||||
*c = towupper (*c);
|
||||
}
|
||||
return wchar_to_utf8 (ws);
|
||||
return to_string (ws);
|
||||
}
|
||||
|
||||
std::string tl::to_lower_case (const std::string &s)
|
||||
{
|
||||
std::vector<wchar_t> ws = utf8_to_wchar (s);
|
||||
for (std::vector<wchar_t>::iterator c = ws.begin (); c != ws.end (); ++c) {
|
||||
std::wstring ws = to_wstring (s);
|
||||
for (std::wstring::iterator c = ws.begin (); c != ws.end (); ++c) {
|
||||
*c = towlower (*c);
|
||||
}
|
||||
return wchar_to_utf8 (ws);
|
||||
return to_string (ws);
|
||||
}
|
||||
|
||||
std::string to_local (const std::string &s)
|
||||
{
|
||||
std::auto_ptr<char> buffer (new char [MB_CUR_MAX]); // MB_CUR_MAX isn't a constant
|
||||
std::string ls;
|
||||
|
||||
std::wstring ws = to_wstring (s);
|
||||
for (std::wstring::const_iterator c = ws.begin (); c != ws.end (); ++c) {
|
||||
int length = wctomb (buffer.get (), *c);
|
||||
for (int i = 0; i < length; ++i) {
|
||||
ls += buffer.get ()[i];
|
||||
}
|
||||
}
|
||||
|
||||
return ls;
|
||||
}
|
||||
|
||||
std::string to_string_from_local (const char *cp)
|
||||
|
|
@ -161,7 +177,7 @@ std::string to_string_from_local (const char *cp)
|
|||
mbstate_t state;
|
||||
memset ((void *) &state, 0, sizeof (mbstate_t));
|
||||
|
||||
std::vector<wchar_t> ws;
|
||||
std::wstring ws;
|
||||
|
||||
size_t max = strlen (cp);
|
||||
|
||||
|
|
@ -172,12 +188,12 @@ std::string to_string_from_local (const char *cp)
|
|||
if (length < 1) {
|
||||
break;
|
||||
}
|
||||
ws.push_back (wc);
|
||||
ws += wc;
|
||||
cp += length;
|
||||
max -= length;
|
||||
}
|
||||
|
||||
return wchar_to_utf8 (ws);
|
||||
return to_string (ws);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -34,7 +34,9 @@
|
|||
#include "tlException.h"
|
||||
#include "tlVariant.h"
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
class QImage;
|
||||
#endif
|
||||
|
||||
namespace tl {
|
||||
|
||||
|
|
@ -262,6 +264,7 @@ TL_PUBLIC std::string to_string (float d, int prec);
|
|||
TL_PUBLIC std::string to_string (const unsigned char *cp, int length);
|
||||
TL_PUBLIC std::string to_string (const char *cp, int length);
|
||||
TL_PUBLIC std::string to_string_from_local (const char *cp);
|
||||
TL_PUBLIC std::string to_local (const std::string &s);
|
||||
|
||||
template <class T> inline std::string to_string (const T &o) { return o.to_string (); }
|
||||
template <> inline std::string to_string (const double &d) { return to_string (d, 12); }
|
||||
|
|
@ -287,8 +290,20 @@ template <> inline std::string to_string (const std::string &s) { return s; }
|
|||
// to a variant object
|
||||
template <> inline std::string to_string (const tl::Variant &v) { return v.to_parsable_string (); }
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
// some dummy conversions provided for tl::Variant implementation
|
||||
template <> inline std::string to_string (const QImage &) { return std::string (); }
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Converts UTF-8 to wide character string
|
||||
*/
|
||||
std::wstring TL_PUBLIC to_wstring (const std::string &s);
|
||||
|
||||
/**
|
||||
* @brief Converts a wide character string to UTF-8
|
||||
*/
|
||||
std::string TL_PUBLIC to_string (const std::wstring &ws);
|
||||
|
||||
/**
|
||||
* @brief Convert to a quoted string
|
||||
|
|
|
|||
|
|
@ -24,6 +24,10 @@
|
|||
#include "tlFileUtils.h"
|
||||
#include "tlUnitTest.h"
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
|
||||
// A few things we cross-check against Qt
|
||||
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QFile>
|
||||
|
|
@ -161,3 +165,5 @@ TEST (3)
|
|||
file.close ();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue