ALib C++ Framework
by
Library Version: 2511 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
path.inl
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/// \emoji :copyright: 2013-2025 A-Worx GmbH, Germany.
6/// Published under #"mainpage_license".
7//==================================================================================================
8ALIB_EXPORT namespace alib { namespace system {
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/// The string-type used with this \alibmod_nl.
34
35/// The string-type used with this \alibmod_nl.
37
38/// The string-type used with this \alibmod_nl.
40
41#if ALIB_MONOMEM
42/// A mono-allocated string representing a path.
44
45/// A pool-allocated string representing a path.
47#endif
48
49#if DOXYGEN
50/// A nulled path string.
51inline constexpr PathString NULL_PATH;
52
53/// An empty path string.
54inline constexpr PathString EMPTY_PATH;
55#else
56inline constexpr PathString NULL_PATH(nullptr);
57inline constexpr PathString EMPTY_PATH(A_PATH(""));
58#endif
59
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//##################################################################################################
69// MacOS System call wrappers (implemented in Objective-C)
70//##################################################################################################
71#if defined(__APPLE__)
72class Path;
73namespace macos
74{
75 void ALIB_APPLE_OC_NSTemporaryDirectory( Path& target );
76 void ALIB_APPLE_OC_NSHomeDirectory ( Path& target );
77}
78#endif
79
80//==================================================================================================
81/// Enumerates special system folders like "home", "temp", "config", etc.
82/// This enumeration is primarily used with class #"system::Path" and this documentation
83/// refers to this type.
84//==================================================================================================
85enum class SystemFolders
86{
87 /// The root directory .
89
90 /// The current directory of the process.
92
93 /// The user's home directory
95
96 /// The user's configuration directory. This is evaluated as follows:
97 /// - Using environment variable \e HOME (under WindowsOS a combination of \e HOMEDRIVE
98 /// and \e HOMEPATH), the home directory is determined.
99 /// - If within this directory \e ".config" exists, it is used, otherwise
100 /// - if within this direcotory the directories \e "AppData/Roaming" exist, this is used.
102
103 /// The directory of the executable of the process.
105
106 /// A directory to be used for creation of temporary files.
107 ///
108 /// - On GNU/Linux OS this defaults to <c>/tmp</c>.
109 /// - On Windows OS, environment variables "TMP" and "TEMP" are evaluated.<br>
110 ///
111 /// If the directory does not exist, then (on all OS), a new directory named \c ".tmp"
112 /// is created in the user's home directory and returned (if not existent already).
113 /// If this fails, the home directory itself is returned.
114 ///
115 /// \note With the potential creation of the directory \c ".tmp" in the user's home
116 /// directory, a small \c readme.txt file is created containing the name of
117 /// the running application and the reason of the creation.
118 ///
119 /// To overrule this behavior, public static variable
120 /// #"Path::tempDirEvaluatedOnce;*" may be set arbitrarily before using this
121 /// enum value.
123
124 /// A directory to be used for creation of temporary files that survives reboots of the
125 /// host machine.
126 ///
127 /// - On GNU/Linux OS this defaults to <c>/var/tmp</c>.
128 /// - On Windows OS, environment variables "TMP" and "TEMP" are evaluated (same as
129 /// with \b %SystemFolders::Temp).<br>
130 ///
131 /// If the directory does not exist, then (on all OS), a new directory named \c ".var.tmp"
132 /// is created in the user's home directory and returned (if not existent already).
133 /// If this fails, the home directory itself is returned.
134 ///
135 /// \note With the potential creation of the directory \c ".var.tmp" in the user's home
136 /// directory, a small \c readme.txt file is created, containing the name of
137 /// the running application and the reason of the creation.
138 ///
139 /// To overrule this behavior, public static variable
140 /// #"Path::varTempDirEvaluatedOnce;*" may be set arbitrarily before using this
141 /// enum value.
143};
144
145
146//==================================================================================================
147/// Represents a directory or file in a file system.
148///
149/// Inherits a local string buffer fixed to size 256. The flexible nature of \alib
150/// #"TLocalString;local strings" allows dynamic allocation if this should be exceeded
151/// (which usually is not expected with paths).
152///
153/// The character type of templated parent class \b AString is defined by the type definition
154/// #"system::PathCharType;2", which in turn aliases <c>std::filesystem::path::value_type</c>.
155//==================================================================================================
156class Path : public strings::TLocalString<PathCharType, 256>
157{
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 \b %SystemFolders::Temp.
165 /// To change the default behavior of evaluation, this variable may be filled with a proper
166 /// path before using enum \b %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 \b %SystemFolders::VarTemp.
175 /// To change the default behavior of evaluation, this variable may be filled with a proper
176 /// path before using enum \b %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 relative (e.g., a name of a subdirectory
225 /// or ".."), such path is added to the current #"Path". Otherwise, this objects' path
226 /// string is replaced.
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, \c false otherwise.
231 ALIB_DLL bool Change( const PathString& path );
232
233 /// Changes the directory to one of the known special directories.
234 /// @param special The special directory to change this instance to.
235 /// @returns \c true if the change was successful, \c false otherwise.
236 ALIB_DLL bool Change( SystemFolders special );
237
238 /// Changes the directory to one of the known special directories and adds the given
239 /// \p{fileName} to this path.
240 /// @param special The special directory to change this instance to.
241 /// @param fileName The filename within \p{special}.
242 inline void Change( SystemFolders special, const PathString& fileName )
243 {
244 Change( special );
245 Add(fileName);
246 }
247
248 /// In the case of directories, this path is set to the parent directory.
249 /// In the case of files, the file name is removed from the path.
250 ///
251 /// If the resulting destination directory is not valid, \c false is returned and this
252 /// object is not changed.
253 /// @returns \c true if the change was successful, \c false otherwise.
254 /// I.e., in case this object represented the root folder \c false is returned.
256
257
258 /// Adds a directory or filename to the internal string. If the current string does not
259 /// end with a #"DIRECTORY_SEPARATOR", one will be inserted first.
260 ///
261 /// @param dirOrFilename The path component to add.
262 /// @return \c *this to allow concatenated operations.
263 inline Path& Add( const PathString& dirOrFilename ) {
266 _(dirOrFilename);
267 return *this;
268 }
269
270 /// Adds this processes' module name to the currently stored folder path.
271 ///
272 /// @param extension An additional extension string that is added to the evaluated file
273 /// name, for example, <c>".jpg"</c>.
274 ALIB_DLL void AddModuleName( const PathString& extension );
275
276 /// Tests if this path represents an existing directory in the file system.
277 /// @return \c true if a directory was found, \c false if not found or the path represents
278 /// a file.
280 bool IsDirectory();
281
282 /// Invokes static overload of this method, passing this object.
283 /// @returns The result of a call to #"IsAbsolute(const" PathString&).
284 int IsAbsolute() const { return IsAbsolute(*this); }
285
286 /// Gets the name portion of the path.
287 /// @returns A string containing the characters after the last directory separator.
288 PathString Name() const {
290 if( idx < 0 )
291 return *this;
292 return Substring(idx + 1);
293 }
294
295 /// In the case of directories, the path string to the parent directory is returned.
296 /// In the case of files, the directory that the file resides in is returned.
297 /// @returns A string containing the characters from the start to the last directory
298 /// separator. If the currently stored string ends with a separator, this is
299 /// returned first.
301 integer startIdx= length;
302 if ( CharAtEnd() == DIRECTORY_SEPARATOR ) {
303 if ( startIdx == 1 )
304 return *this;
305 --startIdx;
306 }
307
308 integer lastDirSep= LastIndexOf(DIRECTORY_SEPARATOR, startIdx);
309 if (lastDirSep==0)
310 ++lastDirSep;
311 return Substring(0, lastDirSep );
312 }
313
314 /// Resolves the path by removing all symbolic links and relative addressing.
315 /// @return <c>std::errc(0)</c> on success, otherwise an error code.
317 std::errc MakeCanonical();
318
319 /// Determines if the given string contains a path/filename with absolute addressing or
320 /// not.
321 /// \attention This method must be invoked on "real path strings" only. Assembled paths
322 /// which contain redundant slashes return a false result.
323 /// @param path The relative or absolute path to check.
324 /// @returns \c 0 if \p{path} is relative. If absolute, the position of the first character
325 /// that does not belong to the root symbol. For example, with windows OS, if
326 /// <c>"C:\XYZ"</c> was given, \c 3 is returned.
327 /// With other OSes "//" is searched.
328 static int IsAbsolute( const PathString& path ) {
329 #if defined(_WIN32)
330 if( path.Length() >= 3 ) {
331 if( path.CharAt<NC>(1) == ':'
332 && path.CharAt<NC>(2)== DIRECTORY_SEPARATOR )
333 return 3;
334
335 if ( path.CharAt<NC>(0) == DIRECTORY_SEPARATOR
336 && path.CharAt<NC>(1) == DIRECTORY_SEPARATOR)
337 return int(path.IndexOf<NC>( DIRECTORY_SEPARATOR, 2 ) + 1);
338 }
339 return 0;
340 #else
341 if( path.CharAtStart() == '/' )
342 return 1;
343 auto slashSlashPos= path.IndexOf(A_PATH("//"));
344 if( slashSlashPos > 0 )
345 return int(slashSlashPos + 2);
346 return 0;
347 #endif
348 }
349
350}; //class Path
351
352// Note(25/01/17):
353// Clang strangely did not find the following templated operators when they resided in an
354// exported namespace.
355// The workaround was to not export the namespace but export each operator instead.
356// We think this is wrong behavior and not aligned with the language specification.
357#if !DOXYGEN
358}} namespace alib::system {
359
361inline bool operator== (const Path& lhs, const Path& rhs)
362{ return lhs. template Equals <CHK, lang::Case::Sensitive>(rhs); }
363
365inline auto operator<=> (const Path& lhs, const Path& rhs)
366{ return lhs. template CompareTo<CHK, lang::Case::Sensitive>(rhs); }
367
368
369} ALIB_EXPORT namespace alib { namespace system {
370#endif // DOXYGEN
371
372} // namespace alib[::system]
373
374/// Type alias in namespace \b alib.
376
377/// Type alias in namespace \b alib.
379
380
381//##################################################################################################
382// Specializations of ZTArrayTraits for class Path
383//##################################################################################################
384#if !DOXYGEN
385namespace characters {
386template<>
387struct ZTArrayTraits<system::Path, system::PathCharType>
388{
389 static constexpr Policy Access = Policy::Implicit;
390 static constexpr Policy Construction = Policy::NONE;
391 static constexpr const system::PathCharType* Buffer(const system::Path& src) { return src.Terminate(); }
392 static constexpr integer Length(const system::Path& src) { return src.Length(); }
393};
394}// namespace alib[::characters]
395#endif //!DOXYGEN
396
397} // namespace [alib]
398
#define ALIB_DLL
Definition alib.inl:573
#define ALIB_EXPORT
Definition alib.inl:562
#define ALIB_BOXING_VTABLE_DECLARE(TMapped, Identifier)
constexpr const TChar * Terminate() const
Definition tastring.inl:620
constexpr TLocalString(lang::HeapAllocator &pAllocator)
constexpr integer Length() const
Definition string.inl:304
TChar CharAtStart() const
Definition string.inl:421
integer IndexOf(TChar needle, integer startIdx=0) const
Definition string.inl:803
TChar CharAt(integer idx) const
Definition string.inl:403
integer LastIndexOf(PathCharType needle, integer startIndex=MAX_LEN) const
Definition string.inl:913
Path(SystemFolders special, const PathString &fileName)
Definition path.inl:199
std::errc MakeCanonical()
Definition path.cpp:492
static PathString varTempDirEvaluatedOnce
Definition path.inl:180
Path & Add(const PathString &dirOrFilename)
Definition path.inl:263
PathString Parent() const
Definition path.inl:300
Path(SystemFolders special)
Definition path.inl:194
PathString Name() const
Definition path.inl:288
void AddModuleName(const PathString &extension)
Definition path.cpp:403
int IsAbsolute() const
Definition path.inl:284
bool IsDirectory()
Definition path.cpp:464
Path(const PathString &path)
Definition path.inl:203
bool ChangeToParent()
Definition path.cpp:440
void Change(SystemFolders special, const PathString &fileName)
Definition path.inl:242
std::errc Create()
Definition path.inl:222
bool Change(const PathString &path)
Definition path.cpp:417
static int IsAbsolute(const PathString &path)
Definition path.inl:328
static PathString tempDirEvaluatedOnce
Definition path.inl:170
#define ALIB_ENUMS_ASSIGN_RECORD(TEnum, TRecord)
@ Current
The current directory of the process.
Definition path.inl:91
@ Home
The user's home directory.
Definition path.inl:94
@ Module
The directory of the executable of the process.
Definition path.inl:104
@ Root
The root directory .
Definition path.inl:88
strings::TAString< PathCharType, PoolAllocator > PathStringMA
A mono-allocated string representing a path.
Definition path.inl:43
strings::TCString< PathCharType > CPathString
The string-type used with this ALib Module.
Definition path.inl:36
strings::TString< PathCharType > PathString
The string-type used with this ALib Module.
Definition path.inl:33
strings::TSubstring< PathCharType > PathSubstring
The string-type used with this ALib Module.
Definition path.inl:39
constexpr PathString NULL_PATH
A nulled path string.
Definition path.inl:51
strings::TAString< PathCharType, PoolAllocator > PathStringPA
A pool-allocated string representing a path.
Definition path.inl:46
constexpr PathString EMPTY_PATH
An empty path string.
Definition path.inl:54
std::filesystem::path::value_type PathCharType
Definition path.inl:12
constexpr PathCharType DIRECTORY_SEPARATOR
The standard path separator character. Defaults to '\' on Windows OS, '/' else.
Definition path.inl:63
system::SystemFolders SystemFolders
Type alias in namespace alib.
Definition path.inl:378
lang::integer integer
Type alias in namespace alib.
Definition integers.inl:149
system::Path Path
Type alias in namespace alib.
Definition path.inl:375
strings::TSubstring< character > Substring
Type alias in namespace alib.
#define A_PATH(literal)