ALib C++ Library
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 \ref mainpage_license "Boost Software 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 "Compiler symbol 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 "Compiler symbol 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 compiler-symbol 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 compiler-symbol 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 \alib{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 /// \alib{system;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 /// \alib{system;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/// \alib{strings;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/// \alib{system::PathCharType}, 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 /// \alib{system;SystemFolders;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 \alib{monomem;GLOBAL_ALLOCATOR} and
169 /// access to this variable is consequently protected with \alib{monomem;GLOBAL_ALLOCATOR_LOCK}.
171
172 /// Singleton containing the path for the use of enum value
173 /// \alib{system;SystemFolders;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 \alib{monomem;GLOBAL_ALLOCATOR} and
179 /// access to this variable is consequently protected with \alib{monomem;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 \alib{system;SystemErrors}.
216 SystemErrors 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 the enum type \alib{system;SystemErrors}.
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 \alib{system;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 \alib{system;SystemErrors;SystemErrors::OK} on success, otherwise
316 /// an error code.
319
320 /// Determines if the given string contains a path/filename with absolute addressing or
321 /// not.
322 /// \attention This method must be invoked on "real path strings" only. Assembled paths
323 /// which contain redundant slashes return a false result.
324 /// @param path The relative or absolute path to check.
325 /// @returns \c 0 if \p{path} is relative. If absolute, the position of the first character
326 /// that does not belong to the root symbol. For example, with windows OS, if
327 /// <c>"C:\XYZ"</c> was given, \c 3 is returned.
328 /// With other OSes "//" is searched.
329 static int IsAbsolute( const PathString& path ) {
330 #if defined(_WIN32)
331 if( path.Length() >= 3 ) {
332 if( path.CharAt<NC>(1) == ':'
333 && path.CharAt<NC>(2)== DIRECTORY_SEPARATOR )
334 return 3;
335
336 if ( path.CharAt<NC>(0) == DIRECTORY_SEPARATOR
337 && path.CharAt<NC>(1) == DIRECTORY_SEPARATOR)
338 return int(path.IndexOf<NC>( DIRECTORY_SEPARATOR, 2 ) + 1);
339 }
340 return 0;
341 #else
342 if( path.CharAtStart() == '/' )
343 return 1;
344 auto slashSlashPos= path.IndexOf(A_PATH("//"));
345 if( slashSlashPos > 0 )
346 return int(slashSlashPos + 2);
347 return 0;
348 #endif
349 }
350
351}; //class Path
352
353// Note(25/01/17):
354// Clang strangely did not find the following templated operators when they resided in an
355// exported namespace.
356// The workaround was to not export the namespace but export each operator instead.
357// We think this is wrong behavior and not aligned with the language specification.
358#if !DOXYGEN
359}} namespace alib::system {
360
362inline bool operator== (const Path& lhs, const Path& rhs)
363{ return lhs. template Equals <CHK, lang::Case::Sensitive>(rhs); }
364
366inline auto operator<=> (const Path& lhs, const Path& rhs)
367{ return lhs. template CompareTo<CHK, lang::Case::Sensitive>(rhs); }
368
369
370} ALIB_EXPORT namespace alib { namespace system {
371#endif // DOXYGEN
372
373} // namespace alib[::system]
374
375/// Type alias in namespace \b alib.
377
378/// Type alias in namespace \b alib.
380
381
382//##################################################################################################
383// Specializations of ZTArrayTraits for class Path
384//##################################################################################################
385#if !DOXYGEN
386namespace characters {
387template<>
388struct ZTArrayTraits<system::Path, system::PathCharType>
389{
390 static constexpr Policy Access = Policy::Implicit;
391 static constexpr Policy Construction = Policy::NONE;
392 static constexpr const system::PathCharType* Buffer(const system::Path& src) { return src.Terminate(); }
393 static constexpr integer Length(const system::Path& src) { return src.Length(); }
394};
395}// namespace alib[::characters]
396#endif //!DOXYGEN
397
398} // namespace [alib]
399
constexpr const TChar * Terminate() const
Definition tastring.inl:660
constexpr TLocalString(lang::HeapAllocator &pAllocator)
constexpr integer Length() const
Definition string.inl:316
TChar CharAtStart() const
Definition string.inl:433
integer IndexOf(TChar needle, integer startIdx=0) const
Definition string.inl:815
TChar CharAt(integer idx) const
Definition string.inl:415
integer LastIndexOf(PathCharType needle, integer startIndex=MAX_LEN) const
Definition string.inl:925
Path(SystemFolders special, const PathString &fileName)
Definition path.inl:199
ALIB_DLL SystemErrors MakeReal()
Definition path.cpp:493
static PathString varTempDirEvaluatedOnce
Definition path.inl:180
Path & Add(const PathString &dirOrFilename)
Definition path.inl:263
ALIB_DLL SystemErrors Create()
Definition path.inl:222
PathString Parent() const
Definition path.inl:300
Path(SystemFolders special)
Definition path.inl:194
PathString Name() const
Definition path.inl:288
ALIB_DLL void AddModuleName(const PathString &extension)
Definition path.cpp:404
int IsAbsolute() const
Definition path.inl:284
ALIB_DLL bool IsDirectory()
Definition path.cpp:465
Path(const PathString &path)
Definition path.inl:203
ALIB_DLL bool ChangeToParent()
Definition path.cpp:441
void Change(SystemFolders special, const PathString &fileName)
Definition path.inl:242
ALIB_DLL bool Change(const PathString &path)
Definition path.cpp:418
static int IsAbsolute(const PathString &path)
Definition path.inl:329
static PathString tempDirEvaluatedOnce
Definition path.inl:170
#define ALIB_DLL
Definition alib.inl:503
#define ALIB_ENUMS_ASSIGN_RECORD(TEnum, TRecord)
#define ALIB_BOXING_VTABLE_DECLARE(TMapped, Identifier)
#define A_PATH(literal)
#define ALIB_EXPORT
Definition alib.inl:497
@ 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
lang::integer integer
Type alias in namespace alib.
Definition integers.inl:149
system::SystemFolders SystemFolders
Type alias in namespace alib.
Definition path.inl:379
system::Path Path
Type alias in namespace alib.
Definition path.inl:376
strings::TSubstring< character > Substring
Type alias in namespace alib.