From f736d81cd80aca54a2ebbe3efeb8cec6a265a3f2 Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Tue, 15 Jan 2013 20:37:34 -0800 Subject: [PATCH] Convert plFileName to "has-a" model for better semantics. You're welcome, branan ;) --- Sources/Plasma/CoreLib/hsStream.h | 3 +- Sources/Plasma/CoreLib/plString.cpp | 77 ++++++++++++++++++----------- Sources/Plasma/CoreLib/plString.h | 50 +++++++++++++++++-- 3 files changed, 96 insertions(+), 34 deletions(-) diff --git a/Sources/Plasma/CoreLib/hsStream.h b/Sources/Plasma/CoreLib/hsStream.h index 09dc7c79..b7980289 100644 --- a/Sources/Plasma/CoreLib/hsStream.h +++ b/Sources/Plasma/CoreLib/hsStream.h @@ -84,7 +84,8 @@ public: virtual ~hsStream() { } // Pre-filename-stringification shortcut: - bool Open_TEMP(const plFileName & filename, const char * mode = "rb") { return Open(filename.c_str(), mode); } + bool Open_TEMP(const plFileName & filename, const char * mode = "rb") + { return Open(filename.AsString().c_str(), mode); } virtual bool Open(const char *, const char * = "rb")=0; virtual bool Open(const wchar_t *, const wchar_t * = L"rb")=0; diff --git a/Sources/Plasma/CoreLib/plString.cpp b/Sources/Plasma/CoreLib/plString.cpp index 3693973c..5f390933 100644 --- a/Sources/Plasma/CoreLib/plString.cpp +++ b/Sources/Plasma/CoreLib/plString.cpp @@ -880,88 +880,107 @@ size_t ustrlen(const UniChar *ustr, size_t max) /* plFileName */ +static_assert(sizeof(plFileName) == sizeof(plString), + "plFileName should be a thin wrapper around plString"); + plString plFileName::GetFileName() const { - int end = FindLast('/'); + int end = fName.FindLast('/'); if (end < 0) - end = FindLast('\\'); + end = fName.FindLast('\\'); if (end < 0) - return *this; + return fName; - return Substr(end + 1); + return fName.Substr(end + 1); } plString plFileName::GetFileExt() const { - int dot = FindLast('.'); + int dot = fName.FindLast('.'); // Be sure not to get a dot in the directory! - int end = FindLast('/'); + int end = fName.FindLast('/'); if (end < 0) - end = FindLast('\\'); + end = fName.FindLast('\\'); if (dot > end) - return Substr(dot + 1); + return fName.Substr(dot + 1); return plString::Null; } plString plFileName::GetFileNameNoExt() const { - int dot = FindLast('.'); + int dot = fName.FindLast('.'); - int end = FindLast('/'); + int end = fName.FindLast('/'); if (end < 0) - end = FindLast('\\'); + end = fName.FindLast('\\'); // Be sure not to get a dot in the directory! if (dot > end) - return Substr(end + 1, dot - end - 1); - return Substr(end + 1); + return fName.Substr(end + 1, dot - end - 1); + return fName.Substr(end + 1); } plFileName plFileName::StripFileName() const { - int end = FindLast('/'); + int end = fName.FindLast('/'); if (end < 0) - end = FindLast('\\'); + end = fName.FindLast('\\'); if (end < 0) return *this; - return Left(end); + return fName.Left(end); } plFileName plFileName::StripFileExt() const { - int dot = FindLast('.'); + int dot = fName.FindLast('.'); // Be sure not to get a dot in the directory! - int end = FindLast('/'); + int end = fName.FindLast('/'); if (end < 0) - end = FindLast('\\'); + end = fName.FindLast('\\'); if (dot > end) - return Left(dot); + return fName.Left(dot); return *this; } +plFileName plFileName::Normalize(char slash) const +{ + plStringBuffer norm; + char *norm_p = norm.CreateWritableBuffer(fName.GetSize()); + for (const char *p = fName.c_str(); *p; ++p) { + if (*p == '/' || *p == '\\') + *norm_p++ = slash; + else + *norm_p++ = *p; + } + *norm_p = 0; + return plString(norm); +} + plFileName plFileName::Join(const plFileName &base, const plFileName &path) { - if (base.IsEmpty()) + if (!base.IsValid()) return path; - if (path.IsEmpty()) + if (!path.IsValid()) return base; - char last = base.CharAt(base.GetSize() - 1); - char first = path.CharAt(0); + char last = base.fName.CharAt(base.GetSize() - 1); + char first = path.fName.CharAt(0); if (last != '/' && last != '\\') { - if (first != '/' && first != '\\') - return plString::Format("%s" PATH_SEPARATOR_STR "%s", base.c_str(), path.c_str()); - return base + path; + if (first != '/' && first != '\\') { + return plString::Format("%s" PATH_SEPARATOR_STR "%s", + base.fName.c_str(), path.fName.c_str()); + } + return base.fName + path.fName; } else if (first != '/' && first != '\\') { - return base + path; + return base.fName + path.fName; } // Both have a slash, but we only need one - return base + path.Substr(1); + return base.fName + path.fName.Substr(1); } diff --git a/Sources/Plasma/CoreLib/plString.h b/Sources/Plasma/CoreLib/plString.h index f596d894..410315cd 100644 --- a/Sources/Plasma/CoreLib/plString.h +++ b/Sources/Plasma/CoreLib/plString.h @@ -672,20 +672,52 @@ size_t ustrlen(const UniChar *ustr, size_t max = plString::kSizeAuto); /** Subclass of plString with specific methods to help deal with common * filename manipulation tasks. */ -class plFileName : public plString +class plFileName { public: /** Construct an empty filename. */ plFileName() { } /** Construct a filename from the UTF-8 character data in \a cstr. */ - plFileName(const char *cstr) : plString(cstr) { } + plFileName(const char *cstr) : fName(cstr) { } /** Construct a filename from the plString argument \a copy. */ - plFileName(const plString ©) : plString(copy) { } + plFileName(const plString ©) : fName(copy) { } /** Copy constructor. */ - plFileName(const plFileName ©) : plString(copy) { } + plFileName(const plFileName ©) : fName(copy.fName) { } + + /** Assignment operator. Same as plFileName(const char *). */ + plFileName &operator=(const char *cstr) + { + fName.operator=(cstr); + return *this; + } + + /** Assignment operator. Same as plFileName(const plString &). */ + plFileName &operator=(const plString ©) + { + fName.operator=(copy); + return *this; + } + + /** Assignment operator. Same as plFileName(const plFileName &). */ + plFileName &operator=(const plFileName ©) + { + fName.operator=(copy.fName); + return *this; + } + + /** Return whether this filename is valid (not empty). */ + bool IsValid() const { return !fName.IsEmpty(); } + + /** Return the length of the filename string (UTF-8). */ + size_t GetSize() const { return fName.GetSize(); } + + /** Convert the filename to a string. This does not resolve relative + * paths or normalize slashes, it just returns the stored name string. + */ + const plString &AsString() const { return fName; } /** Return the name portion of the path (including extension). * For example: @@ -717,6 +749,13 @@ public: */ plFileName StripFileExt() const; + /** Normalize slashes to a particular format. By default, we use the + * OS's native slash format. + * For example: + *
plFileName("C:\\Path/Filename.ext").Normalize("\\") => "C:\\Path\\Filename.ext"
+ */ + plFileName Normalize(char slash = PATH_SEPARATOR) const; + /** Join two path components together with the correct path separator. * For example: *
plFileName::Join("C:\\Path", "Filename.ext") => "C:\\Path\\Filename.ext"
@@ -736,6 +775,9 @@ public: static plFileName Join(const plFileName &base, const plFileName &path, const plFileName& path2, const plFileName &path3) { return Join(Join(Join(base, path), path2), path3); } + +private: + plString fName; }; #endif //plString_Defined