1#pragma once
  2
  3#include <stdarg.h>
  4#include <uchar.h>
  5
  6#include <fcntl.h>
  7
  8#include <pw_types.h>
  9
 10#ifdef __cplusplus
 11extern "C" {
 12#endif
 13
 14/*
 15 * File type supports the following interfaces:
 16 *  - Fd
 17 *  - File
 18 *  - Reader
 19 *  - Writer
 20 */
 21
 22extern uint16_t PwTypeId_File;
 23
 24#define pw_is_file(value)      pw_is_subtype((value), PwTypeId_File)
 25#define pw_assert_file(value)  pw_assert(pw_is_file(value))
 26
 27
 28/*
 29 * In addition to interfaces supported by File, BufferedFile type also supports:
 30 *  - BufferedFile
 31 *  - LineReader
 32 *
 33 * LineReader has dual purpose. Its `read_line`, `unread_line` can be used as normal
 34 * methods, but when wrapped with `start` and `stop`, it can be considered as a singleton
 35 * iterator, comprised of both iterable and iterator.
 36 *
 37 * This means nested iterations aren't possible but they do not make
 38 * sense for files either.
 39 */
 40
 41extern uint16_t PwTypeId_BufferedFile;
 42
 43#define pw_is_buffered_file(value)      pw_is_subtype((value), PwTypeId_BufferedFile)
 44#define pw_assert_buffered_file(value)  pw_assert(pw_is_buffered_file(value))
 45
 46typedef struct {
 47    PwCtorArgs* next;
 48    uint16_t type_id;
 49
 50    unsigned read_bufsize;
 51    unsigned write_bufsize;
 52
 53} PwBufferedFileCtorArgs;
 54
 55
 56/****************************************************************
 57 * File interface
 58 */
 59
 60extern uint16_t PwInterfaceId_File;
 61
 62PW_METHOD_BEGIN(File, open)
 63    bool (*PwFunc_File_open)(PwMethod_File_open* mthis, PwValuePtr self, PwValuePtr file_name, int flags, mode_t mode)
 64PW_METHOD_END(File, open)
 65/*
 66 * Open or create file with `open` function from standard C library.
 67 * `mode` is unused when file is not created
 68 */
 69
 70PW_METHOD_BEGIN(File, get_name)
 71    bool (*PwFunc_File_get_name)(PwMethod_File_get_name* mthis, PwValuePtr self, PwValuePtr result)
 72PW_METHOD_END(File, get_name)
 73/*
 74 * Get file name.
 75 */
 76
 77PW_METHOD_BEGIN(File, set_name)
 78    bool (*PwFunc_File_set_name)(PwMethod_File_set_name* mthis, PwValuePtr self, PwValuePtr file_name)
 79PW_METHOD_END(File, set_name)
 80/*
 81 * Set file name.
 82 * This works only if file descriptor was set with `set_fd` method.
 83 */
 84
 85PW_METHOD_BEGIN(File, seek)
 86    bool (*PwFunc_File_seek)(PwMethod_File_seek* mthis, PwValuePtr self, off_t offset, int whence, off_t* position)
 87PW_METHOD_END(File, seek)
 88/*
 89 * XXX all clear but a good comment would be good
 90 * position can be nullptr
 91 */
 92
 93PW_METHOD_BEGIN(File, tell)
 94    bool (*PwFunc_File_tell)(PwMethod_File_tell* mthis, PwValuePtr self, off_t* position)
 95PW_METHOD_END(File, tell)
 96/*
 97 * XXX all clear but a good comment would be good
 98 */
 99
100#define PW_FILE_INTERFACE_METHODS  \
101    X(open,     1)  \
102    X(get_name, 1)  \
103    X(set_name, 1)  \
104    X(seek,     1)  \
105    X(tell)
106    // TODO truncate, etc.
107
108PW_INTERFACE_BEGIN(File)
109#define X(name, ...) PwMethod_File_##name name;
110    PW_FILE_INTERFACE_METHODS
111#undef X
112PW_INTERFACE_END(File)
113
114
115/****************************************************************
116 * BufferedFile interface
117 */
118
119extern uint16_t PwInterfaceId_BufferedFile;
120
121PW_METHOD_BEGIN(BufferedFile, flush)
122    bool (*PwFunc_BufferedFile_flush)(PwMethod_BufferedFile_flush* mthis, PwValuePtr self)
123PW_METHOD_END(BufferedFile, flush)
124/*
125 * Flush write buffer.
126 */
127
128#define PW_BUFFERED_FILE_INTERFACE_METHODS  \
129    X(flush)
130
131PW_INTERFACE_BEGIN(BufferedFile)
132#define X(name, ...) PwMethod_BufferedFile_##name name;
133    PW_BUFFERED_FILE_INTERFACE_METHODS
134#undef X
135PW_INTERFACE_END(BufferedFile)
136
137
138/****************************************************************
139 * Shorthand functions
140 */
141
142// `pw_file_open` and `pw_file_from_fd` return BufferedFile
143// with read buffer equals to page size and with no write bufer
144
145#define pw_file_open(file_name, flags, mode, result) _Generic((file_name), \
146             char*: _pw_file_open_ascii,  \
147          char8_t*: _pw_file_open_utf8,   \
148         char32_t*: _pw_file_open_utf32,  \
149        PwValuePtr: _pw_file_open         \
150    )((file_name), (flags), (mode), (result))
151
152[[nodiscard]] bool _pw_file_open(PwValuePtr file_name, int flags, mode_t mode, PwValuePtr result);
153
154[[nodiscard]] static inline bool _pw_file_open_ascii(char*     file_name, int flags, mode_t mode, PwValuePtr result) { _PwValue fname = PwStaticString(file_name); return _pw_file_open(&fname, flags, mode, result); }
155[[nodiscard]] static inline bool _pw_file_open_utf8 (char8_t*  file_name, int flags, mode_t mode, PwValuePtr result) { PwValue fname = PW_NULL; if (!pw_create_string(file_name, &fname)) { return false; } return _pw_file_open(&fname, flags, mode, result); }
156[[nodiscard]] static inline bool _pw_file_open_utf32(char32_t* file_name, int flags, mode_t mode, PwValuePtr result) { _PwValue fname = PwStaticStringUtf32(file_name); return _pw_file_open(&fname, flags, mode, result); }
157
158
159[[nodiscard]] bool pw_file_from_fd(int fd, bool take_ownership, PwValuePtr result);
160
161[[nodiscard]] static inline bool pw_file_get_name(PwValuePtr file, PwValuePtr result)
162{
163    return pw_call(File, get_name, file, result);
164}
165
166[[nodiscard]] static inline bool pw_file_set_name(PwValuePtr file, PwValuePtr file_name)
167{
168    return pw_call(File, set_name, file, file_name);
169}
170
171[[nodiscard]] static inline bool pw_seek(PwValuePtr file, off_t offset, int whence, off_t* position)
172{
173    return pw_call(File, seek, file, offset, whence, position);
174}
175
176[[nodiscard]] static inline bool pw_tell(PwValuePtr file, off_t* position)
177{
178    return pw_call(File, tell, file, position);
179}
180
181[[nodiscard]] static inline bool pw_flush(PwValuePtr file)
182{
183    return pw_call(BufferedFile, flush, file);
184}
185
186
187/****************************************************************
188 * Miscellaneous functions
189 */
190
191[[nodiscard]] bool pw_file_size(PwValuePtr file_name, off_t* size);
192/*
193 * Return file size as Unsigned or Status if error.
194 */
195
196
197/****************************************************************
198 * Path functions, probably should be separated
199 */
200
201[[nodiscard]] bool pw_basename(PwValuePtr filename, PwValuePtr result);
202[[nodiscard]] bool pw_dirname(PwValuePtr filename, PwValuePtr result);
203
204#define pw_path(result, ...)  \
205    _pw_path_va((result) __VA_OPT__(,) __VA_ARGS__, PwVaEnd())
206
207[[nodiscard]] bool _pw_path_va(PwValuePtr result, ...);
208
209#ifdef __cplusplus
210}
211#endif