ALib C++ Library
Library Version: 2510 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 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 this \b AString derivate is bound to 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 //==========================================================================================
189 /// Constructs an object representing no directory.
190 /// Field #Path remains empty.
191 //==========================================================================================
193 {}
194
195 //==========================================================================================
196 /// Constructs an object representing one of the known special directories.
197 /// @param special The special directory to initialize this instance to.
198 //==========================================================================================
200 {
201 Change( special );
202 }
203
204 //==========================================================================================
205 /// Constructs an object representing one of the known special directories.
206 /// @param special The special directory to initialize this instance to.
207 /// @param fileName The filename in folder \p{special}.
208 //==========================================================================================
209 Path( SystemFolders special, const PathString& fileName )
210 {
211 Change( special );
212 Add(fileName);
213 }
214
215 //==========================================================================================
216 /// Constructs an object representing the given path.
217 /// @param path The initial path.
218 //==========================================================================================
219 Path( const PathString& path )
220 : strings::TLocalString<PathCharType, 256>(path) {}
221
222
223 // #############################################################################################
224 // Interface
225 // #############################################################################################
226 public:
227 //==========================================================================================
228 /// Creates the directory of the given \p{path}. If a relative path is given, then
229 /// it is appended to the currently stored path, otherwise the current path is replaced.
230 /// @param path Zero-terminated string defining the path to test.
231 /// @return A value of enum type \alib{system;SystemErrors}.
232 //==========================================================================================
234 SystemErrors Create( const PathString& path );
235
236 //==========================================================================================
237 /// Creates the directory represented by this object by invoking #Create(const PathString&)
238 /// passing an empty String.
239 /// @return A value of the enum type \alib{system;SystemErrors}.
240 //==========================================================================================
243
244 //==========================================================================================
245 /// Changes the directory. If the given path is relative (e.g., a name of a subdirectory
246 /// or ".."), such path is added to the current #Path. Otherwise, this objects' path
247 /// string is replaced.
248 /// If the resulting destination directory is not valid, \c false is returned and this
249 /// object is not changed.
250 /// @param path The relative or absolute path to change to.
251 /// @returns \c true if the change was successful, \c false otherwise.
252 //==========================================================================================
253 ALIB_DLL bool Change( const PathString& path );
254
255 //==========================================================================================
256 /// Changes the directory to one of the known special directories.
257 /// @param special The special directory to change this instance to.
258 /// @returns \c true if the change was successful, \c false otherwise.
259 //==========================================================================================
260 ALIB_DLL bool Change( SystemFolders special );
261
262 //==========================================================================================
263 /// Changes the directory to one of the known special directories and adds the given
264 /// \p{fileName} to this path.
265 /// @param special The special directory to change this instance to.
266 /// @param fileName The filename within \p{special}.
267 //==========================================================================================
268 inline void Change( SystemFolders special, const PathString& fileName )
269 {
270 Change( special );
271 Add(fileName);
272 }
273
274
275 //==========================================================================================
276 /// Adds a directory or filename to the internal string. If the current string does not
277 /// end with a \alib{system;DIRECTORY_SEPARATOR}, one will be inserted first.
278 ///
279 /// @param dirOrFilename The path component to add.
280 /// @return \c *this to allow concatenated operations.
281 //==========================================================================================
282 inline Path& Add( const PathString& dirOrFilename )
283 {
286 _(dirOrFilename);
287 return *this;
288 }
289
290 //==========================================================================================
291 /// Adds this processes' module name to the currently stored folder path.
292 ///
293 /// @param extension An additional extension string that is added to the evaluated file
294 /// name, for example <c>".jpg"</c>.
295 //==========================================================================================
296 ALIB_DLL void AddModuleName( const PathString& extension );
297
298 //==========================================================================================
299 /// Tests if this path represents an existing directory in the file system.
300 /// @return \c true if a directory was found, \c false if not found or the path represents
301 /// a file.
302 //==========================================================================================
304 bool IsDirectory();
305
306 //==========================================================================================
307 /// Calls invokes static overload of this method, passing this object.
308 /// @returns The result of a call to #IsAbsolute(const PathString&).
309 //==========================================================================================
310 int IsAbsolute() const { return IsAbsolute(*this); }
311
312 //==========================================================================================
313 /// Gets the name portion of the path.
314 /// @returns A string containing the characters after the last directory separator.
315 //==========================================================================================
317 {
319 if( idx < 0 )
320 return *this;
321 return Substring(idx + 1);
322 }
323
324 //==========================================================================================
325 /// Resolves the path by removing all symbolic links and relative addressing.
326 /// @return \alib{system;SystemErrors;SystemErrors::OK} on success, otherwise
327 /// an error code.
328 //==========================================================================================
331
332 //==========================================================================================
333 /// Determines if the given string contains a path/filename with absolute addressing or
334 /// not.
335 /// \attention This method must be invoked on "real path strings" only. Assembled paths
336 /// which contain redundant slashes return a false result.
337 /// @param path The relative or absolute path to check.
338 /// @returns \c 0 if \p{path} is relative. If absolute, the position of the first character
339 /// that does not belong to the root symbol. For example, with windows OS, if
340 /// <c>"C:\XYZ"</c> was given, \c 3 is returned.
341 /// With other OSes "//" is searched.
342 //==========================================================================================
343 static int IsAbsolute( const PathString& path )
344 {
345 #if defined(_WIN32)
346 if( path.Length() >= 3 )
347 {
348 if( path.CharAt<NC>(1) == ':'
349 && path.CharAt<NC>(2)== DIRECTORY_SEPARATOR )
350 return 3;
351
352 if ( path.CharAt<NC>(0) == DIRECTORY_SEPARATOR
353 && path.CharAt<NC>(1) == DIRECTORY_SEPARATOR)
354 return int(path.IndexOf<NC>( DIRECTORY_SEPARATOR, 2 ) + 1);
355 }
356 return 0;
357 #else
358 if( path.CharAtStart() == '/' )
359 return 1;
360 auto slashSlashPos= path.IndexOf(A_PATH("//"));
361 if( slashSlashPos > 0 )
362 return int(slashSlashPos + 2);
363 return 0;
364 #endif
365 }
366
367}; //class Path
368
369// Note(25/01/17):
370// Clang strangely did not find the following templated operators when they resided in an
371// exported namespace.
372// The workaround was to not export the namespace but export each operator instead.
373// We think this is wrong behavior and not aligned with the language specification.
374#if !DOXYGEN
375}} namespace alib::system {
376
378inline bool operator== (const Path& lhs, const Path& rhs)
379{ return lhs. template Equals <CHK, lang::Case::Sensitive>(rhs); }
380
382inline auto operator<=> (const Path& lhs, const Path& rhs)
383{ return lhs. template CompareTo<CHK, lang::Case::Sensitive>(rhs); }
384
385
386} ALIB_EXPORT namespace alib { namespace system {
387#endif // DOXYGEN
388
389} // namespace alib[::system]
390
391/// Type alias in namespace \b alib.
393
394/// Type alias in namespace \b alib.
396
397
398// #################################################################################################
399// Specializations of ZTArrayTraits for class Path
400// #################################################################################################
401#if !DOXYGEN
402namespace characters {
403template<>
404struct ZTArrayTraits<system::Path, system::PathCharType>
405{
406 static constexpr Policy Access = Policy::Implicit;
407 static constexpr Policy Construction = Policy::NONE;
408 static constexpr const system::PathCharType* Buffer(const system::Path& src) { return src.Terminate(); }
409 static constexpr integer Length(const system::Path& src) { return src.Length(); }
410};
411}// namespace alib[::characters]
412#endif //!DOXYGEN
413
414} // namespace [alib]
415
418
419
420
constexpr const TChar * Terminate() const
Definition tastring.inl:682
constexpr TLocalString(lang::HeapAllocator &pAllocator)
constexpr integer Length() const
Definition string.inl:318
TChar CharAtStart() const
Definition string.inl:440
integer IndexOf(TChar needle, integer startIdx=0) const
Definition string.inl:844
TChar CharAt(integer idx) const
Definition string.inl:421
integer LastIndexOf(PathCharType needle, integer startIndex=MAX_LEN) const
Definition string.inl:967
Path(SystemFolders special, const PathString &fileName)
Definition path.inl:209
ALIB_DLL SystemErrors MakeReal()
Definition path.cpp:500
static PathString varTempDirEvaluatedOnce
Definition path.inl:180
Path & Add(const PathString &dirOrFilename)
Definition path.inl:282
ALIB_DLL SystemErrors Create()
Definition path.inl:242
Path(SystemFolders special)
Definition path.inl:199
PathString Name() const
Definition path.inl:316
ALIB_DLL void AddModuleName(const PathString &extension)
Definition path.cpp:429
int IsAbsolute() const
Definition path.inl:310
ALIB_DLL bool IsDirectory()
Definition path.cpp:470
Path(const PathString &path)
Definition path.inl:219
void Change(SystemFolders special, const PathString &fileName)
Definition path.inl:268
ALIB_DLL bool Change(const PathString &path)
Definition path.cpp:444
static int IsAbsolute(const PathString &path)
Definition path.inl:343
static PathString tempDirEvaluatedOnce
Definition path.inl:170
#define ALIB_DLL
Definition alib.inl:496
#define ALIB_ENUMS_ASSIGN_RECORD(TEnum, TRecord)
#define ALIB_BOXING_VTABLE_DECLARE(TMapped, Identifier)
#define A_PATH(literal)
#define ALIB_EXPORT
Definition alib.inl:488
@ 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:395
system::Path Path
Type alias in namespace alib.
Definition path.inl:392
strings::TSubstring< character > Substring
Type alias in namespace alib.