ALib C++ Library
Library Version: 2412 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 sub-namespace #alib::lang::system of module \alib_basecamp of
4/// the \aliblong.
5///
6/// \emoji :copyright: 2013-2024 A-Worx GmbH, Germany.
7/// Published under \ref mainpage_license "Boost Software License".
8//==================================================================================================
9#ifndef HPP_ALIB_LANG_SYSTEM_PATH
10#define HPP_ALIB_LANG_SYSTEM_PATH 1
11#pragma once
15#include <filesystem>
16
17namespace alib { namespace lang::system {
18
19/// The character type that this \alibmod_nl uses for String representations.
20/// This is taken from the C++ standard library.
21using PathCharType = std::filesystem::path::value_type;
22
23// Symbol ALIB_PATH_CHARACTERS_WIDE and macro A_PATH for literals
24#if !defined(ALIB_PATH_CHARACTERS_WIDE)
25# if defined(_WIN32)
26# define ALIB_PATH_CHARACTERS_WIDE 1
28 "Compiler symbol ALIB_PATH_CHARACTERS_WIDE wrongly detected: 1 but std::filesystem::path::value_type does not equal characters::wchar.");
29# else
30# define ALIB_PATH_CHARACTERS_WIDE 0
32 "Compiler symbol ALIB_PATH_CHARACTERS_WIDE wrongly detected: 0 but std::filesystem::path::value_type does not equal characters::nchar.");
33# endif
34#else
35# if ALIB_PATH_CHARACTERS_WIDE
37 "Given compiler symbol ALIB_PATH_CHARACTERS_WIDE mismatch: Given 1 but std::filesystem::path::value_type does not equal characters::wchar.");
38# else
40 "Given compiler symbol ALIB_PATH_CHARACTERS_WIDE mismatch: Given 0 but std::filesystem::path::value_type does not equal characters::nchar.");
41# endif
42#endif
43
44#if ALIB_PATH_CHARACTERS_WIDE
45# define A_PATH(literal) L##literal
46#else
47# define A_PATH(literal) literal
48#endif
49
50#if ALIB_CHARACTERS_WIDE == ALIB_PATH_CHARACTERS_WIDE
51# define ALIB_PATH_TO_STRING( src,dest,bufSize ) decltype(src)& dest(src);
52# define ALIB_PATH_TO_STRING_ARG( src,bufSize ) src;
53# define ALIB_STRING_TO_PATH( src,dest,bufSize ) decltype(src)& dest(src);
54# define ALIB_STRING_TO_PATH_ARG( src,bufSize ) src;
55#else
56# define ALIB_PATH_TO_STRING( src,dest,bufSize ) alib::strings::TLocalString<alib::characters::character ,bufSize> dest(src);
57# define ALIB_PATH_TO_STRING_ARG( src,bufSize ) alib::strings::TLocalString<alib::characters::character ,bufSize>(src);
58# define ALIB_STRING_TO_PATH( src,dest,bufSize ) alib::strings::TLocalString<alib::lang::system::PathCharType ,bufSize> dest(src);
59# define ALIB_STRING_TO_PATH_ARG( src,bufSize ) alib::strings::TLocalString<alib::lang::system::PathCharType ,bufSize>(src);
60#endif
61
62#if !ALIB_PATH_CHARACTERS_WIDE
63# define ALIB_PATH_TO_NARROW( src,dest,bufSize ) decltype(src)& dest(src);
64# define ALIB_PATH_TO_NARROW_ARG( src,bufSize ) src;
65#else
66# define ALIB_PATH_TO_NARROW( src,dest,bufSize ) alib::strings::TLocalString<alib::characters::nchar, bufSize> dest(src);
67# define ALIB_PATH_TO_NARROW_ARG( src,bufSize ) alib::strings::TLocalString<alib::characters::nchar, bufSize>(src);
68#endif
69
70/// The string-type used with this \alibmod_nl.
72
73/// The string-type used with this \alibmod_nl.
75
76/// The string-type used with this \alibmod_nl.
78
79/// A mono-allocated string representing a path.
81
82/// A pool-allocated string representing a path.
84
85#if DOXYGEN
86/// A nulled path string.
87constexpr static PathString NULL_PATH;
88
89/// An empty path string.
90constexpr static PathString EMPTY_PATH;
91#else
92constexpr static PathString NULL_PATH(nullptr);
93constexpr static PathString EMPTY_PATH(A_PATH(""));
94#endif
95
96
97#if !defined( _WIN32 ) || DOXYGEN
98 /// The standard path separator character. Defaults to '\\' on Windows OS, '/' else.
99 constexpr static PathCharType DIRECTORY_SEPARATOR = '/';
100#else
101 constexpr static PathCharType DIRECTORY_SEPARATOR = '\\';
102#endif
103
104// #############################################################################################
105// MacOS System call wrappers (implemented in Objective-C)
106// #############################################################################################
107#if defined(__APPLE__)
108class Path;
109namespace macos
110{
111 void ALIB_APPLE_OC_NSTemporaryDirectory( Path& target );
112 void ALIB_APPLE_OC_NSHomeDirectory ( Path& target );
113}
114#endif
115
116//==================================================================================================
117/// Enumerates special system folders like "home", "temp", "config", etc.
118/// This enumeration is primarily used with class \alib{lang::system;Path} and this documentation
119/// refers to this type.
120//==================================================================================================
122{
123 /// The root directory .
124 Root,
125
126 /// The current directory of the process.
127 Current,
128
129 /// The user's home directory
130 Home,
131
132 /// The user's configuration directory. This is evaluated as follows:
133 /// - Using environment variable \e HOME (under WindowsOS a combination of \e HOMEDRIVE
134 /// and \e HOMEPATH), the home directory is determined.
135 /// - If within this directory \e ".config" exists, it is used, otherwise
136 /// - if within this the directories \e "AppData/Roaming" exist, this is used.
138
139 /// The directory of the executable of the process.
140 Module,
141
142 /// A directory to be used for creation of temporary files.
143 ///
144 /// - On GNU/Linux OS this defaults to <c>/tmp</c>.
145 /// - On Windows OS, environment variables TMP and TEMP are evaluated.<br>
146 ///
147 /// If the directory does not exist, then (on all OS), a new directory named \c ".tmp"
148 /// is created in the user's home directory and returned (if not existent already).
149 /// If this fails, the home directory itself is returned.
150 ///
151 /// \note With the potential creation of the directory \c ".tmp" in the user's home
152 /// directory, a small \c readme.txt file is created containing the name of
153 /// the running application and the reason of the creation.
154 ///
155 /// To overrule this behavior, public static variable
156 /// \alib{lang::system;Path::tempDirEvaluatedOnce} may be set arbitrarily before using this
157 /// enum value.
158 Temp,
159
160 /// A directory to be used for creation of temporary files that survives reboots of the
161 /// host machine.
162 ///
163 /// - On GNU/Linux OS this defaults to <c>/var/tmp</c>.
164 /// - On Windows OS, environment variables TMP and TEMP are evaluated (same as
165 /// with \b %SystemFolders::Temp).<br>
166 ///
167 /// If the directory does not exist, then (on all OS), a new directory named \c ".var.tmp"
168 /// is created in the user's home directory and returned (if not existent already).
169 /// If this fails, the home directory itself is returned.
170 ///
171 /// \note With the potential creation of the directory \c ".var.tmp" in the user's home
172 /// directory, a small \c readme.txt file is created, containing the name of
173 /// the running application and the reason of the creation.
174 ///
175 /// To overrule this behavior, public static variable
176 /// \alib{lang::system;Path::varTempDirEvaluatedOnce} may be set arbitrarily before using this
177 /// enum value.
178 VarTemp,
179};
180
181
182//==================================================================================================
183/// Represents a directory or file in a file system.
184///
185/// Inherits a local string buffer fixed to size 256. The flexible nature of \alib
186/// \alib{strings;TLocalString;local strings} allows dynamic allocation if this should be exceeded
187/// (which usually is not expected with paths).
188///
189/// The character type of this \b AString derivate is bound to type definition
190/// \alib{lang;system::PathCharType}, which in turn aliases
191/// <c>std::filesystem::path::value_type</c>.
192//==================================================================================================
193class Path : public strings::TLocalString<PathCharType, 256>
194{
195 // #############################################################################################
196 // Fields
197 // #############################################################################################
198 public:
199 /// Singleton containing the path for the use of enum value
200 /// \alib{lang::system;SystemFolders;SystemFolders::Temp}.
201 /// This is evaluated once with the first use of \b %SystemFolders::Temp.
202 /// To change the default behavior of evaluation, this variable may be filled with a proper
203 /// path before using enum \b %SystemFolders::Temp with this class.
204 ///
205 /// The one-time evaluated value is stored in the \alib{monomem;GLOBAL_ALLOCATOR} and
206 /// access to this variable is consequently protected with \alib{monomem;GLOBAL_ALLOCATOR_LOCK}.
208
209 /// Singleton containing the path for the use of enum value
210 /// \alib{lang::system;SystemFolders;SystemFolders::VarTemp}".
211 /// This is evaluated once with the first use of \b %SystemFolders::VarTemp.
212 /// To change the default behavior of evaluation, this variable may be filled with a proper
213 /// path before using enum \b %SystemFolders::VarTemp with this class.
214 ///
215 /// The one-time evaluated value is stored in the \alib{monomem;GLOBAL_ALLOCATOR} and
216 /// access to this variable is consequently protected with \alib{monomem;GLOBAL_ALLOCATOR_LOCK}.
218
219 // #############################################################################################
220 // Constructors
221 // #############################################################################################
222 public:
224
225 //==========================================================================================
226 /// Constructs an object representing no directory.
227 /// Field #Path remains empty.
228 //==========================================================================================
230 {}
231
232 //==========================================================================================
233 /// Constructs an object representing one of the known special directories.
234 /// @param special The special directory to initialize this instance to.
235 //==========================================================================================
237 {
238 Change( special );
239 }
240
241 //==========================================================================================
242 /// Constructs an object representing one of the known special directories.
243 /// @param special The special directory to initialize this instance to.
244 /// @param fileName The filename in folder \p{special}.
245 //==========================================================================================
246 Path( SystemFolders special, const PathString& fileName )
247 {
248 Change( special );
249 Add(fileName);
250 }
251
252 //==========================================================================================
253 /// Constructs an object representing the given path.
254 /// @param path The initial path.
255 //==========================================================================================
256 Path( const PathString& path )
257 : strings::TLocalString<PathCharType, 256>(path) {}
258
259
260 // #############################################################################################
261 // Interface
262 // #############################################################################################
263 public:
264 //==========================================================================================
265 /// Creates the directory of the given \p{path}. If a relative path is given, then
266 /// it is appended to the currently stored path, otherwise the current path is replaced.
267 /// @param path Zero-terminated string defining the path to test.
268 /// @return A value of enum type \alib{lang::system;SystemErrors}.
269 //==========================================================================================
271 SystemErrors Create( const PathString& path );
272
273 //==========================================================================================
274 /// Creates the directory represented by this object by invoking #Create(const String&)
275 /// passing an empty String.
276 /// @return A value of enum type \alib{lang::system;SystemErrors}.
277 //==========================================================================================
280
281 //==========================================================================================
282 /// Changes the directory. If the given path is relative (e.g., a name of a subdirectory
283 /// or ".."), such path is added to the current #Path. Otherwise, this objects' path
284 /// string is replaced.
285 /// If the resulting destination directory is not valid, \c false is returned and this
286 /// object is not changed.
287 /// @param path The relative or absolute path to change to.
288 /// @returns \c true if the change was successful, \c false otherwise.
289 //==========================================================================================
290 ALIB_API bool Change( const PathString& path );
291
292 //==========================================================================================
293 /// Changes the directory to one of the known special directories.
294 /// @param special The special directory to change this instance to.
295 /// @returns \c true if the change was successful, \c false otherwise.
296 //==========================================================================================
297 ALIB_API bool Change( SystemFolders special );
298
299 //==========================================================================================
300 /// Changes the directory to one of the known special directories and adds the given
301 /// \p{fileName} to this path.
302 /// @param special The special directory to change this instance to.
303 /// @param fileName The filename within \p{special}.
304 //==========================================================================================
305 inline void Change( SystemFolders special, const PathString& fileName )
306 {
307 Change( special );
308 Add(fileName);
309 }
310
311
312 //==========================================================================================
313 /// Adds a directory or filename to the internal string. If the current string does not
314 /// end with a \alib{lang::system;DIRECTORY_SEPARATOR}, one will be inserted first.
315 ///
316 /// @param dirOrFilename The path component to add.
317 /// @return \c *this to allow concatenated operations.
318 //==========================================================================================
319 inline Path& Add( const PathString& dirOrFilename )
320 {
323 _(dirOrFilename);
324 return *this;
325 }
326
327 //==========================================================================================
328 /// Adds this processes' module name to the currently stored folder path.
329 ///
330 /// @param extension An additional extension string that is added to the evaluated file
331 /// name, for example <c>".jpg"</c>.
332 //==========================================================================================
333 ALIB_API void AddModuleName( const PathString& extension );
334
335 //==========================================================================================
336 /// Tests if this path represents an existing directory in the file system.
337 /// @return \c true if a directory was found, \c false if not found or the path represents
338 /// a file.
339 //==========================================================================================
341 bool IsDirectory();
342
343 //==========================================================================================
344 /// Calls invokes static overload of this method, passing this object.
345 /// @returns The result of a call to #IsAbsolute(const PathString&).
346 //==========================================================================================
347 int IsAbsolute() const { return IsAbsolute(*this); }
348
349 //==========================================================================================
350 /// Gets the name portion of the path.
351 /// @returns A string containing the characters after the last directory separator.
352 //==========================================================================================
354 {
356 if( idx < 0 )
357 return *this;
358 return Substring(idx + 1);
359 }
360
361 //==========================================================================================
362 /// Resolves the path by removing all symbolic links and relative addressing.
363 /// @return \alib{lang::system;SystemErrors;SystemErrors::OK} on success, otherwise
364 /// an error code.
365 //==========================================================================================
368
369 //==========================================================================================
370 /// Determines if the given string contains a path/filename with absolute addressing or
371 /// not.
372 /// \attention This method must be invoked on "real path strings" only. Assembled paths
373 /// which contain redundant slashes return a false result.
374 /// @param path The relative or absolute path to check.
375 /// @returns \c 0 if \p{path} is relative. If absolute, the position of the first character
376 /// that does not belong to the root symbol. For example, with windows OS, if
377 /// <c>"C:\XYZ"</c> was given, \c 3 is returned.
378 /// With other OSes "//" is searched.
379 //==========================================================================================
380 static int IsAbsolute( const PathString& path )
381 {
382 #if defined(_WIN32)
383 if( path.Length() >= 3 )
384 {
385 if( path.CharAt<NC>(1) == ':'
386 && path.CharAt<NC>(2)== DIRECTORY_SEPARATOR )
387 return 3;
388
389 if ( path.CharAt<NC>(0) == DIRECTORY_SEPARATOR
390 && path.CharAt<NC>(1) == DIRECTORY_SEPARATOR)
391 return int(path.IndexOf<NC>( DIRECTORY_SEPARATOR, 2 ) + 1);
392 }
393 return 0;
394 #else
395 if( path.CharAtStart() == '/' )
396 return 1;
397 auto slashSlashPos= path.IndexOf(A_PATH("//"));
398 if( slashSlashPos > 0 )
399 return int(slashSlashPos + 2);
400 return 0;
401 #endif
402 }
403
404}; //class Path
405
406} // namespace alib[:: lang::system]
407
408/// Type alias in namespace \b alib.
410
411/// Type alias in namespace \b alib.
413
414
415// #################################################################################################
416// Specializations of T_ZTCharArray for class Path
417// #################################################################################################
418#if !DOXYGEN
419namespace characters {
420template<>
421struct T_ZTCharArray<lang::system::Path, lang::system::PathCharType>
422{
423 static constexpr AccessType Access = AccessType::Implicit;
424 static constexpr const lang::system::PathCharType* Buffer(const lang::system::Path& src) { return src.Terminate(); }
425 static constexpr integer Length(const lang::system::Path& src) { return src.Length(); }
426
427 static constexpr ConstructionType Construction = ConstructionType::NONE;
428};
429}// namespace alib[::characters]
430#endif //!DOXYGEN
431
432} // namespace [alib]
433
436
437
438#endif // HPP_ALIB_LANG_SYSTEM_PATH
439
Path(const PathString &path)
Definition path.hpp:256
static int IsAbsolute(const PathString &path)
Definition path.hpp:380
ALIB_API bool Change(const PathString &path)
Definition path.cpp:334
Path & Add(const PathString &dirOrFilename)
Definition path.hpp:319
int IsAbsolute() const
Definition path.hpp:347
Path(SystemFolders special)
Definition path.hpp:236
static PathString tempDirEvaluatedOnce
Definition path.hpp:207
ALIB_API SystemErrors Create()
Definition path.hpp:279
ALIB_API SystemErrors MakeReal()
Definition path.cpp:390
Path(SystemFolders special, const PathString &fileName)
Definition path.hpp:246
PathString Name() const
Definition path.hpp:353
ALIB_API void AddModuleName(const PathString &extension)
Definition path.cpp:319
void Change(SystemFolders special, const PathString &fileName)
Definition path.hpp:305
static PathString varTempDirEvaluatedOnce
Definition path.hpp:217
ALIB_API bool IsDirectory()
Definition path.cpp:360
constexpr const TChar * Terminate() const
Definition tastring.inl:821
integer IndexOf(TChar needle, integer startIdx=0) const
Definition string.hpp:896
TChar CharAt(integer idx) const
Definition string.hpp:444
constexpr integer Length() const
Definition string.hpp:326
TChar CharAtStart() const
Definition string.hpp:466
ALIB_WARNINGS_RESTORE integer LastIndexOf(PathCharType needle, integer startIndex=MAX_LEN) const
Definition string.hpp:1034
#define ALIB_ENUMS_ASSIGN_RECORD(TEnum, TRecord)
Definition records.hpp:712
#define ALIB_API
Definition alib.hpp:639
#define ALIB_BOXING_VTABLE_DECLARE(TMapped, Identifier)
Definition vtable.inl:460
#define A_PATH(literal)
Definition path.hpp:45
#define ATMP_EQ( T, TEqual)
Definition tmp.hpp:27
PLATFORM_SPECIFIC wchar
@ Current
The current directory of the process.
@ Home
The user's home directory.
@ Module
The directory of the executable of the process.
@ Root
The root directory .
static constexpr PathString EMPTY_PATH
An empty path string.
Definition path.hpp:90
static constexpr PathString NULL_PATH
A nulled path string.
Definition path.hpp:87
SystemErrors
Denotes result values returned by system functions (glibc, etc).
std::filesystem::path::value_type PathCharType
Definition path.hpp:21
static constexpr PathCharType DIRECTORY_SEPARATOR
The standard path separator character. Defaults to '\' on Windows OS, '/' else.
Definition path.hpp:99
Definition alib.cpp:69
strings::TSubstring< character > Substring
Type alias in namespace alib.
lang::integer integer
Type alias in namespace alib.
Definition integers.hpp:273
static const TChar * Buffer(const TString &src)
static integer Length(const TString &src)