00001 #include "BufferedFile.h"
00002 #ifndef BUFFEREDFILEFACTORY_H
00003 #include "BufferedFileFactory.h"
00004 #endif
00005
00008 #define TIMETOWAIT 1000
00009
00010 extern int write(int fd,void * data, int size);
00011 BufferedFile::BufferedFile(int fdesc) {
00012 pushBackBlocks = list<CharAndSize *>();
00013 this->fd = fdesc;
00014 parent = NULL;
00015 preadReady = false;
00016 pwriteReady = false;
00017 hasRead = false;
00018 hasWritten = false;
00019 reading = writing = true;
00020 timeToWait = TIMETOWAIT;
00021 }
00022 BufferedFile::BufferedFile() {
00023 parent = NULL;
00024 pushBackBlocks = list<CharAndSize *>();
00025 preadReady = false;
00026 pwriteReady = false;
00027 reading = writing = true;
00028 timeToWait = TIMETOWAIT;
00029 }
00030 void BufferedFile::setBufferedFileFactory(void * p) {
00031 parent = p;
00032 }
00033
00034 int BufferedFile::Write(const char * data,int size) {
00035 hasWritten = true;
00036 return write(fd,(const void *)data, size);
00037
00038
00039 }
00040 BufferedFile::~BufferedFile() {
00041
00042 list<CharAndSize *>::iterator iter = pushBackBlocks.begin();
00043 while (iter != pushBackBlocks.end()) {
00044
00045 delete [] (*iter)->data;
00046 delete (*iter);
00047 iter++;
00048 }
00049 if (fd) {
00050 close(fd);
00051 }
00052 }
00053 void BufferedFile::pushBack(char * data,int size) {
00054 struct CharAndSize * c = new CharAndSize();
00055 c->data = data;
00056 c->size = size;
00057 c->alreadyRead = 0;
00058 pushBackBlocks.push_front(c);
00059 }
00060 int BufferedFile::Read(char * data, int size) {
00061 hasRead = true;
00062 int index = 0;
00063 if (!pushBackBlocks.empty()) {
00064 int si = 0;
00065 int sar = 0;
00066 int min = 0;
00067 int alr = 0;
00068
00069 while (!pushBackBlocks.empty()) {
00070 CharAndSize * block = *(pushBackBlocks.begin());
00071 pushBackBlocks.pop_front();
00072 si = size-index;
00073 min = si;
00074 alr = block->alreadyRead;
00075 sar = (block->size) - alr;
00076 if (sar < min) { sar = min; }
00077 for (int i = 0; i < min; i++) {
00078 data[index+i] = block->data[alr+i];
00079 }
00080
00081 if (sar > si) {
00082
00083
00084 block->alreadyRead+=min;
00085 pushBackBlocks.push_front(block);
00086 return size;
00087 } else if ( sar == si ) {
00088
00089
00090 delete [] block->data;
00091 block->data = NULL;
00092 delete block;
00093 return size;
00094 } else if (sar < si) {
00095 delete [] block->data;
00096 block->data = NULL;
00097 delete block;
00098 index+=sar;
00099 }
00100 }
00101 }
00102 if (index >= size) {
00103 return size;
00104 }
00105 int total = read(fd,(void *)(data+index), sizeof(char)*(size-index));
00106 if (index) {
00107 return total + index;
00108 } else {
00109 return total;
00110 }
00111 }
00112
00113
00114 bool BufferedFile::readReady() {return preadReady;}
00115 bool BufferedFile::writeReady() {return pwriteReady;}
00116
00117 void BufferedFile::Close() {
00118 if (parent!=NULL) {
00119 ((BufferedFileFactory*)parent)->closeFile(this);
00120 }
00121 parent = NULL;
00122 if (fd > 0) {
00123 close(fd);
00124 fd = 0;
00125 }
00126 }
00127
00128 bool BufferedFile::ready(int rw) {
00129 if (pushBackBlocks.size() > 0) {
00130 return true;
00131 }
00132 fd_set tmp_set;
00133 FD_ZERO (&tmp_set);
00134 FD_SET (fd, &tmp_set);
00135 struct timeval tv;
00136 tv.tv_sec = 0;
00137 tv.tv_usec = timeToWait;
00138 int currCount;
00139 if (!rw) {
00140 currCount = select(fd+1, &tmp_set, NULL, NULL, &tv);
00141 } else {
00142 currCount = select(fd+1 ,NULL, &tmp_set, NULL, &tv);
00143 }
00144 return (currCount > 0);
00145 }
00146 void BufferedFile::setWait(int w) {
00147 timeToWait = w;
00148 }
00149 int BufferedFile::getWait() {
00150 return timeToWait;
00151 }
00152 int BufferedFile::getFileHandle() {
00153 return fd;
00154 }
00155 void BufferedFile::setWriteReady(bool b) {
00156 pwriteReady = b;
00157 hasWritten = false;
00158 }
00159 void BufferedFile::setReadReady(bool b) {
00160 preadReady = b;
00161 hasRead = false;
00162 }
00163 void BufferedFile::setWriteOnly() {
00164 reading = false;
00165 writing = true;
00166 setParentRW();
00167 }
00168 void BufferedFile::setParentRW() {
00169 if (parent!=NULL) {
00170 ((BufferedFileFactory*)parent)->setBufferedFileWrite(this,writing);
00171 ((BufferedFileFactory*)parent)->setBufferedFileRead(this,reading);
00172 }
00173 }
00174 void BufferedFile::setReadOnly() {
00175 reading = true;
00176 writing = false;
00177 setParentRW();
00178 }
00179 void BufferedFile::setReadWrite() {
00180 reading = true;
00181 writing = true;
00182 setParentRW();
00183 }
00184 bool BufferedFile::doesRead() {
00185 return reading;
00186 }
00187 bool BufferedFile::doesWrite() {
00188 return writing;
00189 }
00190 bool BufferedFile::hasBeenWritten() {
00191 return hasWritten;
00192 }
00193 bool BufferedFile::hasBeenRead() {
00194 return hasRead;
00195 }