X-Git-Url: https://harrygodden.com/git/?p=vg.git;a=blobdiff_plain;f=vg_io.c;fp=vg_io.c;h=76e8ca3a0d0e9c8955d8cda95363fcaf50dda64f;hp=0000000000000000000000000000000000000000;hb=3b14f3dcd5bf9dd3c85144f2123d667bfa4bb63f;hpb=fce86711735b15bff37de0f70716808410fcf269 diff --git a/vg_io.c b/vg_io.c new file mode 100644 index 0000000..76e8ca3 --- /dev/null +++ b/vg_io.c @@ -0,0 +1,235 @@ +/* Copyright (C) 2021-2024 Harry Godden (hgn) - All Rights Reserved */ + +#include "vg_io.h" +#include "vg_platform.h" +#include "vg_log.h" +#include "vg_mem.h" +#include +#include + +int vg_dir_open( vg_dir *dir, const char *name ) +{ +#ifdef _WIN32 + char q_buf[4096]; + vg_str q; + vg_strnull( &q, q_buf, 4096 ); + vg_strcat( &q, name ); + vg_strcat( &q, "/*" ); + if( !vg_strgood(&q) ) return 0; + + vg_info( "FindFirstFile( '%s' )\n", q.buffer ); + dir->h = FindFirstFile( q.buffer, &dir->data ); + if( dir->h == INVALID_HANDLE_VALUE ){ + if( GetLastError() == ERROR_FILE_NOT_FOUND ){ + dir->index = 0; + return 1; + } + else return 0; + } +#else + dir->h = opendir( name ); + if( !dir->h ) return 0; +#endif + dir->index = 1; + return 1; +} + +const char *vg_dir_entry_name( vg_dir *dir ) +{ +#ifdef _WIN32 + return dir->data.cFileName; +#else + return dir->data->d_name; +#endif +} + +int vg_dirskip( vg_dir *dir ) +{ + const char *s = vg_dir_entry_name(dir); +#ifdef _WIN32 + if( dir->data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN ) return 1; +#endif + if( s[0] == '.' ){ + if( s[1] == '\0' ) return 1; + else if( s[1] == '.' ){ + if( s[2] == '\0' ) return 1; + } + } + return 0; +} + +int vg_dir_next_entry( vg_dir *dir ) +{ +#ifdef _WIN32 + if( dir->index == 0 ) return 0; + if( dir->index > 1 ) { + dir->index ++; + if( !FindNextFile( dir->h, &dir->data ) ) return 0; + } + while( vg_dirskip(dir) ){ + dir->index ++; + if( !FindNextFile( dir->h, &dir->data ) ) return 0; + } + if( dir->index == 1 ) dir->index ++; + return 1; +#else + while( (dir->data = readdir(dir->h)) ){ + dir->index ++; + if( !vg_dirskip(dir) ) break; + } + if( dir->data ) return 1; + else return 0; +#endif +} + +enum vg_entry_type vg_dir_entry_type( vg_dir *dir ) +{ +#ifdef _WIN32 + if( dir->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) + return k_vg_entry_type_dir; + return k_vg_entry_type_file; /* sketchy? */ +#else + if( dir->data->d_type == DT_DIR ) return k_vg_entry_type_dir; + if( dir->data->d_type == DT_REG ) return k_vg_entry_type_file; +#endif + return 0; +} + +void vg_dir_close( vg_dir *dir ) +{ +#ifdef _WIN32 + if( dir->index ) FindClose( dir->h ); + dir->h = INVALID_HANDLE_VALUE; +#else + closedir( dir->h ); + dir->h = NULL; + dir->data = NULL; +#endif + dir->index = 0; +} + +void vg_file_print_invalid( FILE *fp ) +{ + if( feof( fp )) { + vg_error( "mdl_open: header too short\n" ); + } + else{ + if( ferror( fp )) + vg_error( "mdl_open: %s\n", strerror(errno) ); + else + vg_error( "mdl_open: unkown failure\n" ); + + } +} + +#define VG_FILE_IO_CHUNK_SIZE 1024*256 + +/* read entire binary file */ +void *vg_file_read( void *lin_alloc, const char *path, u32 *size ) +{ + FILE *f = fopen( path, "rb" ); + if( f ){ + void *buffer = lin_alloc? vg_linear_alloc( lin_alloc, 0 ): + NULL; + u64 current = 0; + + /* read in chunks */ + for( u32 i=0; 1; i++ ){ + if( lin_alloc ) + buffer = vg_linear_extend( lin_alloc,buffer,VG_FILE_IO_CHUNK_SIZE ); + else + buffer = realloc( buffer, current + VG_FILE_IO_CHUNK_SIZE ); + + u64 l = fread( buffer + current, 1, VG_FILE_IO_CHUNK_SIZE, f ); + current += l; + + if( l != VG_FILE_IO_CHUNK_SIZE ){ + if( feof( f ) ){ + break; + } + else{ + if( ferror( f ) ){ + fclose(f); + vg_fatal_error( "read error" ); + } + else{ + fclose(f); + vg_fatal_error( "unknown error codition" ); + } + } + } + } + + if( lin_alloc ) + buffer = vg_linear_resize( lin_alloc, buffer, vg_align8(current) ); + else + buffer = realloc( buffer, vg_align8(current) ); + + fclose( f ); + + *size = (u32)current; + return buffer; + } + else{ + vg_error( "vg_disk_open_read: %s (file: %s)\n", strerror(errno), path ); + return NULL; + } +} + +/* read entire file and append a null on the end */ +char *vg_file_read_text( void *lin_alloc, const char *path, u32 *sz ) +{ + u32 size; + char *str = vg_file_read( lin_alloc, path, &size ); + + if( !str ) + return NULL; + + /* include null terminator */ + if( lin_alloc ) + str = vg_linear_extend( lin_alloc, str, 1 ); + else + str = realloc( str, size+1 ); + + str[ size ] = '\0'; + *sz = size+1; + + return str; +} + + +int vg_asset_write( const char *path, void *data, i64 size ) +{ + FILE *f = fopen( path, "wb" ); + if( f ){ + fwrite( data, size, 1, f ); + fclose( f ); + return 1; + } + else{ + return 0; + } +} + +/* TODO: error handling if read fails */ +int vg_file_copy( const char *src, const char *dst, void *lin_alloc ) +{ + vg_info( "vg_file_copy( %s -> %s )\n", src, dst ); + u32 size; + void *data = vg_file_read( lin_alloc, src, &size ); + return vg_asset_write( dst, data, size ); +} + +const char *vg_path_filename( const char *path ) +{ + const char *base = path; + + for( int i=0; i<1024; i++ ){ + if( path[i] == '\0' ) break; + if( path[i] == '/' ){ + base = path+i+1; + } + } + + return base; +}