yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Ellie Hermaszewskaformatf65d756bf

master
12.5 KiB350 linesraw
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:
15    static bool exists(const String& fileName);
16
17    static SlangResult readAllText(const String& fileName, String& outString);
18
19    static SlangResult readAllBytes(const String& fileName, List<unsigned char>& out);
20    static SlangResult readAllBytes(const String& fileName, ScopedAllocation& out);
21
22    static SlangResult writeAllText(const String& fileName, const String& text);
23
24    static SlangResult writeAllTextIfChanged(const String& fileName, UnownedStringSlice text);
25
26    /// Write as text in native form for the target (so typically may change line endings )
27    static SlangResult writeNativeText(const String& filename, const void* data, size_t size);
28
29    static SlangResult writeAllBytes(const String& fileName, const void* data, size_t size);
30
31    static SlangResult remove(const String& fileName);
32
33    static 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.
38    static SlangResult generateTemporary(const UnownedStringSlice& prefix, String& outFileName);
39};
40
41class Path
42{
43public:
44    typedef uint32_t SimplifyIntegral;
45
46    struct SimplifyFlag
47    {
48        enum 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'.
52            AbsoluteOnly = 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 ".".
60            NoRoot = 0x2,
61        };
62    };
63
64    // A more convenient typesafe way to specify the SimplifyFlag combinations
65    enum SimplifyStyle : SimplifyIntegral
66    {
67        Normal = 0,
68        AbsoluteOnly = SimplifyFlag::AbsoluteOnly,
69        NoRoot = SimplifyFlag::NoRoot,
70        AbsoluteOnlyAndNoRoot = SimplifyFlag::AbsoluteOnly | SimplifyFlag::NoRoot,
71    };
72
73    enum class Type
74    {
75        Unknown,
76        File,
77        Directory,
78    };
79
80    typedef uint32_t TypeFlags;
81    struct TypeFlag
82    {
83        enum Enum : TypeFlags
84        {
85            Unknown = TypeFlags(1) << int(Type::Unknown),
86            File = TypeFlags(1) << int(Type::File),
87            Directory = TypeFlags(1) << int(Type::Directory),
88        };
89    };
90
91    class Visitor
92    {
93    public:
94        virtual void accept(Type type, const UnownedStringSlice& filename) = 0;
95    };
96
97    static const char kPathDelimiter = '/';
98
99#if SLANG_WINDOWS_FAMILY
100    static const char kOSCanonicalPathDelimiter = '\\';
101    static const char kOSAlternativePathDelimiter = '/';
102
103#else
104    static const char kOSCanonicalPathDelimiter = '/';
105    static 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
115    static SlangResult find(const String& directoryPath, const char* pattern, Visitor* visitor);
116
117    /// Returns -1 if no separator is found
118    static Index findLastSeparatorIndex(String const& path)
119    {
120        return findLastSeparatorIndex(path.getUnownedSlice());
121    }
122    static Index findLastSeparatorIndex(UnownedStringSlice const& path);
123    /// Finds the index of the last dot in a path, else returns -1
124    static Index findExtIndex(String const& path) { return findExtIndex(path.getUnownedSlice()); }
125    static 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.
130    static bool hasPath(const UnownedStringSlice& path)
131    {
132        return findLastSeparatorIndex(path) >= 0;
133    }
134    static bool hasPath(const String& path) { return findLastSeparatorIndex(path) >= 0; }
135
136    static String replaceExt(const String& path, const char* newExt);
137    static String getFileName(const String& path);
138    static String getPathWithoutExt(const String& path);
139
140    static String getPathExt(const String& path) { return getPathExt(path.getUnownedSlice()); }
141    static UnownedStringSlice getPathExt(const UnownedStringSlice& path);
142
143    static String getParentDirectory(const String& path);
144
145    static String getFileNameWithoutExt(const String& path);
146
147    static String combine(const String& path1, const String& path2);
148    static String combine(const String& path1, const String& path2, const String& path3);
149
150    /// Combine path sections and store the result in outBuilder
151    static void combineIntoBuilder(
152        const UnownedStringSlice& path1,
153        const UnownedStringSlice& path2,
154        StringBuilder& outBuilder);
155
156    /// Append a path, taking into account path separators onto the end of ioBuilder
157    static void append(StringBuilder& ioBuilder, const UnownedStringSlice& path);
158
159    static bool createDirectory(const String& path);
160    static bool createDirectoryRecursive(const String& path);
161
162    /// Accept either style of delimiter
163    SLANG_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
168    static 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 []
175    static void split(const UnownedStringSlice& path, List<UnownedStringSlice>& splitOut);
176
177    /// Strips .. and . as much as it can
178    static String simplify(const UnownedStringSlice& path);
179    static 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
183    static SlangResult simplify(
184        const UnownedStringSlice& path,
185        SimplifyStyle style,
186        StringBuilder& outPath);
187    static SlangResult simplify(const String& path, SimplifyStyle style, StringBuilder& outPath)
188    {
189        return simplify(path.getUnownedSlice(), style, outPath);
190    }
191    static SlangResult simplify(const char* path, SimplifyStyle style, StringBuilder& outPath)
192    {
193        return simplify(UnownedStringSlice(path), style, outPath);
194    }
195
196    /// Simplifies the path split up
197    static void simplify(List<UnownedStringSlice>& ioSplit);
198
199    /// Join the parts of the path to produce an output path
200    static void join(const UnownedStringSlice* slices, Index count, StringBuilder& out);
201
202    /// Returns true if the path is absolute
203    static bool isAbsolute(const UnownedStringSlice& path);
204    static bool isAbsolute(const String& path) { return isAbsolute(path.getUnownedSlice()); }
205
206    /// Returns true if path contains contains an element of . or ..
207    static bool hasRelativeElement(const UnownedStringSlice& path);
208    static bool hasRelativeElement(const String& path)
209    {
210        return 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
217    static 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
225    static 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.
229    static String getCurrentPath();
230
231    /// Returns the executable path
232    /// @return The path in platform native format. Returns empty string if failed.
233    static 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
239    static 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
245    static 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
250    static SlangResult removeNonEmpty(const String& path);
251
252    static bool equals(String path1, String path2);
253
254    /// Turn `path` into a relative path from base.
255    static String getRelativePath(String base, String path);
256};
257
258struct URI
259{
260    String uri;
261    bool operator==(const URI& other) const { return uri == other.uri; }
262    bool operator!=(const URI& other) const { return uri != other.uri; }
263
264    HashCode getHashCode() const { return uri.getHashCode(); }
265
266    bool isLocalFile() { return uri.startsWith("file://"); };
267    String getPath() const;
268    StringSlice getProtocol() const;
269
270    static URI fromLocalFilePath(UnownedStringSlice path);
271    static URI fromString(UnownedStringSlice uriString);
272    static 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:
280    enum class LockType
281    {
282        Exclusive,
283        Shared,
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.
289    SlangResult open(const String& fileName);
290
291    /// Closes the lock file.
292    void close();
293
294    /// Returns true if the lock file is open.
295    bool 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.
300    SlangResult 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.
305    SlangResult lock(LockType lockType = LockType::Exclusive);
306
307    /// Release the lock.
308    /// @return SLANG_OK on success.
309    SlangResult unlock();
310
311    LockFile();
312    ~LockFile();
313
314private:
315    LockFile(const LockFile&) = delete;
316    LockFile(LockFile&&) = delete;
317    LockFile& operator=(const LockFile&) = delete;
318    LockFile& operator=(LockFile&&) = delete;
319
320#if SLANG_WINDOWS_FAMILY
321    void* m_fileHandle;
322#else
323    int m_fileHandle;
324#endif
325    bool m_isOpen;
326};
327
328class LockFileGuard
329{
330public:
331    LockFileGuard(LockFile& lockFile, LockFile::LockType lockType = LockFile::LockType::Exclusive)
332        : m_lockFile(lockFile)
333    {
334        m_lockFile.lock(lockType);
335    }
336
337    ~LockFileGuard() { m_lockFile.unlock(); }
338
339private:
340    LockFileGuard(const LockFileGuard&) = delete;
341    LockFileGuard(LockFileGuard&&) = delete;
342    LockFileGuard& operator=(const LockFileGuard&) = delete;
343    LockFileGuard& operator=(LockFileGuard&&) = delete;
344
345    LockFile& m_lockFile;
346};
347
348} // namespace Slang
349
350#endif