gmio_core: provide a POSIX implementation for gmio_stream_stdio_size()
This commit is contained in:
parent
a04b9b2cda
commit
76ee571cd5
@ -25,7 +25,7 @@ project(gmio C)
|
|||||||
|
|
||||||
# Options
|
# Options
|
||||||
option(BUILD_SHARED_LIBS "Build shared libraries (DLL)" ON)
|
option(BUILD_SHARED_LIBS "Build shared libraries (DLL)" ON)
|
||||||
option(BUILD_STRICT_C90 "Build with strict conformance to C90 standard. If disabled, C99 features can be used (eg. strtof(), <stdint.h>, ...)" ON)
|
option(BUILD_STRICT_C90 "Build with strict conformance to C90 standard" OFF)
|
||||||
option(BUILD_WITH_LIBSTL "Build the libSTL module" ON)
|
option(BUILD_WITH_LIBSTL "Build the libSTL module" ON)
|
||||||
|
|
||||||
# Add core source files
|
# Add core source files
|
||||||
@ -39,31 +39,49 @@ math(EXPR GMIO_TARGET_ARCH_BIT_SIZE "8 * ${CMAKE_SIZEOF_VOID_P}")
|
|||||||
include(TestBigEndian)
|
include(TestBigEndian)
|
||||||
test_big_endian(GMIO_HOST_IS_BIG_ENDIAN)
|
test_big_endian(GMIO_HOST_IS_BIG_ENDIAN)
|
||||||
|
|
||||||
# Find available C99 features
|
# Adapt C compiler flags to satisfy the BUILD_STRICT_C90 option
|
||||||
if(NOT BUILD_STRICT_C90)
|
# It must be done before checking of C99 and POSIX features
|
||||||
# Have <stdint.h> ?
|
if(BUILD_STRICT_C90)
|
||||||
check_include_files(stdint.h GMIO_HAVE_STDINT_H)
|
if(CMAKE_COMPILER_IS_GNUCC)
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ansi")
|
||||||
# Have strtof() ?
|
elseif(MSVC)
|
||||||
check_function_exists(strtof GMIO_HAVE_STRTOF_FUNC)
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Za")
|
||||||
|
endif()
|
||||||
# Have powf() ?
|
|
||||||
check_function_exists(powf GMIO_HAVE_POWF_FUNC)
|
|
||||||
|
|
||||||
# Have <stdbool.h> ?
|
|
||||||
check_include_files(stdbool.h GMIO_HAVE_STDBOOL_H)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Have alloca()-like function ?
|
set(CMAKE_REQUIRED_FLAGS "${CMAKE_C_FLAGS}")
|
||||||
|
|
||||||
|
# Some compilers (like GCC v4.9) don't disable <stdint.h> in STRICT_ANSI mode
|
||||||
|
check_include_files(stdint.h GMIO_HAVE_STDINT_H)
|
||||||
|
|
||||||
|
check_include_files(sys/types.h GMIO_HAVE_SYS_TYPES_H)
|
||||||
|
check_include_files(sys/stat.h GMIO_HAVE_SYS_STAT_H)
|
||||||
|
check_function_exists(fileno GMIO_HAVE_POSIX_FILENO_FUNC)
|
||||||
|
check_function_exists(fstat64 GMIO_HAVE_POSIX_FSTAT64_FUNC)
|
||||||
|
if(WIN32)
|
||||||
|
check_function_exists(_fstat64 GMIO_HAVE_WIN__FSTAT64_FUNC)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Find available C99 and compiler/OS specific features
|
||||||
|
if(NOT BUILD_STRICT_C90)
|
||||||
|
check_function_exists(strtof GMIO_HAVE_STRTOF_FUNC)
|
||||||
|
check_function_exists(powf GMIO_HAVE_POWF_FUNC)
|
||||||
|
check_include_files(stdbool.h GMIO_HAVE_STDBOOL_H)
|
||||||
|
|
||||||
|
# Have BSD-like alloca() function ?
|
||||||
check_c_source_compiles(
|
check_c_source_compiles(
|
||||||
"#include <alloca.h>
|
"#include <alloca.h>
|
||||||
int main() { void* ptr = alloca(256); return 0; }"
|
int main() { void* ptr = alloca(256); return 0; }"
|
||||||
GMIO_HAVE_BSD_ALLOCA_FUNC)
|
GMIO_HAVE_BSD_ALLOCA_FUNC)
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
# Have Win32 _alloca() function ?
|
||||||
check_c_source_compiles(
|
check_c_source_compiles(
|
||||||
"#include <malloc.h>
|
"#include <malloc.h>
|
||||||
int main() { void* ptr = _alloca(256); return 0; }"
|
int main() { void* ptr = _alloca(256); return 0; }"
|
||||||
GMIO_HAVE_WIN_ALLOCA_FUNC)
|
GMIO_HAVE_WIN_ALLOCA_FUNC) # TODO: rename to GMIO_HAVE_WIN__ALLOCA_FUNC
|
||||||
|
endif() # WIN32
|
||||||
|
endif()
|
||||||
|
|
||||||
# Have builtin byte swap functions ?
|
# Have builtin byte swap functions ?
|
||||||
if(CMAKE_COMPILER_IS_GNUCC)
|
if(CMAKE_COMPILER_IS_GNUCC)
|
||||||
@ -87,9 +105,6 @@ include_directories(${CMAKE_BINARY_DIR}) # For generated "config.h"
|
|||||||
|
|
||||||
# Specific flags for GCC
|
# Specific flags for GCC
|
||||||
if(CMAKE_COMPILER_IS_GNUCC)
|
if(CMAKE_COMPILER_IS_GNUCC)
|
||||||
if(BUILD_STRICT_C90)
|
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ansi")
|
|
||||||
endif()
|
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pedantic-errors -fstrict-aliasing")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pedantic-errors -fstrict-aliasing")
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Winline -Wextra -Wstrict-aliasing -Wcast-align -Wlogical-op -Wfloat-equal")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Winline -Wextra -Wstrict-aliasing -Wcast-align -Wlogical-op -Wfloat-equal")
|
||||||
|
|
||||||
|
@ -23,6 +23,12 @@
|
|||||||
#cmakedefine GMIO_HAVE_STRTOF_FUNC
|
#cmakedefine GMIO_HAVE_STRTOF_FUNC
|
||||||
#cmakedefine GMIO_HAVE_POWF_FUNC
|
#cmakedefine GMIO_HAVE_POWF_FUNC
|
||||||
|
|
||||||
|
#cmakedefine GMIO_HAVE_SYS_TYPES_H
|
||||||
|
#cmakedefine GMIO_HAVE_SYS_STAT_H
|
||||||
|
#cmakedefine GMIO_HAVE_POSIX_FILENO_FUNC
|
||||||
|
#cmakedefine GMIO_HAVE_POSIX_FSTAT64_FUNC
|
||||||
|
#cmakedefine GMIO_HAVE_WIN__FSTAT64_FUNC
|
||||||
|
|
||||||
#cmakedefine GMIO_HAVE_GCC_BUILTIN_BSWAP16_FUNC
|
#cmakedefine GMIO_HAVE_GCC_BUILTIN_BSWAP16_FUNC
|
||||||
#cmakedefine GMIO_HAVE_GCC_BUILTIN_BSWAP32_FUNC
|
#cmakedefine GMIO_HAVE_GCC_BUILTIN_BSWAP32_FUNC
|
||||||
|
|
||||||
|
@ -23,6 +23,18 @@
|
|||||||
#if defined(WIN64) || defined(_WIN64) || defined(__WIN64__) \
|
#if defined(WIN64) || defined(_WIN64) || defined(__WIN64__) \
|
||||||
|| defined(WIN32) || defined(_WIN32) || defined(__WIN32__) \
|
|| defined(WIN32) || defined(_WIN32) || defined(__WIN32__) \
|
||||||
|| defined(__NT__)
|
|| defined(__NT__)
|
||||||
|
# define GMIO_OS_WIN
|
||||||
|
#endif /* Windows */
|
||||||
|
|
||||||
|
#if defined(__linux) || defined(__linux__) || defined(linux)
|
||||||
|
# define GMIO_OS_LINUX
|
||||||
|
#endif /* Linux */
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
# define GMIO_OS_MAC
|
||||||
|
#endif /* Apple */
|
||||||
|
|
||||||
|
#ifdef GMIO_OS_WIN
|
||||||
# define GMIO_DECL_EXPORT __declspec(dllexport)
|
# define GMIO_DECL_EXPORT __declspec(dllexport)
|
||||||
# define GMIO_DECL_IMPORT __declspec(dllimport)
|
# define GMIO_DECL_IMPORT __declspec(dllimport)
|
||||||
#else
|
#else
|
||||||
@ -118,7 +130,7 @@ typedef double gmio_float64_t;
|
|||||||
# elif defined(_MSC_VER)
|
# elif defined(_MSC_VER)
|
||||||
# define GMIO_INLINE __inline static
|
# define GMIO_INLINE __inline static
|
||||||
# elif !defined(DOXYGEN)
|
# elif !defined(DOXYGEN)
|
||||||
# define GMIO_INLINE
|
# define GMIO_INLINE static
|
||||||
# else
|
# else
|
||||||
/*! Expands to the C compiler specific inline keyword (if any) */
|
/*! Expands to the C compiler specific inline keyword (if any) */
|
||||||
# define GMIO_INLINE
|
# define GMIO_INLINE
|
||||||
|
@ -19,10 +19,54 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
/* TODO: add cmake step to check availability of <sys/xxx.h> header files */
|
#if defined(GMIO_HAVE_SYS_TYPES_H) && defined(GMIO_HAVE_SYS_STAT_H)
|
||||||
|
|
||||||
|
/* Activate 64bit variants of stat(), fstat(), ...
|
||||||
|
* See:
|
||||||
|
* http://linux.die.net/man/2/fstat64
|
||||||
|
* https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man2/fstat.2.html
|
||||||
|
*/
|
||||||
|
# ifdef GMIO_OS_LINUX
|
||||||
|
# if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS != 64
|
||||||
|
# undef _FILE_OFFSET_BITS
|
||||||
|
# endif
|
||||||
|
# if !defined(_FILE_OFFSET_BITS)
|
||||||
|
# define _FILE_OFFSET_BITS=64
|
||||||
|
# endif
|
||||||
|
# if !defined(_POSIX_C_SOURCE)
|
||||||
|
/* This enables fileno() */
|
||||||
|
# define _POSIX_C_SOURCE
|
||||||
|
# endif
|
||||||
|
# define GMIO_FSTAT64_OVERRIDE
|
||||||
|
# endif /* Linux */
|
||||||
|
|
||||||
|
# ifdef GMIO_OS_MAC
|
||||||
|
# if !defined(_DARWIN_USE_64_BIT_INODE)
|
||||||
|
# define _DARWIN_USE_64_BIT_INODE
|
||||||
|
# endif
|
||||||
|
# define GMIO_FSTAT64_OVERRIDE
|
||||||
|
# endif /* Apple */
|
||||||
|
|
||||||
# include <sys/types.h>
|
# include <sys/types.h>
|
||||||
# include <sys/stat.h>
|
# include <sys/stat.h>
|
||||||
|
|
||||||
|
/* Define wrapper around the stat structure and the fstat() function */
|
||||||
|
# ifdef GMIO_HAVE_WIN__FSTAT64_FUNC
|
||||||
|
typedef struct __stat64 gmio_stat_t;
|
||||||
|
GMIO_INLINE int gmio_fstat(int fd, gmio_stat_t* buf)
|
||||||
|
{ return _fstat64(fd, buf); }
|
||||||
|
# elif defined(GMIO_FSTAT64_OVERRIDE) || !defined(GMIO_HAVE_POSIX_FSTAT64_FUNC)
|
||||||
|
typedef struct stat gmio_stat_t;
|
||||||
|
GMIO_INLINE int gmio_fstat(int fd, gmio_stat_t* buf)
|
||||||
|
{ return fstat(fd, buf); }
|
||||||
|
# elif defined(GMIO_HAVE_POSIX_FSTAT64_FUNC)
|
||||||
|
typedef struct stat64 gmio_stat_t;
|
||||||
|
GMIO_INLINE int gmio_fstat(int fd, gmio_stat_t* buf)
|
||||||
|
{ return fstat64(fd, buf); }
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#endif /* GMIO_HAVE_SYS_TYPES_H && GMIO_HAVE_SYS_STAT_H */
|
||||||
|
|
||||||
gmio_stream_t gmio_stream_null()
|
gmio_stream_t gmio_stream_null()
|
||||||
{
|
{
|
||||||
gmio_stream_t null_stream = { 0 };
|
gmio_stream_t null_stream = { 0 };
|
||||||
@ -53,9 +97,58 @@ static size_t gmio_stream_stdio_write(
|
|||||||
|
|
||||||
static size_t gmio_stream_stdio_size(void* cookie)
|
static size_t gmio_stream_stdio_size(void* cookie)
|
||||||
{
|
{
|
||||||
struct stat stat_buf;
|
FILE* file = (FILE*) cookie;
|
||||||
fstat(fileno((FILE*) cookie), &stat_buf);
|
|
||||||
return stat_buf.st_size;
|
#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
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gmio_stream_stdio_rewind(void* cookie)
|
static void gmio_stream_stdio_rewind(void* cookie)
|
||||||
|
Loading…
Reference in New Issue
Block a user