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( DEBUG_THRESHOLD )
6# define DEBUG_THRESHOLD 1
7#endif /* !DEBUG_THRESHOLD */
8
9#ifndef UPRINTF_BUFFER_SZ_MAX
10# define UPRINTF_BUFFER_SZ_MAX 1024
11#endif /* !UPRINTF_BUFFER_SZ_MAX */
12
13#if !defined( MFILE_MMAP ) && \
14 !defined( RETROFLAT_API_WINCE ) && \
15 !defined( RETROFLAT_API_PALM )
16# include <sys/stat.h>
17#endif /* !MFILE_MMAP */
18
19/* TODO: async file_open() call that kicks off download to mem buffer that can
20 * be checked with looped check function.
21 */
22
28
32
33#ifndef MAUG_PATH_SZ_MAX
35# define MAUG_PATH_SZ_MAX 256
36#endif /* !MAUG_PATH_SZ_MAX */
37
46
50#define MFILE_CADDY_TYPE_FILE 0x01
51
55#define MFILE_CADDY_TYPE_MEM_BUFFER 0x80
56 /* maug_mfile_types */
58
59#define MFILE_FLAG_READ_ONLY 0x01
60
68
74#define MFILE_READ_FLAG_LSBF 0x01
75
81#define MFILE_READ_FLAG_MSBF 0x01
82
83#define MFILE_ASSIGN_FLAG_TRIM_EXT 0x01
84
85#ifndef MFILE_TRACE_LVL
86# define MFILE_TRACE_LVL 0
87#endif /* !MFILE_TRACE_LVL */
88
89#ifndef MFILE_TRACE_CONTENTS_LVL
90# define MFILE_TRACE_CONTENTS_LVL 0
91#endif /* !MFILE_TRACE_CONTENTS_LVL */
92
99
104
108#define mfile_cmp_path( a, b ) strncmp( a, b, MAUG_PATH_SZ_MAX )
109 /* maug_retroflt_assets */
111
112struct MFILE_CADDY;
113typedef struct MFILE_CADDY mfile_t;
114
115typedef off_t (*mfile_has_bytes_t)( struct MFILE_CADDY* p_file );
116typedef MERROR_RETVAL (*mfile_read_byte_t)(
117 struct MFILE_CADDY* p_file, uint8_t* buf );
118typedef MERROR_RETVAL (*mfile_read_block_t)(
119 struct MFILE_CADDY* p_file, uint8_t* buf, size_t buf_sz );
120typedef MERROR_RETVAL (*mfile_seek_t)( struct MFILE_CADDY* p_file, off_t pos );
121typedef MERROR_RETVAL (*mfile_read_int_t)(
122 struct MFILE_CADDY* p_file, uint8_t* buf, size_t buf_sz, uint8_t flags );
123typedef MERROR_RETVAL (*mfile_read_line_t)(
124 struct MFILE_CADDY* p_file, char* buf, off_t buf_sz, uint8_t flags );
125typedef MERROR_RETVAL (*mfile_printf_t)(
126 struct MFILE_CADDY* p_file, uint8_t flags, const char* fmt, ... );
127
128off_t mfile_mem_has_bytes( struct MFILE_CADDY* p_file );
129MERROR_RETVAL mfile_mem_read_byte( struct MFILE_CADDY* p_file, uint8_t* buf );
130MERROR_RETVAL mfile_mem_read_block(
131 struct MFILE_CADDY* p_file, uint8_t* buf, size_t buf_sz );
132MERROR_RETVAL mfile_mem_seek( struct MFILE_CADDY* p_file, off_t pos );
133MERROR_RETVAL mfile_mem_read_line(
134 struct MFILE_CADDY* p_f, char* buffer, off_t buffer_sz, uint8_t flags );
135MERROR_RETVAL mfile_mem_vprintf(
136 mfile_t* p_file, uint8_t flags, const char* fmt, va_list args );
137
146 struct MFILE_CADDY* p_file, uint8_t flags, const char* fmt, va_list args );
147
148/* Load the platform-specific file API. */
149#include <mrapifil.h>
150#include <mrapilog.h>
151
154 uint8_t type;
156 union MFILE_HANDLE h;
157 off_t sz;
158 off_t last_read;
162 uint8_t* mem_buffer;
163 uint8_t flags;
164 mfile_has_bytes_t has_bytes;
165 mfile_read_byte_t read_byte;
166 mfile_read_block_t read_block;
167 mfile_seek_t seek;
168 mfile_read_int_t read_int;
169 mfile_read_line_t read_line;
170 mfile_printf_t printf;
171 mfile_vprintf_t vprintf;
172};
173
174typedef struct MFILE_CADDY mfile_t;
175
180
181MERROR_RETVAL mfile_assign_path(
182 retroflat_asset_path tgt, const retroflat_asset_path src, uint8_t flags );
183
185
186off_t mfile_file_has_bytes( struct MFILE_CADDY* p_file );
187
188MERROR_RETVAL mfile_file_read_byte( struct MFILE_CADDY* p_file, uint8_t* buf );
189
190MERROR_RETVAL mfile_file_read_block(
191 struct MFILE_CADDY* p_file, uint8_t* buf, size_t buf_sz );
192
193MERROR_RETVAL mfile_file_read_int(
194 struct MFILE_CADDY* p_f, uint8_t* buf, size_t buf_sz, uint8_t flags );
195
196MERROR_RETVAL mfile_file_seek( struct MFILE_CADDY* p_file, off_t pos );
197
198MERROR_RETVAL mfile_file_read_line(
199 struct MFILE_CADDY* p_f, char* buffer, off_t buffer_sz, uint8_t flags );
200
201MERROR_RETVAL mfile_file_printf(
202 struct MFILE_CADDY* p_f, uint8_t flags, const char* fmt, ... );
203
204MERROR_RETVAL mfile_file_vprintf(
205 struct MFILE_CADDY* p_f, uint8_t flags, const char* fmt, va_list args );
206
207#define mfile_check_lock( p_file ) (NULL != (p_file)->mem_buffer)
208
209#define mfile_get_sz( p_file ) ((p_file)->sz)
210
214MERROR_RETVAL mfile_lock_buffer( MAUG_MHANDLE, off_t, mfile_t* p_file );
215
220MERROR_RETVAL mfile_open_read( const char* filename, mfile_t* p_file );
221
222MERROR_RETVAL mfile_open_write( const char* filename, mfile_t* p_file );
223
227void mfile_close( mfile_t* p_file );
228
229#ifdef MFILE_C
230
231#include <mrapifil.h>
232#include <mrapilog.h>
233
234MERROR_RETVAL mfile_assign_path(
235 retroflat_asset_path tgt, const retroflat_asset_path src, uint8_t flags
236) {
237 MERROR_RETVAL retval = MERROR_OK;
238 char* ext_ptr = NULL;
239
240 maug_snprintf( tgt, MAUG_PATH_SZ_MAX, "%s", src );
241
242 if( MFILE_ASSIGN_FLAG_TRIM_EXT == (MFILE_ASSIGN_FLAG_TRIM_EXT & flags) ) {
243 ext_ptr = maug_strrchr( tgt, '.' );
244 if( NULL != ext_ptr ) {
245 *ext_ptr = '\0';
246 }
247 }
248
249 return retval;
250}
251
252/* === */
253
254MERROR_RETVAL mfile_file_read_int(
255 struct MFILE_CADDY* p_file, uint8_t* buf, size_t buf_sz, uint8_t flags
256) {
257 MERROR_RETVAL retval = MERROR_OK;
258
259 if(
260#ifdef MAUG_LSBF
262#elif defined( MAUG_MSBF )
264#endif
265 ) {
266 debug_printf( MFILE_TRACE_LVL, "reading integer forward" );
267 /* Shrink the buffer moving right and read into it. */
268 retval = p_file->read_block( p_file, buf, buf_sz );
269
270 } else {
271 debug_printf( MFILE_TRACE_LVL, "reading integer reversed" );
272 /* Move to the end of the output buffer and read backwards. */
273 while( 0 < buf_sz ) {
274 retval = p_file->read_byte( p_file, (buf + (buf_sz - 1)) );
275 maug_cleanup_if_not_ok();
276 buf_sz--;
277 }
278 }
279
280cleanup:
281
282 return retval;
283}
284
285/* === */
286
287MERROR_RETVAL mfile_file_printf(
288 struct MFILE_CADDY* p_file, uint8_t flags, const char* fmt, ...
289) {
290 MERROR_RETVAL retval = MERROR_OK;
291 va_list vargs;
292
293 va_start( vargs, fmt );
294 retval = p_file->vprintf( p_file, flags, fmt, vargs );
295 va_end( vargs );
296
297 return retval;
298}
299
300/* === */
301
302off_t mfile_mem_has_bytes( struct MFILE_CADDY* p_file ) {
303 return p_file->sz - p_file->mem_cursor;
304}
305
306/* === */
307
308MERROR_RETVAL mfile_mem_read_byte( struct MFILE_CADDY* p_file, uint8_t* buf ) {
309 return p_file->read_block( p_file, buf, 1 );
310}
311
312/* === */
313
314MERROR_RETVAL mfile_mem_read_block(
315 struct MFILE_CADDY* p_file, uint8_t* buf, size_t buf_sz
316) {
317
318 if( p_file->mem_cursor >= p_file->sz ) {
319 return MERROR_FILE;
320 }
321
322 while( 0 < buf_sz-- ) {
323 *(buf++) = p_file->mem_buffer[p_file->mem_cursor++];
324 }
325
326 return MERROR_OK;
327}
328
329/* === */
330
331MERROR_RETVAL mfile_mem_seek( struct MFILE_CADDY* p_file, off_t pos ) {
332 MERROR_RETVAL retval = MERROR_OK;
333
334 assert( MFILE_CADDY_TYPE_MEM_BUFFER == p_file->type );
335
336 p_file->mem_cursor = pos;
337
338 debug_printf( MFILE_TRACE_LVL,
339 "seeking memory buffer to position " OFF_T_FMT " (" OFF_T_FMT ")",
340 pos, p_file->mem_cursor );
341
342 return retval;
343}
344
345/* === */
346
347MERROR_RETVAL mfile_mem_read_line(
348 struct MFILE_CADDY* p_f, char* buffer, off_t buffer_sz, uint8_t flags
349) {
350 MERROR_RETVAL retval = MERROR_OK;
351 off_t i = 0;
352
353 assert( MFILE_CADDY_TYPE_MEM_BUFFER == p_f->type );
354
355 while( i < buffer_sz - 1 && p_f->has_bytes( p_f ) ) {
356 /* Check for potential overflow. */
357 if( i + 1 >= buffer_sz ) {
358 error_printf( "overflow reading string from file!" );
359 retval = MERROR_FILE;
360 break;
361 }
362
363 p_f->read_int( p_f, (uint8_t*)&(buffer[i]), 1, 0 );
364 if( '\n' == buffer[i] ) {
365 /* Break on newline and overwrite it below. */
366 break;
367 }
368 i++;
369 }
370
371 assert( i < buffer_sz ); /* while() above stops before buffer_sz! */
372
373 /* Append a null terminator. */
374 buffer[i] = '\0';
375
376 return retval;
377}
378
379/* === */
380
381MERROR_RETVAL mfile_mem_vprintf(
382 mfile_t* p_file, uint8_t flags, const char* fmt, va_list args
383) {
384 MERROR_RETVAL retval = MERROR_OK;
385
386 if( MFILE_FLAG_READ_ONLY == (MFILE_FLAG_READ_ONLY & p_file->flags) ) {
387 return MERROR_FILE;
388 }
389
390 /* TODO: Enable writing to memory buffer. */
391 error_printf( "writing to memory buffer not currently supported!" );
392
393 return retval;
394}
395
396/* === */
397
399 MAUG_MHANDLE handle, off_t handle_sz, mfile_t* p_file
400) {
401 MERROR_RETVAL retval = MERROR_OK;
402
403 debug_printf( 1,
404 "locking handle %p as file %p (" OFF_T_FMT " bytes)...",
405 handle, p_file, handle_sz );
406
407 maug_mzero( p_file, sizeof( struct MFILE_CADDY ) );
408 maug_mlock( handle, p_file->mem_buffer );
410
411 p_file->has_bytes = mfile_mem_has_bytes;
412 p_file->read_byte = mfile_mem_read_byte;
413 p_file->read_block = mfile_mem_read_block;
414 p_file->read_int = mfile_file_read_int;
415 p_file->seek = mfile_mem_seek;
416 p_file->read_line = mfile_mem_read_line;
417
418 p_file->sz = handle_sz;
419
420 return retval;
421}
422
423/* === */
424
425MERROR_RETVAL mfile_open_read( const char* filename, mfile_t* p_file ) {
426 MERROR_RETVAL retval = MERROR_OK;
427
428 /* Call the platform-specific actual file opener from mrapifil.h. */
429 retval = mfile_plt_open_read( filename, p_file );
430
431 return retval;
432}
433
434/* === */
435
436MERROR_RETVAL mfile_open_write( const char* filename, mfile_t* p_file ) {
437 MERROR_RETVAL retval = MERROR_OK;
438
439 retval = mfile_plt_open_write( filename, p_file );
440
441 return retval;
442}
443
444/* === */
445
446void mfile_close( mfile_t* p_file ) {
447# ifdef MFILE_MMAP
448 munmap( bytes_ptr_h, bytes_sz );
449# else
450 /* maug_mfree( bytes_ptr_h ); */
451 switch( p_file->type ) {
452 case 0:
453 /* Do nothing silently. */
454 break;
455
457 mfile_plt_close( p_file );
458 p_file->type = 0;
459 break;
460
462 if( NULL != p_file->mem_buffer ) {
463 maug_munlock( p_file->h.mem, p_file->mem_buffer );
464 debug_printf( 1, "unlocked handle %p from file %p...",
465 p_file->h.mem, p_file );
466 p_file->type = 0;
467 }
468 break;
469
470 default:
471 error_printf( "unknown file type: %d", (p_file)->type );
472 break;
473 }
474# endif /* MFILE_MMAP */
475}
476
477#endif /* MFILE_C */
478 /* maug_mfile */
480
481#endif /* !MFILE_H */
482
int MERROR_RETVAL
Return type indicating function returns a value from this list.
Definition merror.h:19
#define MFILE_CADDY_TYPE_FILE
A standard UNIX file.
Definition mfile.h:50
#define MFILE_CADDY_TYPE_MEM_BUFFER
An array of bytes in memory abstracted through this library.
Definition mfile.h:55
#define MAUG_PATH_SZ_MAX
Maximum size allocated for asset paths.
Definition mfile.h:35
#define MFILE_READ_FLAG_MSBF
Flag for mfile_read_int_t() indicating integer should always be read most significant byte first.
Definition mfile.h:81
MERROR_RETVAL(* mfile_vprintf_t)(struct MFILE_CADDY *p_file, uint8_t flags, const char *fmt, va_list args)
Callback to printf the given format string, replacing tokens from the providied pre-initialized list ...
Definition mfile.h:145
#define MFILE_READ_FLAG_LSBF
Flag for mfile_read_int_t() indicating integer should always be read least significant byte first.
Definition mfile.h:74
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.
char retroflat_asset_path[MAUG_PATH_SZ_MAX+1]
Path/name used to load an asset from disk.
Definition mfile.h:103
Definition mfile.h:152
off_t mem_cursor
Current position if its type is MFILE_CADDY_TYPE_MEM_BUFFER.
Definition mfile.h:160
uint8_t type
The RetroFile Types flag describing this file.
Definition mfile.h:154
union MFILE_HANDLE h
The physical handle or pointer to access the file by.
Definition mfile.h:156
uint8_t * mem_buffer
Locked pointer for MFILE_HANDLE::mem.
Definition mfile.h:162