#include "mov-buffer.h" #include "mov-file-buffer.h" #include #include #include #include #if defined(_WIN32) || defined(_WIN64) #define fseek64 _fseeki64 #define ftell64 _ftelli64 #elif defined(__ANDROID__) #define fseek64 fseek #define ftell64 ftell #elif defined(OS_LINUX) #define fseek64 fseeko64 #define ftell64 ftello64 #else #define fseek64 fseek #define ftell64 ftell #endif static int mov_file_read(void* fp, void* data, uint64_t bytes) { if (bytes == fread(data, 1, bytes, (FILE*)fp)) return 0; return 0 != ferror((FILE*)fp) ? ferror((FILE*)fp) : -1 /*EOF*/; } static int mov_file_write(void* fp, const void* data, uint64_t bytes) { return bytes == fwrite(data, 1, bytes, (FILE*)fp) ? 0 : ferror((FILE*)fp); } static int mov_file_seek(void* fp, int64_t offset) { return fseek64((FILE*)fp, offset, offset >= 0 ? SEEK_SET : SEEK_END); } static int64_t mov_file_tell(void* fp) { return ftell64((FILE*)fp); } static int mov_file_cache_read(void* fp, void* data, uint64_t bytes) { uint8_t* p = (uint8_t*)data; struct mov_file_cache_t* file = (struct mov_file_cache_t*)fp; while (bytes > 0) { assert(file->off <= file->len); if (file->off >= file->len) { if (bytes >= sizeof(file->ptr)) { if (bytes == fread(p, 1, bytes, file->fp)) { file->tell += bytes; return 0; } return 0 != ferror(file->fp) ? ferror(file->fp) : -1 /*EOF*/; } else { file->off = 0; file->len = (unsigned int)fread(file->ptr, 1, sizeof(file->ptr), file->fp); if (file->len < 1) return 0 != ferror(file->fp) ? ferror(file->fp) : -1 /*EOF*/; } } if (file->off < file->len) { unsigned int n = file->len - file->off; n = n > bytes ? (unsigned int)bytes : n; memcpy(p, file->ptr + file->off, n); file->tell += n; file->off += n; bytes -= n; p += n; } } return 0; } static int mov_file_cache_write(void* fp, const void* data, uint64_t bytes) { struct mov_file_cache_t* file = (struct mov_file_cache_t*)fp; file->tell += bytes; if (file->off + bytes < sizeof(file->ptr)) { memcpy(file->ptr + file->off, data, bytes); file->off += (unsigned int)bytes; return 0; } // write buffer if (file->off > 0) { if (file->off != fwrite(file->ptr, 1, file->off, file->fp)) return ferror(file->fp); file->off = 0; // clear buffer } // write data; return bytes == fwrite(data, 1, bytes, file->fp) ? 0 : ferror(file->fp); } static int mov_file_cache_seek(void* fp, int64_t offset) { int r; struct mov_file_cache_t* file = (struct mov_file_cache_t*)fp; if (offset != file->tell) { if (file->off > file->len) { // write bufferred data if(file->off != fwrite(file->ptr, 1, file->off, file->fp)) return ferror(file->fp); } file->off = file->len = 0; r = fseek64(file->fp, offset, offset >= 0 ? SEEK_SET : SEEK_END); file->tell = ftell64(file->fp); return r; } return 0; } static int64_t mov_file_cache_tell(void* fp) { struct mov_file_cache_t* file = (struct mov_file_cache_t*)fp; if (ftell64(file->fp) != (int64_t)(file->tell + (uint64_t)(int)(file->len - file->off))) return -1; return (int64_t)file->tell; //return ftell64(file->fp); } const struct mov_buffer_t* mov_file_buffer(void) { static struct mov_buffer_t s_io = { mov_file_read, mov_file_write, mov_file_seek, mov_file_tell, }; return &s_io; } const struct mov_buffer_t* mov_file_cache_buffer(void) { static struct mov_buffer_t s_io = { mov_file_cache_read, mov_file_cache_write, mov_file_cache_seek, mov_file_cache_tell, }; return &s_io; }