Commit 967088ac authored by conrad's avatar conrad
Browse files

- added OggzIO interface (<oggz/oggz_io.h>, src/liboggz/oggz_io.c)

 - added test cases for IO overriding
 - added OGGZ_CONTINUE, OGGZ_STOP_OK, OGGZ_STOP_ERR constants
 - added test cases for read callback stopping (OK and ERR)


git-svn-id: http://svn.annodex.net/liboggz/trunk@382 8158c8cd-e7e1-0310-9fa4-c5954c97daef
parent 824868c7
...@@ -2,5 +2,5 @@ ...@@ -2,5 +2,5 @@
# Include files to install # Include files to install
includedir = $(prefix)/include/oggz includedir = $(prefix)/include/oggz
include_HEADERS = oggz.h oggz_constants.h oggz_table.h include_HEADERS = oggz.h oggz_constants.h oggz_io.h oggz_table.h
...@@ -1094,5 +1094,6 @@ long oggz_seek_packets (OGGZ * oggz, long serialno, long packets, int whence); ...@@ -1094,5 +1094,6 @@ long oggz_seek_packets (OGGZ * oggz, long serialno, long packets, int whence);
*/ */
long oggz_serialno_new (OGGZ * oggz); long oggz_serialno_new (OGGZ * oggz);
#include <oggz/oggz_io.h>
#endif /* __OGGZ_H__ */ #endif /* __OGGZ_H__ */
...@@ -63,6 +63,17 @@ enum OggzFlags { ...@@ -63,6 +63,17 @@ enum OggzFlags {
OGGZ_AUTO = 0x20 OGGZ_AUTO = 0x20
}; };
enum OggzStopCtl {
/** Continue calling read callbacks */
OGGZ_CONTINUE = 0,
/** Stop calling callbacks, but retain buffered packet data */
OGGZ_STOP_OK = 1,
/** Stop calling callbacks, and purge buffered packet data */
OGGZ_STOP_ERR = -1
};
/** /**
* Flush options for oggz_write_feed; can be or'ed together * Flush options for oggz_write_feed; can be or'ed together
*/ */
......
...@@ -62,7 +62,7 @@ ...@@ -62,7 +62,7 @@
* \retval 0 to indicate that there is no more data to read (End of file) * \retval 0 to indicate that there is no more data to read (End of file)
* \retval "< 0" An error condition * \retval "< 0" An error condition
*/ */
typedef long (*OggzIORead) (void * user_handle, void * buf, long n); typedef size_t (*OggzIORead) (void * user_handle, void * buf, size_t n);
/** /**
* This is the signature of a function which you provide for Oggz * This is the signature of a function which you provide for Oggz
...@@ -75,7 +75,7 @@ typedef long (*OggzIORead) (void * user_handle, void * buf, long n); ...@@ -75,7 +75,7 @@ typedef long (*OggzIORead) (void * user_handle, void * buf, long n);
* \a n if a write error has occurred) * \a n if a write error has occurred)
* \retval "< 0" An error condition * \retval "< 0" An error condition
*/ */
typedef long (*OggzIOWrite) (void * user_handle, void * buf, long n); typedef size_t (*OggzIOWrite) (void * user_handle, void * buf, size_t n);
/** /**
* This is the signature of a function which you provide for Oggz * This is the signature of a function which you provide for Oggz
...@@ -86,8 +86,11 @@ typedef long (*OggzIOWrite) (void * user_handle, void * buf, long n); ...@@ -86,8 +86,11 @@ typedef long (*OggzIOWrite) (void * user_handle, void * buf, long n);
* \param whence SEEK_SET, SEEK_CUR or SEEK_END (as for stdio.h) * \param whence SEEK_SET, SEEK_CUR or SEEK_END (as for stdio.h)
* \retval ">= 0" The offset seeked to * \retval ">= 0" The offset seeked to
* \retval "< 0" An error condition * \retval "< 0" An error condition
*
* \note If you provide an OggzIOSeek function, you MUST also provide
* an OggzIOTell function, or else all your seeks will fail.
*/ */
typedef off_t (*OggzIOSeek) (void * user_handle, off_t offset, int whence); typedef int (*OggzIOSeek) (void * user_handle, long offset, int whence);
/** /**
* This is the signature of a function which you provide for Oggz * This is the signature of a function which you provide for Oggz
...@@ -98,7 +101,7 @@ typedef off_t (*OggzIOSeek) (void * user_handle, off_t offset, int whence); ...@@ -98,7 +101,7 @@ typedef off_t (*OggzIOSeek) (void * user_handle, off_t offset, int whence);
* \retval ">= 0" The offset * \retval ">= 0" The offset
* \retval "< 0" An error condition * \retval "< 0" An error condition
*/ */
typedef off_t (*OggzIOTell) (void * user_handle); typedef long (*OggzIOTell) (void * user_handle);
/** /**
* This is the signature of a function which you provide for Oggz * This is the signature of a function which you provide for Oggz
...@@ -165,6 +168,9 @@ void * oggz_io_get_write_user_handle (OGGZ * oggz); ...@@ -165,6 +168,9 @@ void * oggz_io_get_write_user_handle (OGGZ * oggz);
* \retval 0 Success * \retval 0 Success
* \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ
* \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ
*
* \note If you provide an OggzIOSeek function, you MUST also provide
* an OggzIOTell function, or else all your seeks will fail.
*/ */
int oggz_io_set_seek (OGGZ * oggz, OggzIOSeek seek, void * user_handle); int oggz_io_set_seek (OGGZ * oggz, OggzIOSeek seek, void * user_handle);
......
...@@ -12,6 +12,7 @@ lib_LTLIBRARIES = liboggz.la ...@@ -12,6 +12,7 @@ lib_LTLIBRARIES = liboggz.la
liboggz_la_SOURCES = \ liboggz_la_SOURCES = \
oggz.c \ oggz.c \
oggz_private.h oggz_byteorder.h oggz_compat.h oggz_macros.h \ oggz_private.h oggz_byteorder.h oggz_compat.h oggz_macros.h \
oggz_io.c \
oggz_read.c oggz_write.c \ oggz_read.c oggz_write.c \
oggz_auto.c oggz_auto.h \ oggz_auto.c oggz_auto.h \
oggz_table.c \ oggz_table.c \
......
...@@ -79,6 +79,7 @@ oggz_new (int flags) ...@@ -79,6 +79,7 @@ oggz_new (int flags)
oggz->flags = flags; oggz->flags = flags;
oggz->file = NULL; oggz->file = NULL;
oggz->io = NULL;
oggz->offset = 0; oggz->offset = 0;
oggz->offset_data_begin = 0; oggz->offset_data_begin = 0;
...@@ -141,13 +142,7 @@ oggz_flush (OGGZ * oggz) ...@@ -141,13 +142,7 @@ oggz_flush (OGGZ * oggz)
{ {
if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ; if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
if (oggz->file == NULL) return OGGZ_ERR_INVALID; return oggz_io_flush (oggz);
if (fflush (oggz->file) == EOF) {
return OGGZ_ERR_SYSTEM;
}
return 0;
} }
static int static int
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include "oggz_vector.h" #include "oggz_vector.h"
typedef struct _OGGZ OGGZ; typedef struct _OGGZ OGGZ;
typedef struct _OggzIO OggzIO;
typedef struct _OggzReader OggzReader; typedef struct _OggzReader OggzReader;
typedef struct _OggzWriter OggzWriter; typedef struct _OggzWriter OggzWriter;
...@@ -57,6 +58,13 @@ typedef int (*OggzOrder) (OGGZ * oggz, ogg_packet * op, void * target, ...@@ -57,6 +58,13 @@ typedef int (*OggzOrder) (OGGZ * oggz, ogg_packet * op, void * target,
typedef int (*OggzWriteHungry) (OGGZ * oggz, int empty, void * user_data); typedef int (*OggzWriteHungry) (OGGZ * oggz, int empty, void * user_data);
/* oggz_io */
typedef size_t (*OggzIORead) (void * user_handle, void * buf, size_t n);
typedef size_t (*OggzIOWrite) (void * user_handle, void * buf, size_t n);
typedef int (*OggzIOSeek) (void * user_handle, long offset, int whence);
typedef long (*OggzIOTell) (void * user_handle);
typedef int (*OggzIOFlush) (void * user_handle);
typedef struct { typedef struct {
ogg_stream_state ogg_stream; ogg_stream_state ogg_stream;
...@@ -139,9 +147,27 @@ struct _OggzWriter { ...@@ -139,9 +147,27 @@ struct _OggzWriter {
ogg_stream_state * current_stream; ogg_stream_state * current_stream;
}; };
struct _OggzIO {
OggzIORead read;
void * read_user_handle;
OggzIOWrite write;
void * write_user_handle;
OggzIOSeek seek;
void * seek_user_handle;
OggzIOTell tell;
void * tell_user_handle;
OggzIOFlush flush;
void * flush_user_handle;
};
struct _OGGZ { struct _OGGZ {
int flags; int flags;
FILE * file; FILE * file;
OggzIO * io;
ogg_packet current_packet; ogg_packet current_packet;
ogg_page current_page; ogg_page current_page;
...@@ -184,4 +210,11 @@ int oggz_purge (OGGZ * oggz); ...@@ -184,4 +210,11 @@ int oggz_purge (OGGZ * oggz);
int oggz_auto (OGGZ * oggz, ogg_packet * op, long serialno, void * user_data); int oggz_auto (OGGZ * oggz, ogg_packet * op, long serialno, void * user_data);
/* oggz_io */
size_t oggz_io_read (OGGZ * oggz, void * buf, size_t n);
size_t oggz_io_write (OGGZ * oggz, void * buf, size_t n);
int oggz_io_seek (OGGZ * oggz, long offset, int whence);
long oggz_io_tell (OGGZ * oggz);
int oggz_io_flush (OGGZ * oggz);
#endif /* __OGGZ_PRIVATE_H__ */ #endif /* __OGGZ_PRIVATE_H__ */
...@@ -157,7 +157,7 @@ oggz_get_next_page_7 (OGGZ * oggz, ogg_page * og) ...@@ -157,7 +157,7 @@ oggz_get_next_page_7 (OGGZ * oggz, ogg_page * og)
page_offset = 0; page_offset = 0;
#if _UMMODIFIED_ #if _UMMODIFIED_
buffer = ogg_sync_buffer (&reader->ogg_sync, CHUNKSIZE); buffer = ogg_sync_buffer (&reader->ogg_sync, CHUNKSIZE);
if ((bytes = fread (buffer, 1, CHUNKSIZE, oggz->file)) == 0) { if ((bytes = oggz_io_read (oggz, buffer, CHUNKSIZE)) == 0) {
if (ferror (oggz->file)) { if (ferror (oggz->file)) {
oggz_set_error (oggz, OGGZ_ERR_SYSTEM); oggz_set_error (oggz, OGGZ_ERR_SYSTEM);
return -1; return -1;
...@@ -188,7 +188,7 @@ oggz_get_next_page_7 (OGGZ * oggz, ogg_page * og) ...@@ -188,7 +188,7 @@ oggz_get_next_page_7 (OGGZ * oggz, ogg_page * og)
/* Calculate the byte offset of the page which was found */ /* Calculate the byte offset of the page which was found */
if (bytes > 0) { if (bytes > 0) {
oggz->offset = ftell (oggz->file) - bytes + page_offset; oggz->offset = oggz_io_tell (oggz) - bytes + page_offset;
ret = oggz->offset; ret = oggz->offset;
} else { } else {
/* didn't need to do any reading -- accumulate the page_offset */ /* didn't need to do any reading -- accumulate the page_offset */
...@@ -275,6 +275,9 @@ oggz_read_sync (OGGZ * oggz) ...@@ -275,6 +275,9 @@ oggz_read_sync (OGGZ * oggz)
} }
} }
/* If we've got a stop already, don't read more data in */
if (cb_ret != 0) return cb_ret;
if(oggz_get_next_page_7 (oggz, &og) < 0) if(oggz_get_next_page_7 (oggz, &og) < 0)
return -404; /* eof. leave unitialized */ return -404; /* eof. leave unitialized */
...@@ -348,7 +351,7 @@ oggz_read (OGGZ * oggz, long n) ...@@ -348,7 +351,7 @@ oggz_read (OGGZ * oggz, long n)
while (cb_ret != -1 && cb_ret != 1 && bytes_read > 0 && remaining > 0) { while (cb_ret != -1 && cb_ret != 1 && bytes_read > 0 && remaining > 0) {
bytes = MIN (remaining, 4096); bytes = MIN (remaining, 4096);
buffer = ogg_sync_buffer (&reader->ogg_sync, bytes); buffer = ogg_sync_buffer (&reader->ogg_sync, bytes);
if ((bytes_read = (long)fread (buffer, 1, bytes, oggz->file)) == 0) { if ((bytes_read = (long) oggz_io_read (oggz, buffer, bytes)) == 0) {
if (ferror (oggz->file)) { if (ferror (oggz->file)) {
return OGGZ_ERR_SYSTEM; return OGGZ_ERR_SYSTEM;
...@@ -432,7 +435,7 @@ oggz_tell_raw (OGGZ * oggz) ...@@ -432,7 +435,7 @@ oggz_tell_raw (OGGZ * oggz)
{ {
oggz_off_t offset_at; oggz_off_t offset_at;
offset_at = ftell (oggz->file); offset_at = oggz_io_tell (oggz);
return offset_at; return offset_at;
} }
...@@ -446,16 +449,11 @@ oggz_seek_raw (OGGZ * oggz, oggz_off_t offset, int whence) ...@@ -446,16 +449,11 @@ oggz_seek_raw (OGGZ * oggz, oggz_off_t offset, int whence)
OggzReader * reader = &oggz->x.reader; OggzReader * reader = &oggz->x.reader;
oggz_off_t offset_at; oggz_off_t offset_at;
if (fseek (oggz->file, offset, whence) == -1) { if (oggz_io_seek (oggz, offset, whence) == -1) {
if (errno == ESPIPE) {
/*oggz_set_error (oggz, OGGZ_ERR_NOSEEK);*/
} else {
/*oggz_set_error (oggz, OGGZ_ERR_SYSTEM);*/
}
return -1; return -1;
} }
offset_at = ftell (oggz->file); offset_at = oggz_io_tell (oggz);
oggz->offset = offset_at; oggz->offset = offset_at;
...@@ -554,7 +552,7 @@ oggz_get_next_page (OGGZ * oggz, ogg_page * og) ...@@ -554,7 +552,7 @@ oggz_get_next_page (OGGZ * oggz, ogg_page * og)
page_offset = 0; page_offset = 0;
buffer = ogg_sync_buffer (&reader->ogg_sync, CHUNKSIZE); buffer = ogg_sync_buffer (&reader->ogg_sync, CHUNKSIZE);
if ((bytes = (long)fread (buffer, 1, CHUNKSIZE, oggz->file)) == 0) { if ((bytes = (long) oggz_io_read (oggz, buffer, CHUNKSIZE)) == 0) {
if (ferror (oggz->file)) { if (ferror (oggz->file)) {
/*oggz_set_error (oggz, OGGZ_ERR_SYSTEM);*/ /*oggz_set_error (oggz, OGGZ_ERR_SYSTEM);*/
return -1; return -1;
......
...@@ -455,11 +455,14 @@ oggz_page_writeout (OGGZ * oggz, long n) ...@@ -455,11 +455,14 @@ oggz_page_writeout (OGGZ * oggz, long n)
#ifdef OGGZ_WRITE_DIRECT #ifdef OGGZ_WRITE_DIRECT
nwritten = write (fd, og->header + writer->page_offset, h); nwritten = write (fd, og->header + writer->page_offset, h);
#else #else
nwritten = (long)fwrite (og->header + writer->page_offset, 1, h, oggz->file); nwritten = (long)oggz_io_write (oggz, og->header + writer->page_offset, h);
#endif #endif
#ifdef DEBUG
if (nwritten < h) { if (nwritten < h) {
printf ("oggz_page_writeout: %ld < %ld\n", nwritten, h); printf ("oggz_page_writeout: %ld < %ld\n", nwritten, h);
} }
#endif
writer->page_offset += h; writer->page_offset += h;
n -= h; n -= h;
} else { } else {
...@@ -472,12 +475,13 @@ oggz_page_writeout (OGGZ * oggz, long n) ...@@ -472,12 +475,13 @@ oggz_page_writeout (OGGZ * oggz, long n)
nwritten = write (fd, nwritten = write (fd,
og->body + (writer->page_offset - og->header_len), b); og->body + (writer->page_offset - og->header_len), b);
#else #else
nwritten = (long)fwrite (og->body + (writer->page_offset - og->header_len), nwritten = (long)oggz_io_write (oggz, og->body + (writer->page_offset - og->header_len), b);
1, b, oggz->file);
#endif #endif
#ifdef DEBUG
if (nwritten < b) { if (nwritten < b) {
printf ("oggz_page_writeout: %ld < %ld\n", nwritten, b); printf ("oggz_page_writeout: %ld < %ld\n", nwritten, b);
} }
#endif
writer->page_offset += b; writer->page_offset += b;
n -= b; n -= b;
} else { } else {
......
...@@ -17,7 +17,14 @@ write_tests = write-bad-guard write-unmarked-guard write-recursive \ ...@@ -17,7 +17,14 @@ write_tests = write-bad-guard write-unmarked-guard write-recursive \
write-bad-granulepos write-bad-packetno write-bad-granulepos write-bad-packetno
endif endif
TESTS = $(write_tests) if OGGZ_CONFIG_READ
if OGGZ_CONFIG_WRITE
rw_tests = read-generated read-stop-ok read-stop-err \
io-read io-seek io-write
endif
endif
TESTS = $(write_tests) $(rw_tests)
noinst_PROGRAMS = $(TESTS) noinst_PROGRAMS = $(TESTS)
noinst_HEADERS = oggz_tests.h noinst_HEADERS = oggz_tests.h
...@@ -48,3 +55,21 @@ write_bad_granulepos_LDADD = $(OGGZ_LIBS) ...@@ -48,3 +55,21 @@ write_bad_granulepos_LDADD = $(OGGZ_LIBS)
write_bad_packetno_SOURCES = write-bad-packetno.c write_bad_packetno_SOURCES = write-bad-packetno.c
write_bad_packetno_LDADD = $(OGGZ_LIBS) write_bad_packetno_LDADD = $(OGGZ_LIBS)
read_generated_SOURCES = read-generated.c
read_generated_LDADD = $(OGGZ_LIBS)
read_stop_ok_SOURCES = read-stop-ok.c
read_stop_ok_LDADD = $(OGGZ_LIBS)
read_stop_err_SOURCES = read-stop-err.c
read_stop_err_LDADD = $(OGGZ_LIBS)
io_read_SOURCES = io-read.c
io_read_LDADD = $(OGGZ_LIBS)
io_seek_SOURCES = io-seek.c
io_seek_LDADD = $(OGGZ_LIBS)
io_write_SOURCES = io-write.c
io_write_LDADD = $(OGGZ_LIBS)
...@@ -30,9 +30,25 @@ ...@@ -30,9 +30,25 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "config.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#else
# define PRId64 "I64d"
#endif
/* FIXME: on Mac OS X, off_t is 64-bits. Obviously we want a nicer
* way to do it than this, but a quick fix is a good fix */
#ifdef __APPLE__
# define PRI_off_t "q"
#else
# define PRI_off_t "l"
#endif
#define INFO(str) \ #define INFO(str) \
{ printf ("---- %s ...\n", (str)); } { printf ("---- %s ...\n", (str)); }
...@@ -41,3 +57,6 @@ ...@@ -41,3 +57,6 @@
#define FAIL(str) \ #define FAIL(str) \
{ printf ("%s:%d: %s\n", __FILE__, __LINE__, (str)); exit(1); } { printf ("%s:%d: %s\n", __FILE__, __LINE__, (str)); exit(1); }
#undef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment