123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- /*
- * libopenmpt_stream_callbacks_buffer.h
- * ------------------------------------
- * Purpose: libopenmpt public c interface
- * Notes : (currently none)
- * Authors: OpenMPT Devs
- * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
- */
- #ifndef LIBOPENMPT_STREAM_CALLBACKS_BUFFER_H
- #define LIBOPENMPT_STREAM_CALLBACKS_BUFFER_H
- #include "libopenmpt.h"
- /* The use of this header requires:
- #include <libopenmpt/libopenmpt.h>
- #if defined( LIBOPENMPT_STREAM_CALLBACKS_BUFFER )
- #include <libopenmpt/libopenmpt_stream_callbacks_buffer.h>
- #else
- #error "libopenmpt too old."
- #endif
- */
- #include <stdint.h>
- #include <stdlib.h>
- #include <string.h>
- /*! \addtogroup libopenmpt_c
- * @{
- */
- #ifdef __cplusplus
- extern "C" {
- #endif
- typedef struct openmpt_stream_buffer {
- const void * file_data; /* or prefix data IFF prefix_size < file_size */
- int64_t file_size;
- int64_t file_pos;
- int64_t prefix_size;
- int overflow;
- } openmpt_stream_buffer;
- static size_t openmpt_stream_buffer_read_func( void * stream, void * dst, size_t bytes ) {
- openmpt_stream_buffer * s = (openmpt_stream_buffer*)stream;
- int64_t offset = 0;
- int64_t begpos = 0;
- int64_t endpos = 0;
- size_t valid_bytes = 0;
- if ( !s ) {
- return 0;
- }
- offset = bytes;
- begpos = s->file_pos;
- endpos = s->file_pos;
- valid_bytes = 0;
- endpos = (uint64_t)endpos + (uint64_t)offset;
- if ( ( offset > 0 ) && !( (uint64_t)endpos > (uint64_t)begpos ) ) {
- /* integer wrapped */
- return 0;
- }
- if ( bytes == 0 ) {
- return 0;
- }
- if ( begpos >= s->file_size ) {
- return 0;
- }
- if ( endpos > s->file_size ) {
- /* clip to eof */
- bytes = bytes - (size_t)( endpos - s->file_size );
- endpos = endpos - ( endpos - s->file_size );
- }
- memset( dst, 0, bytes );
- if ( begpos >= s->prefix_size ) {
- s->overflow = 1;
- valid_bytes = 0;
- } else if ( endpos > s->prefix_size ) {
- s->overflow = 1;
- valid_bytes = bytes - (size_t)( endpos - s->prefix_size );
- } else {
- valid_bytes = bytes;
- }
- memcpy( dst, (const char*)s->file_data + s->file_pos, valid_bytes );
- s->file_pos = s->file_pos + bytes;
- return bytes;
- }
- static int openmpt_stream_buffer_seek_func( void * stream, int64_t offset, int whence ) {
- openmpt_stream_buffer * s = (openmpt_stream_buffer*)stream;
- int result = -1;
- if ( !s ) {
- return -1;
- }
- switch ( whence ) {
- case OPENMPT_STREAM_SEEK_SET:
- if ( offset < 0 ) {
- return -1;
- }
- if ( offset > s->file_size ) {
- return -1;
- }
- s->file_pos = offset;
- result = 0;
- break;
- case OPENMPT_STREAM_SEEK_CUR:
- do {
- int64_t oldpos = s->file_pos;
- int64_t pos = s->file_pos;
- pos = (uint64_t)pos + (uint64_t)offset;
- if ( ( offset > 0 ) && !( (uint64_t)pos > (uint64_t)oldpos ) ) {
- /* integer wrapped */
- return -1;
- }
- if ( ( offset < 0 ) && !( (uint64_t)pos < (uint64_t)oldpos ) ) {
- /* integer wrapped */
- return -1;
- }
- s->file_pos = pos;
- } while(0);
- result = 0;
- break;
- case OPENMPT_STREAM_SEEK_END:
- if ( offset > 0 ) {
- return -1;
- }
- do {
- int64_t oldpos = s->file_pos;
- int64_t pos = s->file_pos;
- pos = s->file_size;
- pos = (uint64_t)pos + (uint64_t)offset;
- if ( ( offset < 0 ) && !( (uint64_t)pos < (uint64_t)oldpos ) ) {
- /* integer wrapped */
- return -1;
- }
- s->file_pos = pos;
- } while(0);
- result = 0;
- break;
- }
- return result;
- }
- static int64_t openmpt_stream_buffer_tell_func( void * stream ) {
- openmpt_stream_buffer * s = (openmpt_stream_buffer*)stream;
- if ( !s ) {
- return -1;
- }
- return s->file_pos;
- }
- static void openmpt_stream_buffer_init( openmpt_stream_buffer * buffer, const void * file_data, int64_t file_size ) {
- memset( buffer, 0, sizeof( openmpt_stream_buffer ) );
- buffer->file_data = file_data;
- buffer->file_size = file_size;
- buffer->file_pos = 0;
- buffer->prefix_size = file_size;
- buffer->overflow = 0;
- }
- #define openmpt_stream_buffer_init_prefix_only( buffer_, prefix_data_, prefix_size_, file_size_ ) do { \
- openmpt_stream_buffer_init( (buffer_), (prefix_data_), (file_size_) ); \
- (buffer_)->prefix_size = (prefix_size_); \
- } while(0)
- #define openmpt_stream_buffer_overflowed( buffer_ ) ( (buffer_)->overflow )
- /*! \brief Provide openmpt_stream_callbacks for in-memoy buffers
- *
- * Fills openmpt_stream_callbacks suitable for passing an in-memory buffer as a stream parameter to functions doing file input/output.
- *
- * \remarks The stream argument must be passed as `(void*)(openmpt_stream_buffer*)stream_buffer`.
- * \sa \ref libopenmpt_c_fileio
- * \sa openmpt_stream_callbacks
- * \sa openmpt_could_open_probability2
- * \sa openmpt_probe_file_header_from_stream
- * \sa openmpt_module_create2
- */
- static openmpt_stream_callbacks openmpt_stream_get_buffer_callbacks(void) {
- openmpt_stream_callbacks retval;
- memset( &retval, 0, sizeof( openmpt_stream_callbacks ) );
- retval.read = openmpt_stream_buffer_read_func;
- retval.seek = openmpt_stream_buffer_seek_func;
- retval.tell = openmpt_stream_buffer_tell_func;
- return retval;
- }
- #ifdef __cplusplus
- }
- #endif
- /*!
- * @}
- */
- #endif /* LIBOPENMPT_STREAM_CALLBACKS_BUFFER_H */
|