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