Files
LNXSDK/Kha/Backends/Kinc-HL/hl/src/std/file.c
2025-01-22 16:18:30 +01:00

277 lines
7.2 KiB
C

/*
* Copyright (C)2005-2016 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#if defined(__GNUC__) && !defined(__APPLE__)
# define _FILE_OFFSET_BITS 64
#endif
#include <hl.h>
#include <stdio.h>
#ifdef HL_CONSOLE
# include <posix/posix.h>
#endif
#ifdef HL_WIN
#ifdef HL_WIN_DESKTOP
# include <windows.h>
# include <io.h>
# include <fcntl.h>
#else
# include<xdk.h>
#endif
# define fopen(name,mode) _wfopen(name,mode)
# define HL_UFOPEN
#else
#include <errno.h>
#endif
#ifdef HL_WIN_DESKTOP
# define SET_IS_STD(f,b) (f)->is_std = b
#else
# define SET_IS_STD(f,b)
#endif
typedef struct _hl_fdesc hl_fdesc;
struct _hl_fdesc {
void (*finalize)( hl_fdesc * );
FILE *f;
# ifdef HL_WIN_DESKTOP
bool is_std;
# endif
};
static void fdesc_finalize( hl_fdesc *f ) {
if( f->f ) fclose(f->f);
}
HL_PRIM hl_fdesc *hl_file_open( vbyte *name, int mode, bool binary ) {
# ifdef HL_UFOPEN
static const uchar *MODES[] = { USTR("r"), USTR("w"), USTR("a"), USTR("r+"), USTR("rb"), USTR("wb"), USTR("ab"), USTR("rb+") };
FILE *f = fopen((uchar*)name,MODES[mode|(binary?4:0)]);
# else
static const char *MODES[] = { "r", "w", "a", "r+", "rb", "wb", "ab", "rb+" };
FILE *f = fopen((char*)name,MODES[mode|(binary?4:0)]);
# endif
hl_fdesc *fd;
if( f == NULL ) return NULL;
fd = (hl_fdesc*)hl_gc_alloc_finalizer(sizeof(hl_fdesc));
fd->finalize = fdesc_finalize;
fd->f = f;
SET_IS_STD(fd, false);
return fd;
}
HL_PRIM bool hl_file_is_locked( vbyte *name ) {
# ifdef HL_WIN
HANDLE h = CreateFile((uchar*)name,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if( h == INVALID_HANDLE_VALUE ) return true;
CloseHandle(h);
return false;
# else
return false;
# endif
}
HL_PRIM void hl_file_close( hl_fdesc *f ) {
if( !f ) return;
if( f->f ) fclose(f->f);
f->f = NULL;
f->finalize = NULL;
}
HL_PRIM int hl_file_write( hl_fdesc *f, vbyte *buf, int pos, int len ) {
int ret;
if( !f ) return -1;
hl_blocking(true);
# ifdef HL_WIN_DESKTOP
if( f->is_std ) {
// except utf8, handle the case where it's not \0 terminated
uchar *out = (uchar*)malloc((len+1)*2);
vbyte prev = buf[pos+len-1];
if( buf[pos+len] ) buf[pos+len-1] = 0;
int olen = hl_from_utf8(out,len,(const char*)(buf+pos));
buf[pos+len-1] = prev;
_setmode(fileno(f->f),_O_U8TEXT);
ret = _write(fileno(f->f),out,olen<<1);
_setmode(fileno(f->f),_O_TEXT);
if( ret > 0 ) ret = len;
free(out);
} else
# endif
ret = (int)fwrite(buf+pos,1,len,f->f);
hl_blocking(false);
return ret;
}
HL_PRIM int hl_file_read( hl_fdesc *f, vbyte *buf, int pos, int len ) {
int ret;
if( !f ) return -1;
hl_blocking(true);
ret = (int)fread((char*)buf+pos,1,len,f->f);
hl_blocking(false);
return ret;
}
HL_PRIM bool hl_file_write_char( hl_fdesc *f, int c ) {
size_t ret;
unsigned char cc = (unsigned char)c;
if( !f ) return false;
hl_blocking(true);
# ifdef HL_WIN_DESKTOP
if( f->is_std ) {
uchar wcc = cc;
_setmode(fileno(f->f),_O_U8TEXT);
ret = _write(fileno(f->f),&wcc,2);
_setmode(fileno(f->f),_O_TEXT);
if( ret > 0 ) ret = 1;
} else
# endif
ret = fwrite(&cc,1,1,f->f);
hl_blocking(false);
return ret == 1;
}
HL_PRIM int hl_file_read_char( hl_fdesc *f ) {
unsigned char cc;
hl_blocking(true);
if( !f || fread(&cc,1,1,f->f) != 1 ) {
hl_blocking(false);
return -2;
}
hl_blocking(false);
return cc;
}
HL_PRIM bool hl_file_seek( hl_fdesc *f, int pos, int kind ) {
if( !f ) return false;
return fseek(f->f,pos,kind) == 0;
}
HL_PRIM int hl_file_tell( hl_fdesc *f ) {
if( !f ) return -1;
return (int)ftell(f->f);
}
HL_PRIM bool hl_file_seek2( hl_fdesc *f, double pos, int kind ) {
if( !f ) return false;
# ifdef HL_WIN
return _fseeki64(f->f,(__int64)pos,kind) == 0;
# else
return fseek(f->f,(int64)pos,kind) == 0;
# endif
}
HL_PRIM double hl_file_tell2( hl_fdesc *f ) {
if( !f ) return -1;
# ifdef HL_WIN
return (double)_ftelli64(f->f);
# else
return (double)ftell(f->f);
# endif
}
HL_PRIM bool hl_file_eof( hl_fdesc *f ) {
if( !f ) return true;
return (bool)feof(f->f);
}
HL_PRIM int hl_file_error_code() {
return errno;
}
HL_PRIM bool hl_file_flush( hl_fdesc *f ) {
int ret;
if( !f ) return false;
hl_blocking(true);
ret = fflush( f->f );
hl_blocking(false);
return ret == 0;
}
#define MAKE_STDIO(k) \
HL_PRIM hl_fdesc *hl_file_##k() { \
hl_fdesc *f; \
f = (hl_fdesc*)hl_gc_alloc_noptr(sizeof(hl_fdesc)); \
f->f = k; \
f->finalize = NULL; \
SET_IS_STD(f, true); \
return f; \
}
MAKE_STDIO(stdin);
MAKE_STDIO(stdout);
MAKE_STDIO(stderr);
HL_PRIM vbyte *hl_file_contents( vbyte *name, int *size ) {
int len;
int p = 0;
vbyte *content;
# ifdef HL_UFOPEN
FILE *f = fopen((uchar*)name,USTR("rb"));
# else
FILE *f = fopen((char*)name,"rb");
# endif
if( f == NULL )
return NULL;
hl_blocking(true);
fseek(f,0,SEEK_END);
len = ftell(f);
if( size ) *size = len;
fseek(f,0,SEEK_SET);
hl_blocking(false);
content = (vbyte*)hl_gc_alloc_noptr(size ? len : len+1);
hl_blocking(true);
if( !size ) content[len] = 0; else if( !len ) content = (vbyte*)""; // final 0 for UTF8
while( len > 0 ) {
int d = (int)fread((char*)content + p,1,len,f);
if( d <= 0 ) {
hl_blocking(false);
fclose(f);
return NULL;
}
p += d;
len -= d;
}
fclose(f);
hl_blocking(false);
return content;
}
#define _FILE _ABSTRACT(hl_fdesc)
DEFINE_PRIM(_FILE, file_open, _BYTES _I32 _BOOL);
DEFINE_PRIM(_VOID, file_close, _FILE);
DEFINE_PRIM(_I32, file_write, _FILE _BYTES _I32 _I32);
DEFINE_PRIM(_I32, file_read, _FILE _BYTES _I32 _I32);
DEFINE_PRIM(_BOOL, file_write_char, _FILE _I32);
DEFINE_PRIM(_I32, file_read_char, _FILE);
DEFINE_PRIM(_BOOL, file_seek, _FILE _I32 _I32);
DEFINE_PRIM(_I32, file_tell, _FILE);
DEFINE_PRIM(_BOOL, file_seek2, _FILE _F64 _I32);
DEFINE_PRIM(_F64, file_tell2, _FILE);
DEFINE_PRIM(_BOOL, file_eof, _FILE);
DEFINE_PRIM(_BOOL, file_flush, _FILE);
DEFINE_PRIM(_FILE, file_stdin, _NO_ARG);
DEFINE_PRIM(_FILE, file_stdout, _NO_ARG);
DEFINE_PRIM(_FILE, file_stderr, _NO_ARG);
DEFINE_PRIM(_BYTES, file_contents, _BYTES _REF(_I32));
DEFINE_PRIM(_BOOL, file_is_locked, _BYTES);
DEFINE_PRIM(_I32, file_error_code, _NO_ARG);