#ifndef VG_IO_H
#define VG_IO_H
+#include "vg.h"
#include "vg_stdint.h"
#include "vg_platform.h"
#include "vg_log.h"
#include "vg_mem.h"
-#include <stdio.h>
-#include <errno.h>
+
+
+typedef struct vg_dir vg_dir;
+#ifndef _WIN32
+ #include <dirent.h>
+ struct vg_dir{
+ DIR *h;
+ struct dirent *data;
+ u32 index;
+ };
+#else
+ #include <windows.h>
+ #include <fileapi.h>
+ struct vg_dir{
+ HANDLE h;
+ WIN32_FIND_DATA data;
+ u32 index;
+ };
+#endif
+
+enum vg_entry_type{
+ k_vg_entry_type_unknown,
+ k_vg_entry_type_file,
+ k_vg_entry_type_dir
+};
+
+static 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;
+}
+
+static const char *vg_dir_entry_name( vg_dir *dir ){
+#ifdef _WIN32
+ return dir->data.cFileName;
+#else
+ return dir->data->d_name;
+#endif
+}
+
+static 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;
+}
+
+static 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
+}
+
+static 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;
+}
+
+static 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;
+}
/*
* File I/O
#define VG_FILE_IO_CHUNK_SIZE 1024*256
-VG_STATIC void vg_file_print_invalid( FILE *fp )
+#ifdef __GNUC__
+ #ifndef __clang__
+ #pragma GCC push_options
+ #pragma GCC optimize ("O3")
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+ #endif
+#endif
+
+static void vg_file_print_invalid( FILE *fp )
{
- if( feof( fp ))
- {
+ if( feof( fp )) {
vg_error( "mdl_open: header too short\n" );
}
- else
- {
+ else{
if( ferror( fp ))
vg_error( "mdl_open: %s\n", strerror(errno) );
else
}
/* read entire binary file */
-VG_STATIC void *vg_file_read( void *lin_alloc, const char *path, u32 *size )
+static void *vg_file_read( void *lin_alloc, const char *path, u32 *size )
{
FILE *f = fopen( path, "rb" );
- if( f )
- {
+ if( f ){
void *buffer = vg_linear_alloc( lin_alloc, 0 );
u64 current = 0;
/* read in chunks */
- for( u32 i=0; 1; i++ )
- {
+ for( u32 i=0; 1; i++ ){
buffer = vg_linear_extend( lin_alloc, buffer, 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 ) )
- {
+ if( l != VG_FILE_IO_CHUNK_SIZE ){
+ if( feof( f ) ){
break;
}
- else
- {
- if( ferror( f ) )
- {
+ else{
+ if( ferror( f ) ){
fclose(f);
- vg_fatal_exit_loop( "read error" );
+ vg_fatal_error( "read error" );
}
- else
- {
+ else{
fclose(f);
- vg_fatal_exit_loop( "unknown error codition" );
+ vg_fatal_error( "unknown error codition" );
}
}
}
}
- buffer = vg_linear_resize( lin_alloc, buffer, current );
+ buffer = vg_linear_resize( lin_alloc, buffer, vg_align8(current) );
fclose( f );
*size = (u32)current;
-
return buffer;
}
- else
- {
+ else{
vg_error( "vg_disk_open_read: %s\n", strerror(errno) );
return NULL;
}
}
/* read entire file and append a null on the end */
-VG_STATIC char *vg_file_read_text( void *lin_alloc, const char *path, u32 *sz )
+static char *vg_file_read_text( void *lin_alloc, const char *path, u32 *sz )
{
u32 size;
char *str = vg_file_read( lin_alloc, path, &size );
}
-VG_STATIC int vg_asset_write( const char *path, void *data, i64 size )
-{
+static int vg_asset_write( const char *path, void *data, i64 size ){
FILE *f = fopen( path, "wb" );
- if( f )
- {
+ if( f ){
fwrite( data, size, 1, f );
fclose( f );
return 1;
}
- else
- {
+ else{
return 0;
}
}
+/* TODO: error handling if read fails */
+static 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 );
+}
+
+static 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;
+}
+
+#ifdef __GNUC__
+ #ifndef __clang__
+ #pragma GCC pop_options
+ #pragma GCC diagnostic pop
+ #endif
+#endif
+
#endif /* VG_IO_H */