#include <cerrno>
#include <cstdio>
+#include <cstdlib>
#include <cstring>
+#include <iostream>
+#include <stdexcept>
#ifdef _WIN32
# include <conio.h>
# include <direct.h>
#endif
#include <sys/stat.h>
+using namespace std;
+
namespace blank {
return S_ISREG(info.st_mode);
}
#endif
- std::time_t get_mtime(const Stat &info) {
+ time_t get_mtime(const Stat &info) {
#ifdef __APPLE__
return info.st_mtimespec.tv_sec;
#else
return is_file(info);
}
-std::time_t file_mtime(const char *path) {
+time_t file_mtime(const char *path) {
Stat info;
if (do_stat(path, info) != 0) {
return 0;
}
-bool make_dirs(const std::string &path) {
+bool make_dirs(const string &path) {
if (make_dir(path)) {
return true;
}
#else
auto pos = path.find_last_of('/');
#endif
- if (pos == std::string::npos) {
+ if (pos == string::npos) {
return false;
}
if (pos == path.length() - 1) {
#else
pos = path.find_last_of('/', pos - 1);
#endif
- if (pos == std::string::npos) {
+ if (pos == string::npos) {
return false;
}
}
}
-bool remove_file(const std::string &path) {
+bool remove_file(const string &path) {
return remove(path.c_str()) == 0;
}
-bool remove_dir(const std::string &path) {
+bool remove_dir(const string &path) {
#ifdef _WIN32
// shamelessly stolen from http://www.codeguru.com/forum/showthread.php?t=239271
- const std::string pattern = path + "\\*.*";
+ const string pattern = path + "\\*.*";
WIN32_FIND_DATA info;
HANDLE file = FindFirstFile(pattern.c_str(), &info);
if (file == INVALID_HANDLE_VALUE) {
) {
continue;
}
- const std::string sub_path = path + '\\' + info.cFileName;
+ const string sub_path = path + '\\' + info.cFileName;
if ((info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
if (!remove_dir(sub_path)) {
return false;
) {
continue;
}
- const std::string sub_path = path + '/' + entry->d_name;
+ const string sub_path = path + '/' + entry->d_name;
if (is_dir(sub_path)) {
if (!remove_dir(sub_path)) {
return false;
#endif
}
+
+TempDir::TempDir() {
+#if _DEFAULT_SOURCE || _BSD_SOURCE || _POSIX_C_SOURCE >= 200809L
+ char tmpl[] = "blank.XXXXXX";
+ const char *name = mkdtemp(tmpl);
+ if (!name) {
+ throw runtime_error("unable to create temporary directory");
+ }
+ path = name;
+#else
+ char name[L_tmpnam];
+ tmpnam(name);
+ constexpr int max_tries = 10;
+ int tries = 0;
+ while (!make_dirs(name) && tries < max_tries) {
+ tmpnam(name);
+ ++tries;
+ }
+ if (tries == max_tries) {
+ throw runtime_error("unable to create temporary directory");
+ }
+#endif
+ path = name;
+}
+
+TempDir::~TempDir() {
+ try {
+ remove_dir(path);
+ } catch (...) {
+ cerr << "warning: could not remove temp dir " << path << endl;
+ }
+}
+
}
/// @return true if the directory was completely removed
bool remove_dir(const std::string &);
+
+/// Create a temporary directory with lifetime tie to the instance's.
+/// Note that the directory may survive its object if removal fails
+/// for any reason, e.g. another process changing permissions.
+class TempDir {
+
+public:
+ TempDir();
+ ~TempDir();
+
+ TempDir(const TempDir &) = delete;
+ TempDir &operator =(const TempDir &) = delete;
+
+public:
+ const std::string &Path() const noexcept { return path; }
+
+private:
+ std::string path;
+
+};
+
}
#endif
}
}
+Socket::Socket(const string &host, unsigned short port)
+: sock(nullptr) {
+ IPaddress ip;
+ if (SDLNet_ResolveHost(&ip, host.c_str(), port) == -1) {
+ throw NetError("failed to resolve host " + host);
+ }
+ sock = SDLNet_TCP_Open(&ip);
+ if (!sock) {
+ throw NetError("failed to connect to " + host + ':' + to_string(port));
+ }
+}
+
Socket::Socket(TCPsocket sock)
: sock(sock) {
Pool::Pool(int max_conn, size_t buf_siz)
: set(SDLNet_AllocSocketSet(max_conn))
-, buffer(buf_siz, '\0')
, connections()
, use_conn(0)
, max_conn(max_conn)
Socket();
/// create TCP socket bound to given port
explicit Socket(unsigned short port);
+ /// connect to given host:port
+ Socket(const std::string &host, unsigned short port);
private:
/// wrap given SDLNet TCP socket
/// for use with Accept()
private:
SDLNet_SocketSet set;
- std::string buffer;
ConnectionSet connections;
int use_conn;
int max_conn;
namespace test {
void FilesystemTest::setUp() {
- test_dir = "test-dir";
- CPPUNIT_ASSERT_MESSAGE(
- "failed to create test dir",
- make_dir(test_dir));
+ test_dir.reset(new TempDir());
}
void FilesystemTest::tearDown() {
- CPPUNIT_ASSERT_MESSAGE(
- "failed to remove test dir",
- remove_dir(test_dir));
+ test_dir.reset();
}
void FilesystemTest::testFile() {
#ifdef _WIN32
- const string test_file = test_dir + "\\test-file.txt";
+ const string test_file = test_dir->Path() + "\\test-file.txt";
#else
- const string test_file = test_dir + "/test-file";
+ const string test_file = test_dir->Path() + "/test-file";
#endif
CPPUNIT_ASSERT_MESSAGE(
void FilesystemTest::testDirectory() {
#ifdef _WIN32
- const string test_subdir = test_dir + "\\a";
+ const string test_subdir = test_dir->Path() + "\\a";
const string test_subsubdir = test_subdir + "\\b";
const string test_file = test_subsubdir + "\\c.txt";
#else
- const string test_subdir = test_dir + "/a";
+ const string test_subdir = test_dir->Path() + "/a";
const string test_subsubdir = test_subdir + "/b";
const string test_file = test_subsubdir + "/c";
#endif
#ifndef BLANK_TEST_IO_FILESYSTEMTEST_HPP
#define BLANK_TEST_IO_FILESYSTEMTEST_HPP
+#include "io/filesystem.hpp"
+
+#include <memory>
#include <string>
#include <cppunit/extensions/HelperMacros.h>
-namespace blank {
+namespace blank {
namespace test {
class FilesystemTest
void testDirectory();
private:
- std::string test_dir;
+ std::unique_ptr<TempDir> test_dir;
};