Finish agi::Path so we can actually use it, our current path system is brutal and I needed this for libmedia. I'll be adding OS X support shortly: someone else will have to figure out what to do with windows it's completely trivial see unix/path.cpp and check libaegisub/path.h for the return values.

Originally committed to SVN as r5315.
This commit is contained in:
Amar Takhar 2011-02-07 16:39:49 +00:00
parent 7b06c334aa
commit a35962923f
4 changed files with 198 additions and 37 deletions

View file

@ -17,6 +17,7 @@ LDFLAGS += -L../universalchardet -luniversalchardet
endif endif
common/charset_conv.o: CXXFLAGS += $(CFLAGS_ICONV) common/charset_conv.o: CXXFLAGS += $(CFLAGS_ICONV)
unix/path.o: CXXFLAGS += -DDIR_DATA=\"$(P_DATA)\" -DDIR_DOC=\"$(P_DOC)\"
SRC = \ SRC = \
common/charset.cpp \ common/charset.cpp \
@ -27,6 +28,7 @@ SRC = \
common/mru.cpp \ common/mru.cpp \
common/option.cpp \ common/option.cpp \
common/option_visit.cpp \ common/option_visit.cpp \
common/path.cpp \
common/progress.cpp \ common/progress.cpp \
common/keyframe.cpp \ common/keyframe.cpp \
common/log.cpp \ common/log.cpp \
@ -35,7 +37,8 @@ SRC = \
unix/util.cpp \ unix/util.cpp \
unix/io.cpp \ unix/io.cpp \
unix/access.cpp \ unix/access.cpp \
unix/log.cpp unix/log.cpp \
unix/path.cpp
ifeq (yes, $(BUILD_DARWIN)) ifeq (yes, $(BUILD_DARWIN))
SRC += \ SRC += \

View file

@ -1,4 +1,4 @@
// Copyright (c) 2010, Amar Takhar <verm@aegisub.org> // Copyright (c) 2010-2011, Amar Takhar <verm@aegisub.org>
// //
// Permission to use, copy, modify, and distribute this software for any // Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above // purpose with or without fee is hereby granted, provided that the above
@ -18,18 +18,130 @@
/// @brief Common paths. /// @brief Common paths.
/// @ingroup libaegisub /// @ingroup libaegisub
#ifndef LAGI_PRE
#include <vector>
#endif
#include <libaegisub/path.h> #include "libaegisub/access.h"
#include "libaegisub/log.h"
#include "libaegisub/path.h"
namespace agi { namespace agi {
Path::Path(const std::string &file, const std::string& default_path): path_file(file), path_default(default_path) { Path::Path(const std::string &file, const std::string& default_path)
: path_file(file),
path_default(default_path) {
opt = new agi::Options(file, default_path); opt = new agi::Options(file, default_path);
opt->ConfigUser(); opt->ConfigUser();
LOG_D("agi/path") << "New Path object";
} }
Path::~Path() { Path::~Path() {
opt->Flush(); opt->Flush();
} }
const std::string Path::Get(const char *name) {
std::string path;
try {
path = std::string(opt->Get(name)->GetString());
} catch (OptionErrorNotFound& e) {
throw PathErrorNotFound("Invalid path key");
}
Decode(path);
return path;
}
void Path::Set(const char *name, const std::string &path) {
std::string set(path);
if (path[0] == 94) {
std::string tmp(path);
// Check that the used cookie exists.
Decode(tmp);
agi::acs::CheckDirWrite(path);
}
try {
opt->Get(name)->SetString(set);
} catch (OptionErrorNotFound& e) {
throw PathErrorNotFound("Invalid path key");
}
}
void Path::ListGet(const char *name, std::vector<std::string> &out) {
opt->Get(name)->GetListString(out);
}
void Path::ListSet(const char *name, std::vector<std::string> list) {
opt->Get(name)->SetListString(list);
}
const void Path::Decode(std::string &path) {
if (path[0] != 94) // "^"
return;
try {
if (path.find("^CONFIG") == 0) {
path.replace(0, 7, Config());
return;
}
if (path.find("^USER") == 0) {
path.replace(0, 5, User());
return;
}
if (path.find("^DATA") == 0) {
path.replace(0, 5, Data());
return;
}
if (path.find("^DOC") == 0) {
path.replace(0, 4, Doc());
return;
}
if (path.find("^TEMP") == 0) {
path.replace(0, 5, Temp());
return;
}
if (path.find("^AUDIO") == 0) {
std::string path_str(opt->Get("Last/Audio")->GetString());
Decode(path_str);
path.replace(0, 6, path_str);
return;
}
if (path.find("^VIDEO") == 0) {
std::string path_str(opt->Get("Last/Video")->GetString());
Decode(path_str);
path.replace(0, 6, path_str);
return;
}
if (path.find("^SUBTITLE") == 0) {
std::string path_str(opt->Get("Last/Subtitle")->GetString());
Decode(path_str);
path.replace(0, 5, path_str);
return;
}
throw PathErrorInvalid("Invalid cookie used");
} catch (OptionErrorNotFound& e) {
throw PathErrorInternal("Failed to find key in Decode");
}
}
void Path::Encode(std::string &path) {
}
} // namespace agi } // namespace agi

View file

@ -1,4 +1,4 @@
// Copyright (c) 2010, Amar Takhar <verm@aegisub.org> // Copyright (c) 2010-2011, Amar Takhar <verm@aegisub.org>
// //
// Permission to use, copy, modify, and distribute this software for any // Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above // purpose with or without fee is hereby granted, provided that the above
@ -21,14 +21,22 @@
#ifndef AGI_PRE #ifndef AGI_PRE
#endif #endif
#include <libaegisub/exception.h>
#include <libaegisub/option.h> #include <libaegisub/option.h>
namespace agi { namespace agi {
DEFINE_BASE_EXCEPTION_NOINNER(PathError, Exception)
DEFINE_SIMPLE_EXCEPTION_NOINNER(PathErrorNotFound, PathError, "path/not_found")
DEFINE_SIMPLE_EXCEPTION_NOINNER(PathErrorInvalid, PathError, "path/invalid")
DEFINE_SIMPLE_EXCEPTION_NOINNER(PathErrorInternal, PathError, "path")
/// @class Path /// @class Path
// Internal representation of all paths in aegisub. // Internal representation of all paths in aegisub.
class Path { class Path {
public: public:
// For unit testing.
friend class PathTest;
/// Constructor /// Constructor
Path(const std::string &file, const std::string& default_path); Path(const std::string &file, const std::string& default_path);
@ -36,6 +44,37 @@ public:
/// Destructor /// Destructor
~Path(); ~Path();
/// @brief Get a path, this is automatically decoded.
/// @param name Path to get
/// @return Full path name in UTF-8
const std::string Get(const char *name);
/// @brief Set a path, this will be automaticalled encoded if a cookie matches.
/// @param[in] name Path name to save to.
void Set(const char *name, const std::string &path);
/// @brief Set a list of paths
/// @param name Path name.
/// @param out[out] Map to load list into
void ListGet(const char *name, std::vector<std::string> &out);
/// @brief Set a list of paths.
/// @param name Path name.
/// @param list List to set.
void ListSet(const char *name, std::vector<std::string> list);
/// @brief Get the default 'open' directory when no alternative is available.
/// @return Directory
/// This returns several different values based on OS:
/// Windows: Documents folder
/// OS X: ~/Documents
/// Unix: ~ or Documents folder if set in the environment
const std::string Default();
/// @brief Decode a path
/// @param path Decode a path in-place.
const void Decode(std::string &path);
private: private:
/// Location of path config file. /// Location of path config file.
const std::string path_file; const std::string path_file;
@ -43,14 +82,30 @@ private:
/// Internal default config. /// Internal default config.
const std::string path_default; const std::string path_default;
/// @brief Encode a path.
/// @param path Encode a path in-place.
/// ^CONFIG - Configuration directory (not changable)
/// ^USER - Users home directory
/// ^DATA - Aegisub data files
/// ^VIDEO - Last opened video directory
/// ^SUBTITLE - Last opened subtitle directory
/// ^AUDIO - Last opened audio directory
void Encode(std::string &path);
/// Options object. /// Options object.
Options *opt; Options *opt;
const char *Data(); ///< Shared resources /// @brief Locale files
const char *Doc(); ///< Documents /// @return Locale location
const char *User(); ///< User config directory /// This is directly assessibly as the Locale directory will never change on any platform.
const char *Locale(); ///< Locale files const std::string Locale();
const char *Temp(); ///< Temporary storage
protected:
const std::string Data(); ///< Shared resources
const std::string Config(); ///< Configuration directory
const std::string Doc(); ///< Documents
const std::string User(); ///< User config directory
const std::string Temp(); ///< Temporary storage
}; };
} // namespace agi } // namespace agi

View file

@ -1,4 +1,4 @@
// Copyright (c) 2010, Amar Takhar <verm@aegisub.org> // Copyright (c) 2010-2011, Amar Takhar <verm@aegisub.org>
// //
// Permission to use, copy, modify, and distribute this software for any // Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above // purpose with or without fee is hereby granted, provided that the above
@ -18,46 +18,37 @@
/// @brief Common paths. /// @brief Common paths.
/// @ingroup libaegisub /// @ingroup libaegisub
#include "acconf.h" #include "../commit/acconf.h"
#include <string>
#include <libaegisub/path.h> #include <libaegisub/path.h>
namespace agi { namespace agi {
const char *Path::Data() { const std::string Path::Data() {
std::string tmp; return DIR_DATA;
tmp.assign(INSTALL_PREFIX);
tmp.append("-");
tmp.append(AEGISUB_VERSION_DATA);
return tmp.c_str();
} }
const char *Path::Doc() { const std::string Path::Doc() {
std::string tmp; return DIR_DOC;
tmp.assign(INSTALL_PREFIX);
tmp.append("-");
tmp.append(AEGISUB_VERSION_DATA);
return tmp.c_str();
} }
const char *Path::User() { const std::string Path::User() {
std::string tmp; return "~/";
tmp.assign("~/.aegisub-");
tmp.append(AEGISUB_VERSION_DATA);
return tmp.c_str();
} }
const char *Path::Locale() { const std::string Path::Locale() {
std::string tmp; std::string tmp("~/.aegisub-");
tmp.assign("~/.aegisub-"); return tmp.append(AEGISUB_VERSION_DATA);
tmp.append(AEGISUB_VERSION_DATA);
return tmp.c_str();
} }
const std::string Path::Config() {
std::string tmp("~/.aegisub-");
return tmp.append(AEGISUB_VERSION_DATA);
}
const char *Path::Temp() { const std::string Path::Temp() {
const char *tmp = "/tmp"; return "/tmp/";
return tmp;
} }
} // namespace agi } // namespace agi