maug
Quick and dirty C mini-augmentation library.
Loading...
Searching...
No Matches
mfile.h
Go to the documentation of this file.
1
2#ifndef MFILE_H
3#define MFILE_H
4
5#if !defined( MFILE_MMAP ) && \
6 !defined( RETROFLAT_API_WINCE ) && \
7 !defined( RETROFLAT_API_PALM )
8# include <sys/stat.h>
9#endif /* !MFILE_MMAP */
10
11/* TODO: async file_open() call that kicks off download to mem buffer that can
12 * be checked with looped check function.
13 */
14
20
24
25#ifndef MAUG_PATH_MAX
27# define MAUG_PATH_MAX 256
28#endif /* !MAUG_PATH_MAX */
29
38
42#define MFILE_CADDY_TYPE_FILE 0x01
43
47#define MFILE_CADDY_TYPE_MEM_BUFFER 0x80
48 /* maug_mfile_types */
50
51#define MFILE_FLAG_READ_ONLY 0x01
52
60
66#define MFILE_READ_FLAG_LSBF 0x01
67
73#define MFILE_READ_FLAG_MSBF 0x01
74
75#ifndef MFILE_TRACE_LVL
76# define MFILE_TRACE_LVL 0
77#endif /* !MFILE_TRACE_LVL */
78
79#ifndef MFILE_TRACE_CONTENTS_LVL
80# define MFILE_TRACE_CONTENTS_LVL 0
81#endif /* !MFILE_TRACE_CONTENTS_LVL */
82
83struct MFILE_CADDY;
84
85typedef off_t (*mfile_has_bytes_t)( struct MFILE_CADDY* p_file );
86typedef MERROR_RETVAL (*mfile_read_byte_t)(
87 struct MFILE_CADDY* p_file, uint8_t* buf );
88typedef MERROR_RETVAL (*mfile_read_block_t)(
89 struct MFILE_CADDY* p_file, uint8_t* buf, size_t buf_sz );
90typedef MERROR_RETVAL (*mfile_seek_t)( struct MFILE_CADDY* p_file, off_t pos );
91typedef MERROR_RETVAL (*mfile_read_int_t)(
92 struct MFILE_CADDY* p_file, uint8_t* buf, size_t buf_sz, uint8_t flags );
93typedef MERROR_RETVAL (*mfile_read_line_t)(
94 struct MFILE_CADDY* p_file, char* buf, off_t buf_sz, uint8_t flags );
95
96/* TODO: Don't load platform-specific file stuff if MVFS is enabled. */
97#include <mrapifil.h>
98
101 uint8_t type;
103 union MFILE_HANDLE h;
104 off_t sz;
105 off_t last_read;
109 uint8_t* mem_buffer;
110 uint8_t flags;
111 mfile_has_bytes_t has_bytes;
112 mfile_read_byte_t read_byte;
113 mfile_read_block_t read_block;
114 mfile_seek_t seek;
115 mfile_read_int_t read_int;
116 mfile_read_line_t read_line;
117};
118
119typedef struct MFILE_CADDY mfile_t;
120
121off_t mfile_file_has_bytes( struct MFILE_CADDY* p_file );
122
123MERROR_RETVAL mfile_file_read_byte( struct MFILE_CADDY* p_file, uint8_t* buf );
124
125MERROR_RETVAL mfile_file_read_block(
126 struct MFILE_CADDY* p_file, uint8_t* buf, size_t buf_sz );
127
128MERROR_RETVAL mfile_file_read_int(
129 struct MFILE_CADDY* p_f, uint8_t* buf, size_t buf_sz, uint8_t flags );
130
131MERROR_RETVAL mfile_file_seek( struct MFILE_CADDY* p_file, off_t pos );
132
133MERROR_RETVAL mfile_file_read_line(
134 struct MFILE_CADDY* p_f, char* buffer, off_t buffer_sz, uint8_t flags );
135
136#define mfile_check_lock( p_file ) (NULL != (p_file)->mem_buffer)
137
138#define mfile_get_sz( p_file ) ((p_file)->sz)
139
143MERROR_RETVAL mfile_lock_buffer( MAUG_MHANDLE, off_t, mfile_t* p_file );
144
149MERROR_RETVAL mfile_open_read( const char* filename, mfile_t* p_file );
150
154void mfile_close( mfile_t* p_file );
155
156#ifdef MFILE_C
157
158#include <mrapifil.h>
159
160#ifdef MVFS_ENABLED
161# include <mvfs.h>
162#endif /* MVFS_ENABLED */
163
164MERROR_RETVAL mfile_file_read_int(
165 struct MFILE_CADDY* p_file, uint8_t* buf, size_t buf_sz, uint8_t flags
166) {
167 MERROR_RETVAL retval = MERROR_OK;
168
169 if(
170#ifdef MAUG_LSBF
172#elif defined( MAUG_MSBF )
174#endif
175 ) {
176 debug_printf( MFILE_TRACE_LVL, "reading integer forward" );
177 /* Shrink the buffer moving right and read into it. */
178 retval = p_file->read_block( p_file, buf, buf_sz );
179
180 } else {
181 debug_printf( MFILE_TRACE_LVL, "reading integer reversed" );
182 /* Move to the end of the output buffer and read backwards. */
183 while( 0 < buf_sz ) {
184 retval = p_file->read_byte( p_file, (buf + (buf_sz - 1)) );
185 maug_cleanup_if_not_ok();
186 buf_sz--;
187 }
188 }
189
190cleanup:
191
192 return retval;
193}
194
195/* === */
196
197off_t mfile_mem_has_bytes( struct MFILE_CADDY* p_file ) {
198 return p_file->sz - p_file->mem_cursor;
199}
200
201/* === */
202
203MERROR_RETVAL mfile_mem_read_byte( struct MFILE_CADDY* p_file, uint8_t* buf ) {
204 return p_file->read_block( p_file, buf, 1 );
205}
206
207/* === */
208
209MERROR_RETVAL mfile_mem_read_block(
210 struct MFILE_CADDY* p_file, uint8_t* buf, size_t buf_sz
211) {
212
213 if( p_file->mem_cursor >= p_file->sz ) {
214 return MERROR_FILE;
215 }
216
217 while( 0 < buf_sz-- ) {
218 *(buf++) = p_file->mem_buffer[p_file->mem_cursor++];
219 }
220
221 return MERROR_OK;
222}
223
224/* === */
225
226MERROR_RETVAL mfile_mem_seek( struct MFILE_CADDY* p_file, off_t pos ) {
227 MERROR_RETVAL retval = MERROR_OK;
228
229 assert( MFILE_CADDY_TYPE_MEM_BUFFER == p_file->type );
230
231 p_file->mem_cursor = pos;
232
233 debug_printf( MFILE_TRACE_LVL,
234 "seeking memory buffer to position " OFF_T_FMT " (" OFF_T_FMT ")",
235 pos, p_file->mem_cursor );
236
237 return retval;
238}
239
240/* === */
241
242MERROR_RETVAL mfile_mem_read_line(
243 struct MFILE_CADDY* p_f, char* buffer, off_t buffer_sz, uint8_t flags
244) {
245 MERROR_RETVAL retval = MERROR_OK;
246 off_t i = 0;
247
248 assert( MFILE_CADDY_TYPE_MEM_BUFFER == p_f->type );
249
250 while( i < buffer_sz - 1 && p_f->has_bytes( p_f ) ) {
251 /* Check for potential overflow. */
252 if( i + 1 >= buffer_sz ) {
253 error_printf( "overflow reading string from file!" );
254 retval = MERROR_FILE;
255 break;
256 }
257
258 p_f->read_int( p_f, (uint8_t*)&(buffer[i]), 1, 0 );
259 if( '\n' == buffer[i] ) {
260 /* Break on newline and overwrite it below. */
261 break;
262 }
263 i++;
264 }
265
266 assert( i < buffer_sz ); /* while() above stops before buffer_sz! */
267
268 /* Append a null terminator. */
269 buffer[i] = '\0';
270
271 return retval;
272}
273
274/* === */
275
277 MAUG_MHANDLE handle, off_t handle_sz, mfile_t* p_file
278) {
279 MERROR_RETVAL retval = MERROR_OK;
280
281 debug_printf( 1,
282 "locking handle %p as file %p (" OFF_T_FMT " bytes)...",
283 handle, p_file, handle_sz );
284
285 maug_mzero( p_file, sizeof( struct MFILE_CADDY ) );
286 maug_mlock( handle, p_file->mem_buffer );
288
289 p_file->has_bytes = mfile_mem_has_bytes;
290 p_file->read_byte = mfile_mem_read_byte;
291 p_file->read_block = mfile_mem_read_block;
292 p_file->read_int = mfile_file_read_int;
293 p_file->seek = mfile_mem_seek;
294 p_file->read_line = mfile_mem_read_line;
295
296 p_file->sz = handle_sz;
297
298 return retval;
299}
300
301/* === */
302
303MERROR_RETVAL mfile_open_read( const char* filename, mfile_t* p_file ) {
304 MERROR_RETVAL retval = MERROR_OK;
305# if defined( MVFS_ENABLED )
306 size_t i = 0;
307# elif defined( MFILE_MMAP )
308 uint8_t* bytes_ptr = NULL;
309 struct stat st;
310 int in_file = 0;
311# else
312# endif /* MFILE_MMAP */
313
314 /* MAUG_MHANDLE* p_bytes_ptr_h, off_t* p_bytes_sz */
315
316 /* TODO: Move MVFS stuff into its own platform handler or something? */
317# if defined( MVFS_ENABLED )
318
319 while( NULL != gc_mvfs_data[i] ) {
320 if( 0 == strcmp( filename, gc_mvfs_filenames[i] ) ) {
321 debug_printf( 1, "found file \"%s\" at VFS index: " SIZE_T_FMT
322 " (size: " OFF_T_FMT " bytes)",
323 filename, i, *(gc_mvfs_lens[i]) );
324 break;
325 }
326 i++;
327 }
328
329 if( NULL == gc_mvfs_data[i] ) {
330 retval = MERROR_FILE;
331 error_printf( "file \"%s\" not found in VFS!", filename );
332 goto cleanup;
333 }
334
336
337 p_file->has_bytes = mfile_mem_has_bytes;
338 p_file->read_byte = mfile_mem_read_byte;
339 p_file->read_block = mfile_mem_read_block;
340 p_file->read_int = mfile_file_read_int;
341 p_file->seek = mfile_mem_seek;
342 p_file->read_line = mfile_mem_read_line;
343
344 p_file->flags = MFILE_FLAG_READ_ONLY;
345 p_file->mem_buffer = gc_mvfs_data[i];
346 p_file->sz = *(gc_mvfs_lens[i]);
347 p_file->mem_cursor = 0;
348
349cleanup:
350
351# else
352
353 /* Call the platform-specific actual file opener from mrapifil.h. */
354 retval = mfile_plt_open_read( filename, p_file );
355
356# endif /* MVFS_ENABLED */
357
358 return retval;
359}
360
361/* === */
362
363void mfile_close( mfile_t* p_file ) {
364# ifdef MFILE_MMAP
365 munmap( bytes_ptr_h, bytes_sz );
366# else
367 /* maug_mfree( bytes_ptr_h ); */
368 switch( p_file->type ) {
369 case 0:
370 /* Do nothing silently. */
371 break;
372
374 mfile_plt_close( p_file );
375 p_file->type = 0;
376 break;
377
379 if( NULL != p_file->mem_buffer ) {
380 maug_munlock( p_file->h.mem, p_file->mem_buffer );
381 debug_printf( 1, "unlocked handle %p from file %p...",
382 p_file->h.mem, p_file );
383 p_file->type = 0;
384 }
385 break;
386
387 default:
388 error_printf( "unknown file type: %d", (p_file)->type );
389 break;
390 }
391# endif /* MFILE_MMAP */
392}
393
394#endif /* MFILE_C */
395 /* maug_mfile */
397
398#endif /* !MFILE_H */
399
int MERROR_RETVAL
Return type indicating function returns a value from this list.
Definition merror.h:19
#define maug_mzero(ptr, sz)
Zero the block of memory pointed to by ptr.
Definition mmem.h:65
#define MFILE_CADDY_TYPE_FILE
A standard UNIX file.
Definition mfile.h:42
#define MFILE_CADDY_TYPE_MEM_BUFFER
An array of bytes in memory abstracted through this library.
Definition mfile.h:47
#define MFILE_READ_FLAG_MSBF
Flag for mfile_read_int_t() indicating integer should always be read most significant byte first.
Definition mfile.h:73
#define MFILE_READ_FLAG_LSBF
Flag for mfile_read_int_t() indicating integer should always be read least significant byte first.
Definition mfile.h:66
MERROR_RETVAL mfile_open_read(const char *filename, mfile_t *p_file)
Open a file and read it into memory or memory-map it.
void mfile_close(mfile_t *p_file)
Close a file opened with mfile_open_read().
MERROR_RETVAL mfile_lock_buffer(MAUG_MHANDLE, off_t, mfile_t *p_file)
Lock a buffer and assign it to an mfile_t to read/write.
Definition mfile.h:99
off_t mem_cursor
Current position if its type is MFILE_CADDY_TYPE_MEM_BUFFER.
Definition mfile.h:107
uint8_t type
The RetroFile Types flag describing this file.
Definition mfile.h:101
union MFILE_HANDLE h
The physical handle or pointer to access the file by.
Definition mfile.h:103
uint8_t * mem_buffer
Locked pointer for MFILE_HANDLE::mem.
Definition mfile.h:109