/******************************************************************** ** Image Component Library (ICL) ** ** ** ** Copyright (C) 2006-2013 CITEC, University of Bielefeld ** ** Neuroinformatics Group ** ** Website: www.iclcv.org and ** ** http://opensource.cit-ec.de/projects/icl ** ** ** ** File : ICLUtils/src/ICLUtils/File.cpp ** ** Module : ICLUtils ** ** Authors: Christof Elbrechter ** ** ** ** ** ** GNU LESSER GENERAL PUBLIC LICENSE ** ** This file may be used under the terms of the GNU Lesser General ** ** Public License version 3.0 as published by the ** ** ** ** Free Software Foundation and appearing in the file LICENSE.LGPL ** ** included in the packaging of this file. Please review the ** ** following information to ensure the license requirements will ** ** be met: http://www.gnu.org/licenses/lgpl-3.0.txt ** ** ** ** The development of this software was supported by the ** ** Excellence Cluster EXC 277 Cognitive Interaction Technology. ** ** The Excellence Cluster EXC 277 is a grant of the Deutsche ** ** Forschungsgemeinschaft (DFG) in the context of the German ** ** Excellence Initiative. ** ** ** ********************************************************************/ #include #include #include #include #include #include #ifdef ICL_HAVE_LIBZ #include #endif namespace icl{ namespace utils{ namespace{ static const char DIR_SEPERATOR = '/'; static const char NEW_LINE = '\n'; std::string toString(File::OpenMode om){ switch(om){ case File::writeBinary: return "Write Binary"; case File::writeText: return "Write Text"; case File::readBinary: return "Read Binary"; case File::readText: return "Read Text"; default: return "unknown mode"; } } void break_apart(std::string s, std::string &dir, std::string &basename, std::string &suffix, std::string &filename){ // {{{ open size_t p = s.rfind(DIR_SEPERATOR); /// split directory xxx/filename.suffix if(p==std::string::npos){ dir = ""; filename = s; }else{ dir = s.substr(0,p); filename = s.substr(p+1); } // split suffix p = filename.rfind('.'); if(p == std::string::npos){ suffix = ""; basename = filename; }else{ suffix = filename.substr(p); basename = filename.substr(0,p); if(suffix == ".gz"){ p = basename.rfind('.'); ; if(p != std::string::npos){ suffix = basename.substr(p)+suffix; basename = basename.substr(0,p-1); } } } } // }}} void buffer_file(FILE *fp, std::vector &data){ // {{{ open int len = 0; static const int LEN = 1024; std::vector buf(1,new unsigned char[LEN]); int curlen = fread(buf[0],1,LEN,fp); if(curlen == -1) ERROR_LOG("error reading file"); while(curlen==LEN){ len += curlen; buf.push_back(new unsigned char[LEN]); curlen = fread(buf[buf.size()-1],1,LEN,fp); if(curlen == -1) ERROR_LOG("error reading file"); } data.resize(len+curlen); for(unsigned int i=0;i &data){ // {{{ open int len = 0; static const int LEN = 1024; std::vector buf(1,new unsigned char[LEN]); int curlen = gzread(fp,buf[0],LEN); if(curlen == -1) ERROR_LOG("error reading file"); while(curlen==LEN){ len += curlen; buf.push_back(new unsigned char[LEN]); curlen = gzread(fp,buf[buf.size()-1],LEN); if(curlen == -1) ERROR_LOG("error reading file"); } data.resize(len+curlen); for(unsigned int i=0;iopenmode = openmode; } // }}} void reopen(File::OpenMode openmode){ // {{{ open if(!handle){ open(openmode); return; } const char *pcOpenMode = s_apcOpenModes[openmode]; #ifdef ICL_HAVE_LIBZ if(gzipped){ gzclose((gzFile)handle); handle = gzopen(name.c_str(),pcOpenMode); }else{ handle = freopen(name.c_str(),pcOpenMode,(FILE*)handle); } #else handle = freopen(name.c_str(),pcOpenMode,(FILE*)handle); #endif binary = openmode == File::readBinary || openmode == File::writeBinary; this->openmode = openmode; } // }}} void close(){ // {{{ open ICLASSERT_RETURN(handle); #ifdef ICL_HAVE_LIBZ if(gzipped){ gzclose((gzFile)handle); }else{ fclose((FILE*)handle); } #else fclose((FILE*)handle); #endif handle = 0; } // }}} void bufferData() { // {{{ open ICLASSERT_RETURN(handle); if(buffer.size()) return; #ifdef ICL_HAVE_LIBZ if(gzipped){ buffer_file_gz((gzFile)handle,buffer); }else{ buffer_file((FILE*)handle,buffer); } #else buffer_file((FILE*)handle,buffer); #endif bufferoffset = 0; } // }}} std::string name; std::string dir; std::string suffix; std::string basename; std::string filename; void *handle; #ifdef ICL_HAVE_LIBZ bool gzipped; #endif std::vector buffer; mutable int bufferoffset; bool binary; std::string precision; char writebuf[100]; File::OpenMode openmode; }; void FileImplDelOp::delete_func(FileImpl *i){ // {{{ open ICL_DELETE( i ); } // }}} File::File(): // {{{ open ShallowCopyable(0){ } // }}} File::File(const std::string &name): // {{{ open ShallowCopyable(new FileImpl(name)){ } // }}} File::File(const std::string &name, File::OpenMode openmode): // {{{ open ShallowCopyable(new FileImpl(name)){ open(openmode); } // }}} File::~File(){ // {{{ open if(isOpen()) close(); } // }}} bool File::isBinary() const{ // {{{ open ICLASSERT_RETURN_VAL(!isNull(),false); return impl->binary; } // }}} bool File::exists() const{ // {{{ open ICLASSERT_RETURN_VAL(!isNull(),false); return file_exists(impl->name); } bool File::isDirectory() const{ // {{{ open ICLASSERT_RETURN_VAL(!isNull(),false); return file_is_dir(impl->name); } // }}} // }}} bool File::isOpen() const{ // {{{ open ICLASSERT_RETURN_VAL(!isNull(),false); return impl->handle != 0; } // }}} std::string File::getDir() const{ // {{{ open ICLASSERT_RETURN_VAL(!isNull(),""); return impl->dir; } // }}} std::string File::getBaseName() const{ // {{{ open ICLASSERT_RETURN_VAL(!isNull(),""); return impl->basename; } // }}} std::string File::getSuffix() const{ // {{{ open ICLASSERT_RETURN_VAL(!isNull(),""); return impl->suffix; } // }}} std::string File::getName() const{ // {{{ open ICLASSERT_RETURN_VAL(!isNull(),""); return impl->name; } // }}} void File::write(const void *data, int len){ // {{{ open ICLASSERT_RETURN(!isNull()); ICLASSERT_RETURN(isOpen()); int bytesWritten = 0; #ifdef ICL_HAVE_LIBZ if(impl->gzipped){ while(bytesWritten < len){ bytesWritten += gzwrite((gzFile)(impl->handle),data,len); } }else{ while(bytesWritten < len){ bytesWritten += fwrite(data,1,len,(FILE*)(impl->handle)); } } #else while(bytesWritten < len){ bytesWritten += fwrite(data,1,len,(FILE*)(impl->handle)); } #endif } // }}} void File::writeLine(const void *data, int len){ // {{{ open ICLASSERT_RETURN(!isBinary()); write(data,0); write(&NEW_LINE,1); } // }}} void File::write(const std::string &text){ // {{{ open if(isBinary()){ write(text.c_str(),text.length()); }else{ write(text.c_str(),text.length()); } } // }}} void File::setPrecision(const std::string &p){ // {{{ open ICLASSERT_RETURN(!isNull()); impl->precision = p; } // }}} File &File::operator<<(char c){ // {{{ open ICLASSERT_RETURN_VAL(!isNull(),*this); if(isBinary()){ write(&c,sizeof(char)); }else{ sprintf(impl->writebuf,"%c",c); write(impl->writebuf); } return *this; } // }}} File &File::operator<<(unsigned char uc){ // {{{ open ICLASSERT_RETURN_VAL(!isNull(),*this); if(isBinary()){ write(&uc,sizeof(unsigned char)); }else{ sprintf(impl->writebuf,"%u",uc); write(impl->writebuf); } return *this; } // }}} File &File::operator<<(int i){ // {{{ open ICLASSERT_RETURN_VAL(!isNull(),*this); if(isBinary()){ write(&i,sizeof(int)); }else{ sprintf(impl->writebuf,"%d",i); write(impl->writebuf); } return *this; } // }}} File &File::operator<<(unsigned int ui){ // {{{ open ICLASSERT_RETURN_VAL(!isNull(),*this); if(isBinary()){ write(&ui,sizeof(unsigned int)); }else{ sprintf(impl->writebuf,"%u",ui); write(impl->writebuf); } return *this; } // }}} File &File::operator<<(float f){ // {{{ open ICLASSERT_RETURN_VAL(!isNull(),*this); if(isBinary()){ write(&f,sizeof(float)); }else{ sprintf(impl->writebuf,impl->precision.c_str(),f); write(impl->writebuf); } return *this; } // }}} File &File::operator<<(double d){ // {{{ open ICLASSERT_RETURN_VAL(!isNull(),*this); if(isBinary()){ write(&d,sizeof(double)); }else{ sprintf(impl->writebuf,impl->precision.c_str(),d); write(impl->writebuf); } return *this; } // }}} File &File::operator<<(const std::string &s){ // {{{ open write(s); return *this; } // }}} bool File::canRead() const { // {{{ open ICLASSERT_RETURN_VAL(!isNull(),0); ICLASSERT_RETURN_VAL(isOpen(),0); return getOpenMode() == readText || getOpenMode() == readBinary; } // }}} bool File::canWrite() const { // {{{ open ICLASSERT_RETURN_VAL(!isNull(),0); ICLASSERT_RETURN_VAL(isOpen(),0); return getOpenMode() == writeText || getOpenMode() == writeBinary; } // }}} bool File::hasMoreLines() const{ // {{{ open return bytesAvailable(); } // }}} int File::bytesAvailable() const{ // {{{ open ICLASSERT_RETURN_VAL(!isNull(),0); ICLASSERT_RETURN_VAL(isOpen(),0); const std::vector &data = readAll(); int offs = impl->bufferoffset; return std::max(0,data.size()-offs); } // }}} int File::getFileSize() const{ // {{{ open ICLASSERT_RETURN_VAL(!isNull(),0); ICLASSERT_RETURN_VAL(isOpen(),0); ICLASSERT_RETURN_VAL(canRead(),0); return readAll().size(); } // }}} std::string File::readLine() const{ // {{{ open ICLASSERT_RETURN_VAL(!isNull(),""); ICLASSERT_RETURN_VAL(isOpen(),""); ICLASSERT_RETURN_VAL(hasMoreLines(),""); const std::vector &data = readAll(); unsigned int i=impl->bufferoffset; while(ibufferoffset,data.begin()+i); if(isBinary()){ i++; }else{ while(ibufferoffset = i; return s; } // }}} std::string &File::readLine(std::string &dst) const{ // {{{ open static std::string _null; ICLASSERT_RETURN_VAL(!isNull(),_null); ICLASSERT_RETURN_VAL(isOpen(),_null); ICLASSERT_RETURN_VAL(hasMoreLines(),_null); ICLASSERT_RETURN_VAL(!isBinary(),_null); const std::vector &data = readAll(); unsigned int i=impl->bufferoffset; while(ibufferoffset); std::copy(data.begin()+impl->bufferoffset,data.begin()+i,dst.begin()); while(ibufferoffset = i; return dst; } // }}} std::vector File::read(int len) const{ // {{{ open static std::vector vec; ICLASSERT_RETURN_VAL(!isNull(),vec); ICLASSERT_RETURN_VAL(isOpen(),vec); ICLASSERT_RETURN_VAL(len <= bytesAvailable(),vec); vec.resize(len); const std::vector &data = readAll(); std::copy(&data[0]+impl->bufferoffset,&data[0]+impl->bufferoffset+len,&vec[0]); impl->bufferoffset+=len; return data; } // }}} int File::read(int len, void *dst) const{ // {{{ open ICLASSERT_RETURN_VAL(!isNull(),0); ICLASSERT_RETURN_VAL(isOpen(),0); len = iclMin(len,bytesAvailable()); const std::vector &data = readAll(); std::copy(&data[0]+impl->bufferoffset,&data[0]+impl->bufferoffset+len,(icl8u*)dst); impl->bufferoffset+=len; return len; } // }}} const std::vector &File::readAll() const{ // {{{ open static std::vector _null; ICLASSERT_RETURN_VAL(!isNull(),_null); ICLASSERT_RETURN_VAL(isOpen(),_null); const_cast(impl.get())->bufferData(); return impl->buffer; } // }}} const icl8u* File::getCurrentDataPointer() const{ // {{{ open ICLASSERT_RETURN_VAL(!isNull(),0); ICLASSERT_RETURN_VAL(isOpen(),0); return (&(readAll()[0]))+impl->bufferoffset; } // }}} const icl8u* File::getFileDataPointer() const{ // {{{ open ICLASSERT_RETURN_VAL(!isNull(),0); ICLASSERT_RETURN_VAL(isOpen(),0); return &readAll()[0]; } // }}} void File::open(File::OpenMode openmode){ // {{{ open ICLASSERT_RETURN(!isNull()); ICLASSERT_RETURN(!isOpen()); ICLASSERT_RETURN(openmode != notOpen); impl->open(openmode); ICLASSERT_THROW(isOpen(),FileOpenException(getName()+"(OpenMode: "+toString(openmode)+")")); } // }}} void File::close(){ // {{{ open ICLASSERT_RETURN(!isNull()); impl->close(); } // }}} void File::reset(){ // {{{ open ICLASSERT_RETURN(!isNull()); if(getOpenMode() == readBinary || getOpenMode() == readText){ impl->bufferoffset = 0; }else{ ERROR_LOG("resetting file position is only allowed in read mode (which is buffered!)"); } } // }}} void File::erase(){ // {{{ open ICLASSERT_RETURN(!isNull() && exists()); remove(getName().c_str()); } // }}} void File::reopen(File::OpenMode om){ // {{{ open ICLASSERT_RETURN(!isNull()); impl->reopen(om); ICLASSERT_THROW(isOpen(),FileOpenException(getName()+"(OpenMode: "+toString(om)+")")); } // }}} File::OpenMode File::getOpenMode() const{ // {{{ open ICLASSERT_RETURN_VAL(!isNull(),notOpen); ICLASSERT_RETURN_VAL(isOpen(),notOpen); return impl->openmode; } // }}} void *File::getHandle() const{ // {{{ open ICLASSERT_RETURN_VAL(!isNull(),0); ICLASSERT_RETURN_VAL(isOpen(),0); return impl->handle; } // }}} std::string File::read_file(const std::string &filename, bool textMode){ File f(filename,textMode ? File::readText:File::readBinary); const int len = f.getFileSize(); std::string s(len+1,'\0'); std::copy(f.getFileDataPointer(),f.getFileDataPointer()+len,&s[0]); return s; } std::vector File::read_lines(const std::string &filename){ return tok(read_file(filename,true),"\\n"); } void File::write_file(const std::string &filename, const std::string &text, bool textMode){ File f(filename,textMode ? File::writeText:File::writeBinary); f.write(text); } void File::write_lines(const std::string &filename, const std::vector &lines){ File f(filename,File::writeText); for(size_t i=0;i