2015-03-03 00:38:33 +08:00
|
|
|
/****************************************************************************
|
2015-05-28 15:40:24 +08:00
|
|
|
** gmio
|
2015-05-01 00:19:45 +08:00
|
|
|
** Copyright Fougue (2 Mar. 2015)
|
2015-07-13 17:42:03 +08:00
|
|
|
** contact@fougue.pro
|
2015-03-03 00:38:33 +08:00
|
|
|
**
|
|
|
|
** This software is a reusable library whose purpose is to provide complete
|
|
|
|
** I/O support for various CAD file formats (eg. STL)
|
|
|
|
**
|
|
|
|
** This software is governed by the CeCILL-B license under French law and
|
|
|
|
** abiding by the rules of distribution of free software. You can use,
|
|
|
|
** modify and/ or redistribute the software under the terms of the CeCILL-B
|
|
|
|
** license as circulated by CEA, CNRS and INRIA at the following URL
|
2015-03-30 15:05:25 +08:00
|
|
|
** "http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html".
|
2015-03-03 00:38:33 +08:00
|
|
|
****************************************************************************/
|
|
|
|
|
2013-01-11 01:48:46 +08:00
|
|
|
#include "stream.h"
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
2015-04-01 21:39:00 +08:00
|
|
|
#if defined(GMIO_HAVE_SYS_TYPES_H) && defined(GMIO_HAVE_SYS_STAT_H)
|
|
|
|
# include <sys/types.h>
|
|
|
|
# include <sys/stat.h>
|
|
|
|
|
2015-04-02 15:39:11 +08:00
|
|
|
/* gmio_stat_t: type alias on the stat structure
|
|
|
|
* GMIO_FSTAT_FUNC_NAME: alias on the fstat() function
|
|
|
|
*/
|
|
|
|
# if defined(GMIO_HAVE_WIN__FSTAT64_FUNC)
|
2015-04-01 21:39:00 +08:00
|
|
|
typedef struct __stat64 gmio_stat_t;
|
2015-04-02 15:39:11 +08:00
|
|
|
# define GMIO_FSTAT_FUNC_NAME _fstat64
|
2015-04-01 21:39:00 +08:00
|
|
|
# elif defined(GMIO_HAVE_POSIX_FSTAT64_FUNC)
|
|
|
|
typedef struct stat64 gmio_stat_t;
|
2015-04-02 15:39:11 +08:00
|
|
|
# define GMIO_FSTAT_FUNC_NAME fstat64
|
|
|
|
# else
|
|
|
|
typedef struct stat gmio_stat_t;
|
|
|
|
# define GMIO_FSTAT_FUNC_NAME fstat
|
2015-04-01 21:39:00 +08:00
|
|
|
# endif
|
|
|
|
|
2015-04-02 15:39:11 +08:00
|
|
|
/* Define wrapper around the fstat() function */
|
|
|
|
GMIO_INLINE int gmio_fstat(int fd, gmio_stat_t* buf)
|
|
|
|
{
|
|
|
|
return GMIO_FSTAT_FUNC_NAME(fd, buf);
|
|
|
|
}
|
|
|
|
|
2015-04-01 21:39:00 +08:00
|
|
|
#endif /* GMIO_HAVE_SYS_TYPES_H && GMIO_HAVE_SYS_STAT_H */
|
2015-03-24 01:15:31 +08:00
|
|
|
|
2015-12-04 01:00:25 +08:00
|
|
|
struct gmio_stream gmio_stream_null()
|
2015-03-19 23:34:53 +08:00
|
|
|
{
|
2015-12-04 01:00:25 +08:00
|
|
|
struct gmio_stream null_stream = {0};
|
2015-03-19 23:34:53 +08:00
|
|
|
return null_stream;
|
|
|
|
}
|
|
|
|
|
2014-03-28 23:33:35 +08:00
|
|
|
static gmio_bool_t gmio_stream_stdio_at_end(void* cookie)
|
2013-01-11 01:48:46 +08:00
|
|
|
{
|
2015-09-20 05:14:42 +08:00
|
|
|
return feof((FILE*)cookie);
|
2013-01-11 01:48:46 +08:00
|
|
|
}
|
|
|
|
|
2014-03-28 23:33:35 +08:00
|
|
|
static int gmio_stream_stdio_error(void* cookie)
|
2013-01-11 01:48:46 +08:00
|
|
|
{
|
2015-09-20 05:14:42 +08:00
|
|
|
return ferror((FILE*)cookie);
|
2013-01-15 17:40:35 +08:00
|
|
|
}
|
2013-01-11 01:48:46 +08:00
|
|
|
|
2015-03-13 18:04:14 +08:00
|
|
|
static size_t gmio_stream_stdio_read(
|
|
|
|
void* cookie, void* ptr, size_t item_size, size_t item_count)
|
2013-01-11 01:48:46 +08:00
|
|
|
{
|
2015-09-20 05:14:42 +08:00
|
|
|
return fread(ptr, item_size, item_count, (FILE*)cookie);
|
2013-01-11 01:48:46 +08:00
|
|
|
}
|
|
|
|
|
2015-03-13 18:04:14 +08:00
|
|
|
static size_t gmio_stream_stdio_write(
|
|
|
|
void* cookie, const void* ptr, size_t item_size, size_t item_count)
|
2013-01-11 01:48:46 +08:00
|
|
|
{
|
2015-09-20 05:14:42 +08:00
|
|
|
return fwrite(ptr, item_size, item_count, (FILE*)cookie);
|
2013-01-11 01:48:46 +08:00
|
|
|
}
|
|
|
|
|
2015-11-06 20:43:03 +08:00
|
|
|
static gmio_streamsize_t gmio_stream_stdio_size(void* cookie)
|
2015-03-24 01:15:31 +08:00
|
|
|
{
|
2015-09-20 05:14:42 +08:00
|
|
|
FILE* file = (FILE*)cookie;
|
2015-04-01 21:39:00 +08:00
|
|
|
|
|
|
|
#if defined(GMIO_HAVE_SYS_TYPES_H) \
|
|
|
|
&& defined(GMIO_HAVE_SYS_STAT_H) \
|
|
|
|
&& defined(GMIO_HAVE_POSIX_FILENO_FUNC)
|
|
|
|
|
|
|
|
const int fd = fileno(file);
|
|
|
|
if (fd != -1) {
|
|
|
|
gmio_stat_t buf;
|
|
|
|
if (gmio_fstat(fd, &buf) == 0)
|
|
|
|
return buf.st_size;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
/* Excerpted from: https://www.securecoding.cert.org
|
|
|
|
* item FIO19-C
|
|
|
|
*
|
|
|
|
* Subclause 7.21.9.2 of the C Standard [ISO/IEC 9899:2011] specifies the
|
|
|
|
* following behavior for fseek() when opening a binary file in binary mode:
|
|
|
|
* A binary stream need not meaningfully support fseek calls with a
|
|
|
|
* whence value of SEEK_END.
|
|
|
|
*
|
|
|
|
* In addition, footnote 268 of subclause 7.21.3 says:
|
|
|
|
* Setting the file position indicator to end-of-file, as with
|
|
|
|
* fseek(file, 0, SEEK_END), has undefined behavior for a binary stream
|
|
|
|
* (because of possible trailing null characters) or for any stream with
|
|
|
|
* state-dependent encoding that does not assuredly end in the initial
|
|
|
|
* shift state.
|
|
|
|
*
|
|
|
|
* Subclause 7.21.9.4 of the C Standard [ISO/IEC 9899:2011] specifies the
|
|
|
|
* following behavior for ftell() when opening a text file in text mode:
|
|
|
|
* For a text stream, its file position indicator contains unspecified
|
|
|
|
* information, usable by the fseek function for returning the file
|
|
|
|
* position indicator for the stream to its position at the time of the
|
|
|
|
* ftell call.
|
|
|
|
* Consequently, the return value of ftell() for streams opened in text mode
|
|
|
|
* should never be used for offset calculations other than in calls to
|
|
|
|
* fseek().
|
|
|
|
*/
|
|
|
|
|
|
|
|
long size = 0L;
|
|
|
|
const long old_pos = ftell(file);
|
|
|
|
|
|
|
|
fseek(file, 0L, SEEK_END);
|
|
|
|
size = ftell(file);
|
|
|
|
fseek(file, old_pos, SEEK_SET);
|
|
|
|
|
|
|
|
return size;
|
|
|
|
|
|
|
|
#endif
|
2015-03-24 01:15:31 +08:00
|
|
|
}
|
|
|
|
|
2015-12-04 01:03:46 +08:00
|
|
|
static int gmio_stream_stdio_get_pos(void* cookie, struct gmio_streampos* pos)
|
2015-03-24 01:15:31 +08:00
|
|
|
{
|
2015-09-18 20:33:23 +08:00
|
|
|
fpos_t fpos;
|
|
|
|
int res = fgetpos((FILE*)cookie, &fpos);
|
|
|
|
memcpy(&pos->cookie[0], &fpos, sizeof(fpos_t));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2015-12-04 01:03:46 +08:00
|
|
|
static int gmio_stream_stdio_set_pos(void* cookie, const struct gmio_streampos* pos)
|
2015-09-18 20:33:23 +08:00
|
|
|
{
|
|
|
|
fpos_t fpos;
|
|
|
|
memcpy(&fpos, &pos->cookie[0], sizeof(fpos_t));
|
|
|
|
return fsetpos((FILE*)cookie, &fpos);
|
2015-03-24 01:15:31 +08:00
|
|
|
}
|
|
|
|
|
2015-12-04 01:00:25 +08:00
|
|
|
struct gmio_stream gmio_stream_stdio(FILE* file)
|
2015-03-19 23:34:53 +08:00
|
|
|
{
|
2015-12-04 01:00:25 +08:00
|
|
|
struct gmio_stream stream = gmio_stream_null();
|
2015-03-30 23:26:11 +08:00
|
|
|
stream.cookie = file;
|
2015-07-10 17:33:05 +08:00
|
|
|
stream.func_at_end = gmio_stream_stdio_at_end;
|
|
|
|
stream.func_error = gmio_stream_stdio_error;
|
|
|
|
stream.func_read = gmio_stream_stdio_read;
|
|
|
|
stream.func_write = gmio_stream_stdio_write;
|
|
|
|
stream.func_size = gmio_stream_stdio_size;
|
2015-09-18 20:33:23 +08:00
|
|
|
stream.func_get_pos = gmio_stream_stdio_get_pos;
|
|
|
|
stream.func_set_pos = gmio_stream_stdio_set_pos;
|
2015-03-30 23:26:11 +08:00
|
|
|
return stream;
|
2015-03-19 23:34:53 +08:00
|
|
|
}
|