BufferedFileByteStream.cpp

00001 /*********************************************************************** 00002 * * 00003 * ViTooKi * 00004 * * 00005 * title: BufferedFileByteStream.hpp * 00006 * * 00007 * * 00008 * * 00009 * ITEC institute of the University of Klagenfurt (Austria) * 00010 * http://www.itec.uni-klu.ac.at * 00011 * * 00012 * * 00013 * For more information visit the ViTooKi homepage: * 00014 * http://ViTooKi.sourceforge.net * 00015 * vitooki-user@lists.sourceforge.net * 00016 * vitooki-devel@lists.sourceforge.net * 00017 * * 00018 * This file is part of ViTooKi, a free video toolkit. * 00019 * ViTooKi is free software; you can redistribute it and/or * 00020 * modify it under the terms of the GNU General Public License * 00021 * as published by the Free Software Foundation; either version 2 * 00022 * of the License, or (at your option) any later version. * 00023 * * 00024 * This program is distributed in the hope that it will be useful, * 00025 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00026 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00027 * GNU General Public License for more details. * 00028 * * 00029 * You should have received a copy of the GNU General Public License * 00030 * along with this program; if not, write to the Free Software * 00031 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * 00032 * MA 02111-1307, USA. * 00033 * * 00034 ***********************************************************************/ 00035 00036 /*********************************************************************** 00037 * * 00038 * REVISION HISTORY: * 00039 * * 00040 * * 00041 * * 00042 ***********************************************************************/ 00043 00044 #include "BufferedFileByteStream.hpp" 00045 00046 #ifndef WIN32 00047 #include <sys/file.h> 00048 #endif 00049 00050 #ifndef WINCE 00051 #include <errno.h> 00052 #endif 00053 00054 BufferedFileByteStream::BufferedFileByteStream(const char* url, bool forReading) : ByteStream(url,forReading) { 00055 io = NULL; 00056 } 00057 00058 00059 bool BufferedFileByteStream::open() { 00060 if (io) { //already open.... 00061 dprintf_err("BufferedFileByteStream::open: %s already open!\n",url); 00062 return true; 00063 } 00064 00065 if (readOnly) 00066 io = fopen(url,"rb"); 00067 else { 00068 io = fopen(url,"w"); 00069 #ifndef WIN32 00070 if (io) { 00071 //make sure that we are the only writer system-wide! 00072 int val = flock(fileno(io),LOCK_EX | LOCK_NB); 00073 if (val == -1) 00074 perror("BufferedFileByteStream::open flock out-file"); 00075 //ret = ((val == 0) || (errno == ENOLCK)); //eg. NFS might not support flocks 00076 if (errno == EWOULDBLOCK) { 00077 dprintf_err("MuxDemuxIO::open(): FATAL: lock on %s is held by other process! \n", url); 00078 ::exit(1); 00079 } 00080 } 00081 #endif 00082 } 00083 00084 if (!io) { 00085 dprintf_err("BufferedFileByteStream::open: file not found: %s!\n",url); 00086 return false; 00087 } else { 00088 buf_pos = buf_size = 0; //initialize buffer 00089 return true; 00090 } 00091 } 00092 00093 00094 bool BufferedFileByteStream::close() { 00095 if (!io) 00096 return false; 00097 else 00098 return fclose(io); 00099 } 00100 00101 int BufferedFileByteStream::getChar() { 00102 if (!io) 00103 return false; 00104 00105 return fgetc(io); 00106 } 00107 00108 00109 int BufferedFileByteStream::read(void *ptr, int size) { 00110 int ret = 0; 00111 int not_done=1; 00112 00113 if (!io || !readOnly) 00114 return -1; 00115 00116 //dprintf_full("BufferedFileByteStream::read PRE-refilling: buf_size %i\n",buf_size); 00117 00118 if (size > buf_size) { //refill 00119 if (feof(io) || ferror(io)) 00120 return 0; //EOF... sorry... 00121 00122 if (size < BUF_SIZE) { //only small frame request, do a prebuffer! 00123 //dprintf_full("BufferedFileByteStream::read refilling: PRE-buf_size %i pos %i ret %i (req. size %i)\n",buf_size,buf_pos,ret,size); 00124 ret = fread((void*)((char*)buf+buf_pos+buf_size),1,BUF_SIZE,io); 00125 buf_size += ret; 00126 not_done = 1; //force ptr copying later 00127 //dprintf_full("BufferedFileByteStream::read refilling: buf_size %i pos %i ret %i (req. size %i)\n",buf_size,buf_pos,ret,size); 00128 } else { //copy big data directly to ptr 00129 memcpy(ptr, buf+buf_pos, buf_size); //copy old buffer parts 00130 00131 ret = fread((void*)((char*)ptr+buf_size), size - buf_size, 1, io); 00132 ret += buf_size; //add old bytes to new file bytes 00133 buf_size=buf_pos=0; 00134 not_done = 0; //already filled the ptr.... 00135 } 00136 } 00137 00138 if (not_done == 1) { //take from old buffer 00139 assert(buf_size >= size); 00140 memcpy(ptr, buf+buf_pos, size); 00141 buf_size -= size; 00142 buf_pos += size; 00143 if (buf_pos >= BUF_SIZE) { //move data to buffer front.... 00144 //dprintf_full("BufferedFileByteStream::read MOVING buffer (%i bytes) to front (OVERLAPPING? %i)\n",buf_size,buf_size>buf_pos); 00145 memmove(buf, buf+buf_pos, buf_size); 00146 buf_pos = 0; 00147 } 00148 00149 ret = size; 00150 } 00151 00152 //dprintf_full("BufferedFileByteStream::AFTER read buf_size %i, pos %i\n",buf_size,buf_pos); 00153 00154 return ret; 00155 } 00156 00157 00158 int BufferedFileByteStream::write(void *ptr, int size){ 00159 if (!io|| readOnly) 00160 return -1; 00161 00162 int ret = fwrite(ptr,size,1,io); 00163 fflush(io); 00164 00165 //assure that all bytes where written! 00166 if ( (ret < 1) || feof(io) || ferror(io) ) 00167 return -1; 00168 00169 return size; 00170 } 00171 00172 00173 int BufferedFileByteStream::seek(u64 pos) { 00174 if (!io) 00175 return -1; 00176 00177 return fseek(io, pos, SEEK_SET); 00178 } 00179 00180 00181 u64 BufferedFileByteStream::tell() { 00182 if (!io) 00183 return 0; 00184 00185 return ftell(io); 00186 }