ALib C++ Framework
by
Library Version: 2605 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
path.hpp
Go to the documentation of this file.
1//==================================================================================================
2/// \file
3/// This header-file is part of module \alib_system of the \aliblong.
4///
5/// Copyright 2013-2026 A-Worx GmbH, Germany.
6/// Published under #"mainpage_license".
7//==================================================================================================
8ALIB_EXPORT namespace alib {
9
10/// The character type that this \alibmod_nl uses for String representations.
11/// This is taken from the C++ standard library.
12using PathCharType = std::filesystem::path::value_type;
13
14#if !defined(ALIB_PATH_CHARACTERS_WIDE)
15# if defined(_WIN32)
16 static_assert(std::same_as<PathCharType, characters::wchar>,
17 "Configuration macro ALIB_PATH_CHARACTERS_WIDE wrongly detected: 1 but std::filesystem::path::value_type does not equal characters::wchar.");
18# else
19 static_assert(std::same_as<PathCharType, characters::nchar>,
20 "Configuration macro ALIB_PATH_CHARACTERS_WIDE wrongly detected: 0 but std::filesystem::path::value_type does not equal characters::nchar.");
21# endif
22#else
23# if ALIB_PATH_CHARACTERS_WIDE
24 static_assert(std::same_as<PathCharType, characters::wchar>,
25 "Given configuration macro ALIB_PATH_CHARACTERS_WIDE mismatch: Given 1 but std::filesystem::path::value_type does not equal characters::wchar.");
26# else
27 static_assert(std::same_as<PathCharType, characters::nchar>,
28 "Given configuration macro ALIB_PATH_CHARACTERS_WIDE mismatch: Given 0 but std::filesystem::path::value_type does not equal characters::nchar.");
29# endif
30#endif
31
32
33/// The string-type used with this \alibmod_nl.
35
36/// The string-type used with this \alibmod_nl.
38
39/// The string-type used with this \alibmod_nl.
41
42#if ALIB_MONOMEM
43/// A mono-allocated string representing a path.
45
46/// A pool-allocated string representing a path.
48#endif
49
50#if DOXYGEN
51/// A nulled path string.
52inline constexpr PathString NULL_PATH;
53
54/// An empty path string.
55inline constexpr PathString EMPTY_PATH;
56#else
57inline constexpr PathString NULL_PATH(nullptr);
58inline constexpr PathString EMPTY_PATH(A_PATH(""));
59#endif
60
61#if !defined( _WIN32 ) || DOXYGEN
62 /// The standard path separator character. Defaults to '\\' on Windows OS, '/' else.
63 inline constexpr PathCharType DIRECTORY_SEPARATOR = '/';
64#else
65 inline constexpr PathCharType DIRECTORY_SEPARATOR = '\\';
66#endif
67
68
69namespace system {
70
71//##################################################################################################
72// MacOS System call wrappers (implemented in Objective-C)
73//##################################################################################################
74#if defined(__APPLE__)
75class Path;
76namespace macos {
77 void ALIB_APPLE_OC_NSTemporaryDirectory( Path& target );
78 void ALIB_APPLE_OC_NSHomeDirectory ( Path& target );
79}
80#endif
81
82//==================================================================================================
83/// Enumerates special system folders like "home", "temp", "config", etc.
84/// This enumeration is primarily used with class #"system::Path" and this documentation
85/// refers to this type.
86//==================================================================================================
87enum class SystemFolders {
88 /// The root directory .
90
91 /// The current directory of the process.
93
94 /// The user's home directory
96
97 /// The user's configuration directory. This is evaluated as follows:
98 /// - Using environment variable \e HOME (under WindowsOS a combination of \e HOMEDRIVE
99 /// and \e HOMEPATH), the home directory is determined.
100 /// - If within this directory \e ".config" exists, it is used, otherwise
101 /// - if within this directory the directories \e "AppData/Roaming" exist, this is used.
103
104 /// The directory of the executable of the process.
106
107 /// A directory to be used for creation of temporary files.
108 ///
109 /// - On GNU/Linux OS this defaults to <c>/tmp</c>.
110 /// - On Windows OS, environment variables "TMP" and "TEMP" are evaluated.<br>
111 ///
112 /// If the directory does not exist, then (on all OS), a new directory named \c ".tmp"
113 /// is created in the user's home directory and returned (if not existent already).
114 /// If this fails, the home directory itself is returned.
115 ///
116 /// \note With the potential creation of the directory \c ".tmp" in the user's home
117 /// directory, a small \c readme.txt file is created containing the name of
118 /// the running application and the reason of the creation.
119 ///
120 /// To overrule this behavior, public static variable
121 /// #"Path::tempDirEvaluatedOnce;*" may be set arbitrarily before using this
122 /// enum value.
124
125 /// A directory to be used for creation of temporary files that survives reboots of the
126 /// host machine.
127 ///
128 /// - On GNU/Linux OS this defaults to <c>/var/tmp</c>.
129 /// - On Windows OS, environment variables "TMP" and "TEMP" are evaluated (same as
130 /// with #"%SystemFolders::Temp").<br>
131 ///
132 /// If the directory does not exist, then (on all OS), a new directory named \c ".var.tmp"
133 /// is created in the user's home directory and returned (if not existent already).
134 /// If this fails, the home directory itself is returned.
135 ///
136 /// \note With the potential creation of the directory \c ".var.tmp" in the user's home
137 /// directory, a small \c readme.txt file is created, containing the name of
138 /// the running application and the reason of the creation.
139 ///
140 /// To overrule this behavior, public static variable
141 /// #"Path::varTempDirEvaluatedOnce;*" may be set arbitrarily before using this
142 /// enum value.
144};
145
146
147//==================================================================================================
148/// Represents a directory or file in a file system.
149///
150/// Inherits a local string buffer fixed to size 256. The flexible nature of \alib
151/// #"TLocalString;local strings" allows dynamic allocation if this should be exceeded
152/// (which usually is not expected with paths).
153///
154/// The character type of templated parent class #"%AString" is defined by the type definition
155/// #"PathCharType;2", which in turn aliases <c>std::filesystem::path::value_type</c>.
156//==================================================================================================
157class Path : public strings::TLocalString<PathCharType, 256> {
158 //################################################################################################
159 // Fields
160 //################################################################################################
161 public:
162 /// Singleton containing the path for the use of enum value
163 /// #"SystemFolders::Temp;*".
164 /// This is evaluated once with the first use of #"%SystemFolders::Temp".
165 /// To change the default behavior of evaluation, this variable may be filled with a proper
166 /// path before using enum #"%SystemFolders::Temp" with this class.
167 ///
168 /// The one-time evaluated value is stored in the #"GLOBAL_ALLOCATOR" and
169 /// access to this variable is consequently protected with #"GLOBAL_ALLOCATOR_LOCK".
171
172 /// Singleton containing the path for the use of enum value
173 /// #"SystemFolders::VarTemp;*".
174 /// This is evaluated once with the first use of #"%SystemFolders::VarTemp".
175 /// To change the default behavior of evaluation, this variable may be filled with a proper
176 /// path before using enum #"%SystemFolders::VarTemp" with this class.
177 ///
178 /// The one-time evaluated value is stored in the #"GLOBAL_ALLOCATOR" and
179 /// access to this variable is consequently protected with #"GLOBAL_ALLOCATOR_LOCK".
181
182 //################################################################################################
183 // Constructors
184 //################################################################################################
185 public:
187
188 /// Constructs an object representing no directory.
189 /// Field #"Path" remains empty.
190 Path() {}
191
192 /// Constructs an object representing one of the known special directories.
193 /// @param special The special directory to initialize this instance to.
194 Path( SystemFolders special ) { Change( special ); }
195
196 /// Constructs an object representing one of the known special directories.
197 /// @param special The special directory to initialize this instance to.
198 /// @param fileName The filename in folder \p{special}.
199 Path( SystemFolders special, const PathString& fileName ) { Change( special ); Add(fileName); }
200
201 /// Constructs an object representing the given path.
202 /// @param path The initial path.
203 Path( const PathString& path )
204 : strings::TLocalString<PathCharType, 256>(path) {}
205
206
207 //################################################################################################
208 // Interface
209 //################################################################################################
210 public:
211 /// Creates the directory of the given \p{path}. If a relative path is given, then
212 /// it is appended to the currently stored path, otherwise the current path is replaced.
213 /// @param path Zero-terminated string defining the path to test.
214 /// @return A value of enum type \c std::errc.
216 std::errc Create( const PathString& path );
217
218 /// Creates the directory represented by this object by invoking #".Create(const PathString&)"
219 /// passing an empty String.
220 /// @return A value of enum type \c std::errc.
222 std::errc Create() { return Create(EMPTY_PATH); }
223
224 /// Changes the directory. If the given path is absolute and valid, this objects' content is
225 /// replaced. Otherwise, it is tested if the current combined path string is a directory,
226 /// and if so, the given \p{path} is appended.
227 /// If the resulting destination directory is not valid, \c false is returned and this
228 /// object is not changed.
229 /// @param path The relative or absolute path to change to.
230 /// @returns \c true if the change was successful and this instance was changed, \c false
231 /// otherwise.
232 ALIB_DLL bool Change( const PathString& path );
233
234 /// Changes the directory to one of the known special directories.
235 /// @param special The special directory to change this instance to.
236 /// @returns \c true if the change was successful, \c false otherwise.
237 ALIB_DLL bool Change( SystemFolders special );
238
239 /// Changes the directory to one of the known special directories and adds the given
240 /// \p{fileName} to this path.
241 /// @param special The special directory to change this instance to.
242 /// @param fileName The filename within \p{special}.
243 inline void Change( SystemFolders special, const PathString& fileName )
244 {
245 Change( special );
246 Add(fileName);
247 }
248
249 /// In the case of directories, this path is set to the parent directory.
250 /// In the case of files, the file name is removed from the path.
251 ///
252 /// If the resulting destination directory is not valid, \c false is returned and this
253 /// object is not changed.
254 /// @returns \c true if the change was successful, \c false otherwise.
255 /// I.e., in case this object represented the root folder \c false is returned.
257
258
259 /// Adds a directory or filename to the internal string. If the current string does not
260 /// end with a #"DIRECTORY_SEPARATOR;2", one will be inserted first.
261 ///
262 /// @param dirOrFilename The path component to add.
263 /// @return \c *this to allow concatenated operations.
264 inline Path& Add( const PathString& dirOrFilename ) {
267 _(dirOrFilename);
268 return *this;
269 }
270
271 /// Adds this processes' module name to the currently stored folder path.
272 ///
273 /// @param extension An additional extension string that is added to the evaluated file
274 /// name, for example, <c>".jpg"</c>.
275 ALIB_DLL void AddModuleName( const PathString& extension );
276
277 /// Tests if this path represents an existing directory in the file system.
278 /// @return \c true if a directory was found, \c false if not found or the path represents
279 /// a file.
281 bool IsDirectory();
282
283 /// Tests if this path represents an existing file or directory in the file system.
284 /// @return \c true if this path represents an existing file or directory, \c false otherwise.
286 bool Exists();
287
288 /// Gets the name portion of the path.
289 /// @returns A string containing the characters after the last directory separator.
290 PathString Name() const {
292 if( idx < 0 )
293 return *this;
294 return Substring(idx + 1);
295 }
296
297 /// In the case of directories, the path string to the parent directory is returned.
298 /// In the case of files, the directory that the file resides in is returned.
299 /// @returns A string containing the characters from the start to the last directory
300 /// separator. If the currently stored string ends with a separator, this is
301 /// returned first.
303 integer startIdx= length;
304 if ( CharAtEnd() == DIRECTORY_SEPARATOR ) {
305 if ( startIdx == 1 )
306 return *this;
307 --startIdx;
308 }
309
310 integer lastDirSep= LastIndexOf(DIRECTORY_SEPARATOR, startIdx);
311 if (lastDirSep==0)
312 ++lastDirSep;
313 return Substring(0, lastDirSep );
314 }
315
316 /// Resolves the path by removing all symbolic links and relative addressing.
317 /// @return <c>std::errc(0)</c> on success, otherwise an error code.
319 std::errc MakeCanonical();
320
321 /// Invokes static overloaded method #"IsUNCPath(const PathString&)", passing this object.
322 /// @returns \c true if the given \p{path} is a UNC path, \c false otherwise.
323 /// On non-WindowsOS systems, this method always returns \c false,
324 bool IsUNCPath() const {
325 #if !defined(_WIN32)
326 return false;
327 #endif
328 return IsUNCPath(*this);
329 }
330
331 /// Determines if the given string contains a path that uses
332 /// \https{UNC addressing,en.wikipedia.org/wiki/Path_(computing)#UNC}.
333 /// @param path The path to check for UNC-addressing.
334 /// @returns \c true if the given \p{path} is absolute, \c false otherwise.
335 static
336 bool IsUNCPath(const PathString& path) {
337 #if !defined(_WIN32)
338 (void) path;
339 return false;
340 #else
341 if (path.size() < 5)
342 return false;
343
344 if (path[0] != '\\' || path[1] != '\\')
345 return false;
346
347 // Need \\server\share at minimum.
348 integer serverStart = 2;
349 integer end = path.IndexOf('\\', serverStart);
350 if (end <=2 )
351 return false;
352
353 end++;
354 return path.IndexOf('\\', end) <= end;
355 #endif
356 }
357
358 /// Invokes static overloaded method #"IsAbsolute(const PathString&)", passing this object.
359 /// @returns \c true if the given \p{path} is absolute, \c false otherwise.
360 bool IsAbsolute() const { return IsAbsolute(*this); }
361
362 /// Determines if the given string contains a path/filename with absolute addressing or
363 /// not.
364 /// @param path The path to check for absolute addressing.
365 /// @returns \c true if the given \p{path} is absolute, \c false otherwise.
366 static bool IsAbsolute( const PathString& path ) {
367 #if !defined(_WIN32)
368 return path.CharAtStart() == '/' || path.CharAtStart() == '\\';
369 #else
370 if ( path.size() >= 3
371 && ((path[0] >= 'A' && path[0] <= 'Z') || (path[0] >= 'a' && path[0] <= 'z') )
372 && path[1] == ':'
373 && (path[2] == '\\' || path[2] == '/') )
374 return true;
375
376 if (IsUNCPath(path))
377 return true;
378
379 return false;
380 #endif
381 }
382
383 /// Changes the path to an absolute path, in case it #".IsAbsolute();is not yet one".
384 /// This function does \b not create a canonical path like #".MakeCanonical" does.
385 /// On non-WindowsOS systems, if not absolute, the current working directory
386 /// is set and the current content is appended (separated by #"%DIRECTORY_SEPARATOR;2").
387 /// Under Windows OS function \b GetFullPathNameW is used, which allows to reflect
388 /// the current directory per drive letter, if, for example, <c>"D:mysubdir"</c> is given.
390 void MakeAbsolute();
391
392}; //class Path
393
394// Note(25/01/17):
395// Clang strangely did not find the following templated operators when they resided in an
396// exported namespace.
397// The workaround was to not export the namespace but export each operator instead.
398// We think this is wrong behavior and not aligned with the language specification.
399#if !DOXYGEN
400}} namespace alib::system {
401
403inline bool operator== (const Path& lhs, const Path& rhs)
404{ return lhs. template Equals <CHK, lang::Case::Sensitive>(rhs); }
405
407inline auto operator<=> (const Path& lhs, const Path& rhs)
408{ return lhs. template CompareTo<CHK, lang::Case::Sensitive>(rhs); }
409
410
411} ALIB_EXPORT namespace alib { namespace system {
412#endif // DOXYGEN
413
414} // namespace alib[::system]
415
416/// Type alias in namespace #"%alib".
418
419/// Type alias in namespace #"%alib".
421
422
423//##################################################################################################
424// Specializations of ZTArrayTraits for class Path
425//##################################################################################################
426#if !DOXYGEN
427namespace characters {
428template<>
429struct ZTArrayTraits<system::Path, PathCharType>
430{
431 static constexpr Policy Access = Policy::Implicit;
432 static constexpr Policy Construction = Policy::NONE;
433 static constexpr const PathCharType* Buffer(const system::Path& src) { return src.Terminate(); }
434 static constexpr integer Length(const system::Path& src) { return src.Length(); }
435};
436}// namespace alib[::characters]
437#endif //!DOXYGEN
438
439} // namespace [alib]
440
#define ALIB_DLL
#define ALIB_EXPORT
#define ALIB_BOXING_VTABLE_DECLARE(TMapped, Identifier)
constexpr const TChar * Terminate() const
Definition tastring.hpp:614
constexpr TLocalString(lang::HeapAllocator &pAllocator)
constexpr integer Length() const
Definition string.hpp:300
TChar CharAtStart() const
Definition string.hpp:417
integer IndexOf(TChar needle, integer startIdx=0) const
Definition string.hpp:799
integer LastIndexOf(PathCharType needle, integer startIndex=MAX_LEN) const
Definition string.hpp:909
size_type size() const
Definition string.hpp:1977
bool IsAbsolute() const
Definition path.hpp:360
Path(SystemFolders special, const PathString &fileName)
Definition path.hpp:199
std::errc MakeCanonical()
Definition path.cpp:445
static PathString varTempDirEvaluatedOnce
Definition path.hpp:180
bool IsUNCPath() const
Definition path.hpp:324
Path & Add(const PathString &dirOrFilename)
Definition path.hpp:264
PathString Parent() const
Definition path.hpp:302
Path(SystemFolders special)
Definition path.hpp:194
PathString Name() const
Definition path.hpp:290
void AddModuleName(const PathString &extension)
Definition path.cpp:356
bool IsDirectory()
Definition path.cpp:416
static bool IsAbsolute(const PathString &path)
Definition path.hpp:366
static bool IsUNCPath(const PathString &path)
Definition path.hpp:336
Path(const PathString &path)
Definition path.hpp:203
void MakeAbsolute()
Definition path.cpp:508
bool ChangeToParent()
Definition path.cpp:392
void Change(SystemFolders special, const PathString &fileName)
Definition path.hpp:243
std::errc Create()
Definition path.hpp:222
bool Change(const PathString &path)
Definition path.cpp:370
static PathString tempDirEvaluatedOnce
Definition path.hpp:170
#define ALIB_ENUMS_ASSIGN_RECORD(TEnum, TRecord)
@ Current
The current directory of the process.
Definition path.hpp:92
@ Home
The user's home directory.
Definition path.hpp:95
@ Module
The directory of the executable of the process.
Definition path.hpp:105
@ Root
The root directory .
Definition path.hpp:89
Definition alox.cpp:14
system::SystemFolders SystemFolders
Type alias in namespace #"%alib".
Definition path.hpp:420
lang::integer integer
Type alias in namespace #"%alib".
Definition integers.hpp:149
strings::TAString< PathCharType, PoolAllocator > PathStringMA
A mono-allocated string representing a path.
Definition path.hpp:44
system::Path Path
Type alias in namespace #"%alib".
Definition path.hpp:417
strings::TCString< PathCharType > CPathString
The string-type used with this ALib Module.
Definition path.hpp:37
constexpr PathString NULL_PATH
A nulled path string.
Definition path.hpp:52
strings::TSubstring< character > Substring
Type alias in namespace #"%alib".
strings::TAString< PathCharType, PoolAllocator > PathStringPA
A pool-allocated string representing a path.
Definition path.hpp:47
strings::TString< PathCharType > PathString
The string-type used with this ALib Module.
Definition path.hpp:34
std::filesystem::path::value_type PathCharType
Definition path.hpp:12
constexpr PathCharType DIRECTORY_SEPARATOR
The standard path separator character. Defaults to '\' on Windows OS, '/' else.
Definition path.hpp:63
strings::TSubstring< PathCharType > PathSubstring
The string-type used with this ALib Module.
Definition path.hpp:40
constexpr PathString EMPTY_PATH
An empty path string.
Definition path.hpp:55
#define A_PATH(literal)