Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F126657
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
23 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/util/file-system.cpp b/util/file-system.cpp
index 41230114..d8b1e07b 100644
--- a/util/file-system.cpp
+++ b/util/file-system.cpp
@@ -1,399 +1,403 @@
#ifdef USE_ALLEGRO
#include <allegro.h>
/* FIXME: replace with <winalleg.h> */
#ifdef _WIN32
#define BITMAP dummyBITMAP
#include <windows.h>
#undef BITMAP
#endif
#endif
#include "funcs.h"
#include "file-system.h"
#include "system.h"
#include "globals.h"
#include <dirent.h>
#include <sstream>
#include <exception>
#include <string>
#include <ostream>
#ifndef USE_ALLEGRO
/* some sfl symbols conflict with allegro */
#include "sfl/sfl.h"
#include "sfl/sfldir.h"
#endif
#ifdef _WIN32
#define _WIN32_IE 0x400
#include <shlobj.h>
#endif
using namespace std;
namespace Filesystem{
Exception::Exception(const std::string & where, int line, const std::string & file):
Exc::Base(where, line),
reason(file){
}
Exception::Exception(const std::string & where, int line, const Exc::Base & nested, const std::string & file):
Exc::Base(where, line, nested),
reason(file){
}
Exception::Exception(const Exception & copy):
Exc::Base(copy),
reason(copy.reason){
}
Exception::~Exception() throw (){
}
+
+const std::string Exception::getReason() const {
+ return reason;
+}
NotFound::NotFound(const std::string & where, int line, const std::string & file):
Exception(where, line, file + string(" was not found")){
}
NotFound::NotFound(const std::string & where, int line, const Exc::Base & nested, const std::string & file):
Exception(where, line, nested, file + string(" was not found")){
}
NotFound::NotFound(const NotFound & copy):
Exception(copy){
}
NotFound::~NotFound() throw (){
}
IllegalPath::IllegalPath(const std::string & where, int line, const std::string & file):
Exception(where, line, file){
}
IllegalPath::IllegalPath(const std::string & where, int line, const Exc::Base & nested, const std::string & file):
Exception(where, line, nested, file){
}
IllegalPath::IllegalPath(const IllegalPath & copy):
Exception(copy){
}
IllegalPath::~IllegalPath() throw(){
}
#ifdef _WIN32
AbsolutePath userDirectory(){
ostringstream str;
char path[MAX_PATH];
SHGetSpecialFolderPathA(0, path, CSIDL_APPDATA, false);
str << path << "/paintown/";
return AbsolutePath(str.str());
}
AbsolutePath configFile(){
ostringstream str;
char path[MAX_PATH];
SHGetSpecialFolderPathA(0, path, CSIDL_APPDATA, false);
str << path << "/paintown_configuration.txt";
return AbsolutePath(str.str());
}
#else
AbsolutePath configFile(){
ostringstream str;
/* what if HOME isn't set? */
str << getenv("HOME") << "/.paintownrc";
return AbsolutePath(str.str());
}
AbsolutePath userDirectory(){
ostringstream str;
/* what if HOME isn't set? */
str << getenv("HOME") << "/.paintown/";
return AbsolutePath(str.str());
}
#endif
static AbsolutePath lookup(const RelativePath path) throw (NotFound){
/* first try the main data directory */
AbsolutePath final = Util::getDataPath2().join(path);
if (System::readable(final.path())){
return final;
}
/* then try the user directory, like ~/.paintown */
final = userDirectory().join(path);
if (System::readable(final.path())){
return final;
}
/* then just look in the cwd */
if (System::readable(path.path())){
return AbsolutePath(path.path());
}
ostringstream out;
out << "Cannot find " << path.path() << ". I looked in '" << Util::getDataPath2().join(path).path() << "', '" << userDirectory().join(path).path() << "', and '" << path.path() << "'" << endl;
throw NotFound(__FILE__, __LINE__, out.str());
}
static vector<AbsolutePath> findDirectoriesIn(const AbsolutePath & path){
vector<AbsolutePath> dirs;
DIR * dir = opendir(path.path().c_str());
if (dir == NULL){
return dirs;
}
struct dirent * entry = readdir(dir);
while (entry != NULL){
string total = path.path() + "/" + entry->d_name;
if (System::isDirectory(total)){
dirs.push_back(AbsolutePath(total));
}
entry = readdir(dir);
}
closedir(dir);
return dirs;
}
vector<AbsolutePath> findDirectories(const RelativePath & path){
typedef vector<AbsolutePath> Paths;
Paths dirs;
Paths main_dirs = findDirectoriesIn(Util::getDataPath2().join(path));
Paths user_dirs = findDirectoriesIn(userDirectory().join(path));
Paths here_dirs = findDirectoriesIn(Filesystem::AbsolutePath(path.path()));
dirs.insert(dirs.end(), main_dirs.begin(), main_dirs.end());
dirs.insert(dirs.end(), user_dirs.begin(), user_dirs.end());
dirs.insert(dirs.end(), here_dirs.begin(), here_dirs.end());
return dirs;
}
vector<string> getFiles(const AbsolutePath & dataPath, const string & find){
#ifdef USE_ALLEGRO
struct al_ffblk info;
vector< string > files;
if ( al_findfirst( (dataPath.path() + find).c_str(), &info, FA_ALL ) != 0 ){
return files;
}
files.push_back( dataPath.path() + string( info.name ) );
while ( al_findnext( &info ) == 0 ){
files.push_back( dataPath.path() + string( info.name ) );
}
al_findclose( &info );
return files;
#else
vector<string> files;
DIRST sflEntry;
bool ok = open_dir(&sflEntry, dataPath.path().c_str());
while (ok){
if (file_matches(sflEntry.file_name, find.c_str())){
files.push_back(dataPath.path() + string(sflEntry.file_name));
}
ok = read_dir(&sflEntry);
}
close_dir(&sflEntry);
// Global::debug(0) << "Warning: Filesystem::getFiles() is not implemented yet for SDL" << endl;
return files;
#endif
}
/* remove extra path separators (/) */
static string sanitize(string path){
size_t double_slash = path.find("//");
while (double_slash != string::npos){
path.erase(double_slash, 1);
double_slash = path.find("//");
}
return path;
}
/*
std::string find(const std::string path){
if (path.length() == 0){
throw NotFound("No path given");
}
if (path[0] == '/'){
string str(path);
str.erase(0, 1);
string out = lookup(str);
if (System::isDirectory(out)){
return sanitize(out + "/");
}
return sanitize(out);
}
string out = lookup(path);
if (System::isDirectory(out)){
return sanitize(out + "/");
}
return sanitize(out);
}
*/
AbsolutePath find(const RelativePath & path){
if (path.isEmpty()){
throw NotFound(__FILE__, __LINE__, "No path given");
}
AbsolutePath out = lookup(path);
if (System::isDirectory(out.path())){
return AbsolutePath(sanitize(out.path() + "/"));
}
return AbsolutePath(sanitize(out.path()));
}
RelativePath cleanse(const AbsolutePath & path){
string str = path.path();
if (str.find(Util::getDataPath2().path()) == 0){
str.erase(0, Util::getDataPath2().path().length());
} else if (str.find(userDirectory().path()) == 0){
str.erase(0, userDirectory().path().length());
}
return RelativePath(str);
}
static string dirname(string path){
if (path.find("/") != string::npos ||
path.find("\\") != string::npos){
size_t rem = path.find_last_of("/");
if (rem != string::npos){
return path.substr(0, rem+1);
}
rem = path.find_last_of("\\");
if (rem != string::npos){
return path.substr(0, rem+1);
}
}
return "";
}
std::string stripDir(const std::string & str){
std::string temp = str;
if (str.find( "/") != std::string::npos || str.find( "\\") != std::string::npos){
size_t rem = temp.find_last_of( "/" );
if (rem != std::string::npos){
return str.substr(rem+1,str.size());
}
rem = temp.find_last_of( "\\" );
if( rem != std::string::npos ){
return str.substr(rem+1,str.size());
}
}
return str;
}
std::string removeExtension(const std::string & str){
if (str.find(".") != std::string::npos){
return str.substr(0, str.find_last_of("."));
}
return str;
}
const string & Path::path() const {
return mypath;
}
bool Path::isEmpty() const {
return mypath.empty();
}
Path::~Path(){
}
Path::Path(){
}
static const std::string invertSlashes(const string & str){
string tempStr = str;
if (tempStr.find('\\') != string::npos){
for (int i = tempStr.size()-1; i>-1; --i){
if (tempStr[i] == '\\'){
tempStr[i] = '/';
}
}
}
return tempStr;
}
Path::Path(const std::string & path):
mypath(sanitize(invertSlashes(path))){
}
Path::Path(const Path & path):
mypath(sanitize(invertSlashes(path.path()))){
}
RelativePath::RelativePath(){
}
RelativePath::RelativePath(const std::string & path):
Path(path){
if (! path.empty() && path[0] == '/'){
ostringstream out;
out << "Relative path '" << path << "' cannot start with a /. Only absolute paths can start with /";
throw IllegalPath(__FILE__, __LINE__, out.str());
}
}
RelativePath::RelativePath(const RelativePath & path):
Path(path){
}
RelativePath RelativePath::getDirectory() const {
return RelativePath(dirname(path()));
}
RelativePath RelativePath::getFilename() const {
return RelativePath(stripDir(path()));
}
RelativePath RelativePath::join(const RelativePath & him) const {
return RelativePath(sanitize(path() + "/" + him.path()));
}
RelativePath & RelativePath::operator=(const RelativePath & copy){
setPath(copy.path());
return *this;
}
AbsolutePath::AbsolutePath(){
}
AbsolutePath::AbsolutePath(const std::string & path):
Path(path){
}
AbsolutePath::AbsolutePath(const AbsolutePath & path):
Path(path){
}
AbsolutePath & AbsolutePath::operator=(const AbsolutePath & copy){
setPath(copy.path());
return *this;
}
bool AbsolutePath::operator==(const AbsolutePath & path) const {
return this->path() == path.path();
}
AbsolutePath AbsolutePath::getDirectory() const {
return AbsolutePath(dirname(path()));
}
AbsolutePath AbsolutePath::getFilename() const {
return AbsolutePath(stripDir(path()));
}
AbsolutePath AbsolutePath::join(const RelativePath & path) const {
return AbsolutePath(sanitize(this->path() + "/" + path.path()));
}
}
diff --git a/util/file-system.h b/util/file-system.h
index a24211db..78c6f899 100644
--- a/util/file-system.h
+++ b/util/file-system.h
@@ -1,140 +1,139 @@
#ifndef _paintown_file_system_h
#define _paintown_file_system_h
#include "exceptions/exception.h"
#include <string>
#include <vector>
namespace Filesystem{
/* sorry for the crappy abbreviation, but can't collide with the
* Exception class here
*/
namespace Exc = ::Exception;
class Exception: public Exc::Base {
public:
Exception(const std::string & where, int line, const std::string & file);
Exception(const std::string & where, int line, const Exc::Base & nested, const std::string & file);
Exception(const Exception & copy);
virtual ~Exception() throw ();
- const std::string & getReason() const {
- return reason;
- }
protected:
+ virtual const std::string getReason() const;
+
virtual Exc::Base * copy() const {
return new Exception(*this);
}
private:
std::string reason;
};
class NotFound: public Exception {
public:
NotFound(const std::string & where, int line, const std::string & file);
NotFound(const std::string & where, int line, const Exc::Base & nested, const std::string & file);
virtual ~NotFound() throw();
NotFound(const NotFound & copy);
protected:
virtual Exc::Base * copy() const {
return new NotFound(*this);
}
};
class IllegalPath: public Exception {
public:
IllegalPath(const std::string & where, int line, const std::string & file);
IllegalPath(const std::string & where, int line, const Exc::Base & nested, const std::string & file);
virtual ~IllegalPath() throw();
IllegalPath(const IllegalPath & copy);
protected:
virtual Exc::Base * copy() const {
return new IllegalPath(*this);
}
};
class Path{
public:
const std::string & path() const;
bool isEmpty() const;
virtual ~Path();
protected:
Path();
Path(const std::string & path);
Path(const Path & path);
virtual inline void setPath(const std::string & s){
mypath = s;
}
std::string mypath;
};
/* relative path should not have the leading data directory on it, just
* the path within the paintown system.
*/
class RelativePath: public Path {
public:
explicit RelativePath();
explicit RelativePath(const std::string & path);
RelativePath(const RelativePath & path);
virtual RelativePath getDirectory() const;
virtual RelativePath getFilename() const;
/* a/ + b/ = a/b/ */
RelativePath join(const RelativePath & path) const;
RelativePath & operator=(const RelativePath & copy);
};
/* absolute paths should have the entire filesystem path on it */
class AbsolutePath: public Path {
public:
explicit AbsolutePath();
explicit AbsolutePath(const std::string & path);
AbsolutePath(const AbsolutePath & path);
AbsolutePath & operator=(const AbsolutePath & copy);
bool operator==(const AbsolutePath & path) const;
virtual AbsolutePath getDirectory() const;
virtual AbsolutePath getFilename() const;
AbsolutePath join(const RelativePath & path) const;
};
/* given a relative path like sounds/arrow.png, prepend the proper
* data path to it to give data/sounds/arrow.png
*/
AbsolutePath find(const RelativePath & path);
/* remove the data path from a string
* data/sounds/arrow.png -> sounds/arrow.png
*/
RelativePath cleanse(const AbsolutePath & path);
/* returns all the directories starting with the given path.
* will look in the main data directory, the user directory, and
* the current working directory.
*/
std::vector<AbsolutePath> findDirectories(const RelativePath & path);
/* basename, just get the filename and remove the directory part */
std::string stripDir(const std::string & str);
/* remove extension. foo.txt -> foo */
std::string removeExtension(const std::string & str);
/* user specific directory to hold persistent data */
AbsolutePath userDirectory();
/* user specific path to store the configuration file */
AbsolutePath configFile();
std::vector<std::string> getFiles(const AbsolutePath & dataPath, const std::string & find);
}
#endif
diff --git a/util/load_exception.cpp b/util/load_exception.cpp
index 21c61a0d..8f79143d 100644
--- a/util/load_exception.cpp
+++ b/util/load_exception.cpp
@@ -1,26 +1,30 @@
#include <string>
#include "load_exception.h"
using namespace std;
LoadException::LoadException(const string & file, int line, const string & reason):
Exception::Base(file, line),
reason(reason){
}
LoadException::LoadException(const std::string & file, int line, const Exception::Base & nested, const std::string & reason):
Exception::Base(file, line, nested),
reason(reason){
}
LoadException::~LoadException() throw (){
}
LoadException::LoadException(const LoadException & copy):
Exception::Base(copy),
reason(copy.reason){
}
Exception::Base * LoadException::copy() const {
return new LoadException(*this);
}
+
+const std::string LoadException::getReason() const {
+ return reason;
+}
diff --git a/util/load_exception.h b/util/load_exception.h
index c28d76a8..4bef6924 100644
--- a/util/load_exception.h
+++ b/util/load_exception.h
@@ -1,31 +1,29 @@
#ifndef _load_exception_h
#define _load_exception_h
#include "exceptions/exception.h"
/* Generic load exception class. Thrown whenever a structure is being created
* and an error occurs.
*/
#include <string>
/* FIXME: put this in the Exception namespace */
class LoadException: public Exception::Base {
public:
LoadException(const std::string & file, int line, const std::string & reason);
LoadException(const std::string & file, int line, const Exception::Base & nested, const std::string & reason);
LoadException(const LoadException & copy);
- inline const std::string & getReason() const {
- return reason;
- }
-
virtual ~LoadException() throw();
protected:
+ virtual const std::string getReason() const;
+
virtual Exception::Base * copy() const;
std::string reason;
};
#endif
diff --git a/util/thread.h b/util/thread.h
index f648b8e3..4206eeb5 100644
--- a/util/thread.h
+++ b/util/thread.h
@@ -1,135 +1,182 @@
#ifndef _paintown_thread_h
#define _paintown_thread_h
#ifdef USE_SDL
#include <SDL_thread.h>
#include <SDL_mutex.h>
#else
#include <pthread.h>
#include <semaphore.h>
#endif
#include "exceptions/exception.h"
+#include "util/load_exception.h"
+#include "util/token_exception.h"
namespace Util{
/* Either uses pthreads or SDL_thread */
namespace Thread{
#ifdef USE_SDL
typedef SDL_mutex* Lock;
typedef SDL_Thread* Id;
typedef int (*ThreadFunction)(void*);
typedef SDL_semaphore* Semaphore;
#else
typedef pthread_mutex_t Lock;
typedef pthread_t Id;
typedef sem_t Semaphore;
typedef void * (*ThreadFunction)(void*);
#endif
void initializeLock(Lock * lock);
void initializeSemaphore(Semaphore * semaphore, unsigned int value);
void destroySemaphore(Semaphore * semaphore);
void semaphoreDecrease(Semaphore * semaphore);
void semaphoreIncrease(Semaphore * semaphore);
int acquireLock(Lock * lock);
int releaseLock(Lock * lock);
void destroyLock(Lock * lock);
bool createThread(Id * thread, void * attributes, ThreadFunction function, void * arg);
void joinThread(Id thread);
void cancelThread(Id thread);
}
class WaitThread{
public:
/* does not start a new thread yet */
WaitThread();
/* starts a thread */
WaitThread(Thread::ThreadFunction thread, void * arg);
/* starts a thread */
void start(Thread::ThreadFunction thread, void * arg);
bool isRunning();
void kill();
virtual ~WaitThread();
public:
/* actually runs the thread */
void doRun();
protected:
Thread::Lock doneLock;
Thread::Id thread;
volatile bool done;
void * arg;
Thread::ThreadFunction function;
};
/* wraps a boolean with lock/unlock while checking/setting it */
class ThreadBoolean{
public:
ThreadBoolean(volatile bool & what, Thread::Lock & lock);
bool get();
void set(bool value);
protected:
volatile bool & what;
Thread::Lock & lock;
};
+/* Computes stuff in a separate thread and gives it back when you ask for it.
+ * As soon as the future is created a thread will start executing and compute
+ * whatever it is that the class is supposed to do. You can then call `get'
+ * on the future object to get the result. If the thread is still executing
+ * then `get' will block until the future completes. If the future has already
+ * completed then `get' will return immediately with the computed value.
+ * The use case is computing something that has to be used later:
+ * Future future; // might take a while to compute
+ * do_stuff_that_takes_a_while(); // future might finish sometime in here
+ * Object o = future.get(); // future is already done
+ *
+ * TODO: handle exceptions
+ */
template<class X>
class Future{
+protected:
+ /* WARNING: hack to find out the type of the exception */
+ enum ExceptionType{
+ None,
+ Load,
+ Token,
+ Base
+ };
+
public:
Future():
- thing(0){
+ thing(0),
+ exception(__FILE__, __LINE__),
+ haveException(None){
/* future will increase the count */
Thread::initializeSemaphore(&future, 0);
}
virtual ~Future(){
Thread::joinThread(thread);
Thread::destroySemaphore(&future);
}
virtual X get(){
+ switch (haveException){
+ case None : break;
+ case Load : throw LoadException(__FILE__, __LINE__, exception, "Failed in future");
+ case Token: throw TokenException(exception);
+ default : throw Exception::Base(__FILE__, __LINE__, exception);
+ }
+
X out;
Thread::semaphoreDecrease(&future);
out = thing;
Thread::semaphoreIncrease(&future);
return out;
}
protected:
static void * runit(void * arg){
Future<X> * me = (Future<X>*) arg;
- me->compute();
- Thread::semaphoreIncrease(&me->future);
+ try{
+ me->compute();
+ Thread::semaphoreIncrease(&me->future);
+ } catch (const LoadException & load){
+ me->haveException = Load;
+ me->exception.set(load);
+ } catch (const TokenException & t){
+ me->haveException = Token;
+ me->exception.set(t);
+ } catch (const Exception::Base & base){
+ me->haveException = Base;
+ me->exception.set(base);
+ }
return NULL;
}
virtual void set(X x){
this->thing = x;
}
virtual void start(){
if (!Thread::createThread(&thread, NULL, (Thread::ThreadFunction) runit, this)){
throw Exception::Base(__FILE__, __LINE__);
}
}
virtual void compute() = 0;
X thing;
Thread::Id thread;
Thread::Semaphore future;
+ /* if any exceptions occur, throw them from `get' */
+ Exception::Base exception;
+ ExceptionType haveException;
};
}
#endif
diff --git a/util/token_exception.cpp b/util/token_exception.cpp
index 56fa888b..7e6df458 100644
--- a/util/token_exception.cpp
+++ b/util/token_exception.cpp
@@ -1,19 +1,24 @@
#include <string>
#include "token_exception.h"
TokenException::TokenException(const std::string & file, int line, const std::string reason):
Exception::Base(file, line),
reason(reason){
}
-
+
TokenException::TokenException(const TokenException & copy):
Exception::Base(copy),
reason(copy.reason){
}
+
+TokenException::TokenException(const Exception::Base & copy):
+Exception::Base(copy),
+reason("unknown"){
+}
Exception::Base * TokenException::copy() const {
return new TokenException(*this);
}
TokenException::~TokenException() throw() {
}
diff --git a/util/token_exception.h b/util/token_exception.h
index 59ca1386..7ea66682 100644
--- a/util/token_exception.h
+++ b/util/token_exception.h
@@ -1,25 +1,25 @@
#ifndef _paintown_token_exception_h
#define _paintown_token_exception_h
#include "exceptions/exception.h"
#include <string>
class TokenException: public Exception::Base {
public:
TokenException(const std::string & file, int line, const std::string reason = "");
+ TokenException(const TokenException & copy);
+ TokenException(const Exception::Base & base);
virtual ~TokenException() throw();
- inline const std::string & getReason() const{
- return reason;
- }
-
- TokenException(const TokenException & copy);
-
protected:
virtual Exception::Base * copy() const;
+ virtual inline const std::string getReason() const {
+ return reason;
+ }
+
std::string reason;
};
#endif
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Jun 11, 12:25 PM (3 w, 4 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
69021
Default Alt Text
(23 KB)
Attached To
Mode
R75 R-Tech1
Attached
Detach File
Event Timeline