yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
f65d756bf
master
1#ifndef SLANG_CORE_IO_H 2#define SLANG_CORE_IO_H 3 4#include "slang-blob.h" 5#include "slang-secure-crt.h" 6#include "slang-stream.h" 7#include "slang-string.h" 8#include "slang-text-io.h" 9 10namespace Slang 11{ 12class File 13{ 14public : 15static bool exists (const String & fileName ); 16 17static SlangResult readAllText (const String & fileName ,String & outString ); 18 19static SlangResult readAllBytes (const String & fileName ,List < unsigned char >& out ); 20static SlangResult readAllBytes (const String & fileName ,ScopedAllocation & out ); 21 22static SlangResult writeAllText (const String & fileName ,const String & text ); 23 24static SlangResult writeAllTextIfChanged (const String & fileName ,UnownedStringSlice text ); 25 26/// Write as text in native form for the target (so typically may change line endings ) 27static SlangResult writeNativeText (const String & filename ,const void * data ,size_t size ); 28 29static SlangResult writeAllBytes (const String & fileName ,const void * data ,size_t size ); 30 31static SlangResult remove (const String & fileName ); 32 33static SlangResult makeExecutable (const String & fileName ); 34 35/// Creates a temporary file typically in some way based on the prefix 36/// The file will be *created* with the outFileName, on success. 37/// It's creation in necessary to lock that particular name. 38static SlangResult generateTemporary (const UnownedStringSlice & prefix ,String & outFileName ); 39}; 40 41class Path 42{ 43public : 44typedef uint32_t SimplifyIntegral ; 45 46struct SimplifyFlag 47 { 48enum Enum :SimplifyIntegral 49 { 50/// Can only simplify to an absolute path. Will return an error if not possible. 51/// Useful to constrain a path, such as when wanting something like 'chroot'. 52AbsoluteOnly = 0x1 , 53/// If the simplified path is a root path, remove the root. 54/// Will mean that for example 55/// "/" -> "." 56/// "/a/.." -> "." 57/// "/a" -> "a" 58/// Its worth noting that a path prefixed "/" will never be returned and if *just* the 59/// root it specified it will return as ".". 60NoRoot = 0x2 , 61 }; 62 }; 63 64// A more convenient typesafe way to specify the SimplifyFlag combinations 65enum SimplifyStyle :SimplifyIntegral 66 { 67Normal = 0 , 68AbsoluteOnly = SimplifyFlag ::AbsoluteOnly , 69NoRoot = SimplifyFlag ::NoRoot , 70AbsoluteOnlyAndNoRoot = SimplifyFlag ::AbsoluteOnly |SimplifyFlag ::NoRoot , 71 }; 72 73enum class Type 74 { 75Unknown , 76File , 77Directory , 78 }; 79 80typedef uint32_t TypeFlags ; 81struct TypeFlag 82 { 83enum Enum :TypeFlags 84 { 85Unknown = TypeFlags (1 ) <<int (Type ::Unknown ), 86File = TypeFlags (1 ) <<int (Type ::File ), 87Directory = TypeFlags (1 ) <<int (Type ::Directory ), 88 }; 89 }; 90 91class Visitor 92 { 93public : 94virtual void accept (Type type ,const UnownedStringSlice & filename )= 0 ; 95 }; 96 97static const char kPathDelimiter = '/' ; 98 99#if SLANG_WINDOWS_FAMILY 100static const char kOSCanonicalPathDelimiter = '\\' ; 101static const char kOSAlternativePathDelimiter = '/' ; 102 103#else 104static const char kOSCanonicalPathDelimiter = '/' ; 105static const char kOSAlternativePathDelimiter = '/' ; 106#endif 107 108/// Finds all all the items in the specified directory, that matches the pattern. 109/// 110/// @param directoryPath The directory to do the search in. If the directory is not found, 111/// SLANG_E_NOT_FOUND is returned 112/// @param pattern. The pattern to match against. The pattern matching is targtet specific (ie 113/// window matching is different to linux/unix). Passing nullptr means no matching. 114/// @return is SLANG_E_NOT_FOUND if the directoryPath is not found 115static SlangResult find (const String & directoryPath ,const char * pattern ,Visitor * visitor ); 116 117/// Returns -1 if no separator is found 118static Index findLastSeparatorIndex (String const & path ) 119 { 120return findLastSeparatorIndex (path .getUnownedSlice ()); 121 } 122static Index findLastSeparatorIndex (UnownedStringSlice const & path ); 123/// Finds the index of the last dot in a path, else returns -1 124static Index findExtIndex (String const & path ) {return findExtIndex (path .getUnownedSlice ()); } 125static Index findExtIndex (UnownedStringSlice const & path ); 126 127/// True if isn't just a name (ie has any path separator) 128/// Note this is no the same as having a 'parent' as '/thing' 'has a path', but it doesn't have 129/// a parent. 130static bool hasPath (const UnownedStringSlice & path ) 131 { 132return findLastSeparatorIndex (path ) >=0 ; 133 } 134static bool hasPath (const String & path ) {return findLastSeparatorIndex (path ) >=0 ; } 135 136static String replaceExt (const String & path ,const char * newExt ); 137static String getFileName (const String & path ); 138static String getPathWithoutExt (const String & path ); 139 140static String getPathExt (const String & path ) {return getPathExt (path .getUnownedSlice ()); } 141static UnownedStringSlice getPathExt (const UnownedStringSlice & path ); 142 143static String getParentDirectory (const String & path ); 144 145static String getFileNameWithoutExt (const String & path ); 146 147static String combine (const String & path1 ,const String & path2 ); 148static String combine (const String & path1 ,const String & path2 ,const String & path3 ); 149 150/// Combine path sections and store the result in outBuilder 151static void combineIntoBuilder ( 152const UnownedStringSlice & path1 , 153const UnownedStringSlice & path2 , 154StringBuilder & outBuilder ); 155 156/// Append a path, taking into account path separators onto the end of ioBuilder 157static void append (StringBuilder & ioBuilder ,const UnownedStringSlice & path ); 158 159static bool createDirectory (const String & path ); 160static bool createDirectoryRecursive (const String & path ); 161 162/// Accept either style of delimiter 163SLANG_FORCE_INLINE static bool isDelimiter (char c ) {return c == '/' || c == '\\' ; } 164 165/// True if the element appears to be a drive specification (where element is the prefix to a 166/// path that isn't a directory) 167/// @param pathPrefix The path prefix to test if it's a drive specification 168static bool isDriveSpecification (const UnownedStringSlice & pathPrefix ); 169 170/// Splits the path into it's individual bits 171/// Absolute paths of the form "/" will become [""] 172/// Absolute paths of the form "a:/" will become ["a:", ""] 173/// A drive specification of the form "a:" will become ["a:"] 174/// Relative paths that are in effect "." will become [] 175static void split (const UnownedStringSlice & path ,List < UnownedStringSlice >& splitOut ); 176 177/// Strips .. and . as much as it can 178static String simplify (const UnownedStringSlice & path ); 179static String simplify (const String & path ) {return simplify (path .getUnownedSlice ()); } 180 181/// Given a path simplifies it such the the resultant path is absolute (ie contains no . or ..) 182/// Same behavior as simplify around the root 183static SlangResult simplify ( 184const UnownedStringSlice & path , 185SimplifyStyle style , 186StringBuilder & outPath ); 187static SlangResult simplify (const String & path ,SimplifyStyle style ,StringBuilder & outPath ) 188 { 189return simplify (path .getUnownedSlice (),style ,outPath ); 190 } 191static SlangResult simplify (const char * path ,SimplifyStyle style ,StringBuilder & outPath ) 192 { 193return simplify (UnownedStringSlice (path ),style ,outPath ); 194 } 195 196/// Simplifies the path split up 197static void simplify (List < UnownedStringSlice >& ioSplit ); 198 199/// Join the parts of the path to produce an output path 200static void join (const UnownedStringSlice * slices ,Index count ,StringBuilder & out ); 201 202/// Returns true if the path is absolute 203static bool isAbsolute (const UnownedStringSlice & path ); 204static bool isAbsolute (const String & path ) {return isAbsolute (path .getUnownedSlice ()); } 205 206/// Returns true if path contains contains an element of . or .. 207static bool hasRelativeElement (const UnownedStringSlice & path ); 208static bool hasRelativeElement (const String & path ) 209 { 210return hasRelativeElement (path .getUnownedSlice ()); 211 } 212 213/// Determines the type of file at the path 214/// @param path The path to test 215/// @param outPathType Holds the object type at the path on success 216/// @return SLANG_OK on success 217static SlangResult getPathType (const String & path ,SlangPathType * outPathType ); 218 219/// Determines the canonical equivalent path to path. 220/// The path returned should reference the identical object - and two different references to 221/// the same path should return the same canonical path 222/// @param path Path to get the canonical path for 223/// @param outCanonicalPath The canonical path for 'path' is call is successful 224/// @return SLANG_OK on success 225static SlangResult getCanonical (const String & path ,String & outCanonicalPath ); 226 227/// Returns the current working directory 228/// @return The path in platform native format. Returns empty string if failed. 229static String getCurrentPath (); 230 231/// Returns the executable path 232/// @return The path in platform native format. Returns empty string if failed. 233static String getExecutablePath (); 234 235/// Returns the first element of the path or an empty slice if there is none 236/// This broadly equivalent to returning the first element of split 237/// @param path Path to extract first element from 238/// @return The first element of the path, or empty 239static UnownedStringSlice getFirstElement (const UnownedStringSlice & path ); 240 241/// Remove a file or directory at specified path. The directory must be empty for it to be 242/// removed 243/// @param path 244/// @return SLANG_OK if file or directory is removed 245static SlangResult remove (const String & path ); 246 247/// Remove a file or directory at specified path. The directory can be non-empty. 248/// @param path 249/// @return SLANG_OK if file or directory is removed 250static SlangResult removeNonEmpty (const String & path ); 251 252static bool equals (String path1 ,String path2 ); 253 254/// Turn `path` into a relative path from base. 255static String getRelativePath (String base ,String path ); 256}; 257 258struct URI 259{ 260String uri ; 261bool operator == (const URI & other )const {return uri == other .uri ; } 262bool operator != (const URI & other )const {return uri != other .uri ; } 263 264HashCode getHashCode ()const {return uri .getHashCode (); } 265 266bool isLocalFile () {return uri .startsWith ("file://" ); }; 267String getPath ()const ; 268StringSlice getProtocol ()const ; 269 270static URI fromLocalFilePath (UnownedStringSlice path ); 271static URI fromString (UnownedStringSlice uriString ); 272static bool isSafeURIChar (char ch ); 273}; 274 275/// Helper class abstracting lock files. 276/// Uses LockFileEx() on windows systems and flock() on POSIX systems. 277class LockFile 278{ 279public : 280enum class LockType 281 { 282Exclusive , 283Shared , 284 }; 285 286/// Open the lock file. This will create the file if it doesn't exist yet. 287/// @param fileName File name to open. 288/// @return SLANG_OK on success. 289SlangResult open (const String & fileName ); 290 291/// Closes the lock file. 292void close (); 293 294/// Returns true if the lock file is open. 295bool isOpen ()const {return m_isOpen ; } 296 297/// Acquire the lock in non-blocking mode. 298/// @param lockType Lock type (Exclusive or Shared). 299/// @return SLANG_OK on success. SLANG_E_TIME_OUT if the lock is already held. 300SlangResult tryLock (LockType lockType = LockType ::Exclusive ); 301 302/// Acquire the lock in blocking mode. 303/// @param lockType Lock type (Exclusive or Shared). 304/// @return SLANG_OK on success. 305SlangResult lock (LockType lockType = LockType ::Exclusive ); 306 307/// Release the lock. 308/// @return SLANG_OK on success. 309SlangResult unlock (); 310 311LockFile (); 312 ~LockFile (); 313 314private : 315LockFile (const LockFile & )= delete ; 316LockFile (LockFile && ) = delete; 317LockFile & operator = ( const LockFile & ) = delete; 318LockFile & operator = (LockFile && ) = delete; 319 320#if SLANG_WINDOWS_FAMILY 321void * m_fileHandle; 322#else 323int m_fileHandle; 324#endif 325bool m_isOpen; 326}; 327 328class LockFileGuard 329{ 330public : 331LockFileGuard (LockFile & lockFile, LockFile::LockType lockType = LockFile::LockType::Exclusive) 332: m_lockFile( lockFile ) 333{ 334m_lockFile. lock (lockType); 335} 336 337~ LockFileGuard () { m_lockFile. unlock (); } 338 339private : 340LockFileGuard( const LockFileGuard & ) = delete; 341LockFileGuard (LockFileGuard && ) = delete; 342LockFileGuard & operator = ( const LockFileGuard & ) = delete; 343LockFileGuard & operator = (LockFileGuard && ) = delete; 344 345LockFile & m_lockFile; 346}; 347 348} // namespace Slang 349 350#endif