?? stream.cc
字號:
/* * A File */File::File(){ mcount = 0;}#define FILE_TRANSFER_BUFSIZE 4*1024/** * Low-level control function. * @param cmd file control command number * @returns 0 on success, POSIX.1 I/O error code on error */int File::cntl(uint cmd, ...){ va_list vargs; va_start(vargs, cmd); int ret = vcntl(cmd, vargs); va_end(vargs); return ret;}void File::move(FileOfs src, FileOfs dest, FileOfs size){ if (dest < src) { char tbuf[FILE_TRANSFER_BUFSIZE]; while (size != 0) { FileOfs k = size; if (k > sizeof tbuf) k = sizeof tbuf; seek(src); readx(tbuf, k); seek(dest); writex(tbuf, k); src += k; dest += k; size -= k; } } else if (dest > src) { src += size; dest += size; char tbuf[FILE_TRANSFER_BUFSIZE]; while (size != 0) { FileOfs k = size; if (k > sizeof tbuf) k = sizeof tbuf; src -= k; dest -= k; seek(src); readx(tbuf, k); seek(dest); writex(tbuf, k); size -= k; } }}/** * Cut out bytes from file. * Cut out <i>size</i> bytes starting at current file pointer, ending at * current file pointer + <i>size</i>. Does not modify the current file pointer. * * @param size number of bytes to delete * @throws IOException */void File::cut(FileOfs size){ FileOfs t = tell(); FileOfs o = t+size; if (o > getSize()) throw IOException(EINVAL); FileOfs s = getSize()-o; move(o, t, s); truncate(getSize()-size); seek(t);}/** * Extend file. * Extend file to new size <i>newsize</i>. * The current file pointer is undefined (but valid) after this operation. * * @param newsize new extended file size * @throws IOException */void File::extend(FileOfs newsize){ if (getSize() > newsize) throw IOException(EINVAL); if (getSize() == newsize) return; FileOfs save_ofs = tell(); int e = 0; IOAccessMode oldmode = getAccessMode(); if (!(oldmode & IOAM_WRITE)) { int f = setAccessMode(oldmode | IOAM_WRITE); if (f) throw IOException(f); } FileOfs s = getSize(); char buf[FILE_TRANSFER_BUFSIZE]; memset(buf, 0, sizeof buf); newsize -= s; seek(s); while (newsize != 0) { uint k = MIN(sizeof buf, newsize); uint l = write(buf, k); if (l != k) { e = EIO; break; } newsize -= l; } if (!(oldmode & IOAM_WRITE)) { int f = setAccessMode(oldmode); if (f) e = f; } if (e) throw IOException(e); seek(save_ofs);}/** * Get filename. * * @param result String that receives the filename * @returns its argument */String &File::getFilename(String &result) const{ result = ""; return result;}/** * Get file size. * * @returns file size */FileOfs File::getSize() const{ return 0;}#define FILE_INSERT_BUFSIZE 4*1024/** * Insert bytes into file. * Insert <i>size</i> bytes from <i>buf</i> at the current file pointer * into the file and extend file accordingly. * * @param buf pointer to buffer that holds at least <i>size</i> bytes * @param size number of bytes to insert * @throws IOException */void File::insert(const void *buf, FileOfs size){ FileOfs t = tell(); FileOfs s = getSize()-t; extend(getSize()+size); move(t, t+size, s); seek(t); writex(buf, size);}/** * Get file status in a portable way. * @param s structure that receives the file status */void File::pstat(pstat_t &s) const{ s.caps = 0;}/** * Set current file pointer. * @param offset new value for current file pointer */void File::seek(FileOfs offset){ throw NotImplementedException(HERE);}/** * Get current file pointer. * @returns current file pointer */FileOfs File::tell() const{ return 0;}/** * Truncate file. * Truncate file to new size <i>newsize</i>. * The current file pointer is undefined (but valid) after this operation. * * @param newsize new truncated file size * @throws IOException */void File::truncate(FileOfs newsize){ if (getSize() < newsize) throw IOException(EINVAL); if (getSize() == newsize) return; throw NotImplementedException(HERE);}/** * Vararg wrapper for cntl() */int File::vcntl(uint cmd, va_list vargs){ switch (cmd) { case FCNTL_GET_MOD_COUNT: { // int &mcount int *mc = va_arg(vargs, int *); *mc = mcount; return 0; } } return ENOSYS;}char *File::fgetstrz(){ FileOfs o = tell(); /* get string size */ char buf[64]; int s, z = 0; bool found = false; while (!found) { s = read(buf, 64); for (int i=0; i < s; i++) { z++; if (buf[i] == 0) { found = true; break; } } if (s < 64) { break; } } if (s == 0) return ht_strdup(""); /* read string */ char *str = ht_malloc(z); if (!str) throw std::bad_alloc(); seek(o); readx(str, z); str[z-1] = 0; return str;}/* * FileLayer */FileLayer::FileLayer(File *f, bool own_f) : File(){ mFile = f; mOwnFile = own_f;}FileLayer::~FileLayer(){ if (mOwnFile) delete mFile;}void FileLayer::cut(FileOfs size){ return mFile->cut(size);}void FileLayer::extend(FileOfs newsize){ return mFile->extend(newsize);}IOAccessMode FileLayer::getAccessMode() const{ return mFile->getAccessMode();}String &FileLayer::getDesc(String &result) const{ return mFile->getDesc(result);}String &FileLayer::getFilename(String &result) const{ return mFile->getFilename(result);}FileOfs FileLayer::getSize() const{ return mFile->getSize();}void FileLayer::insert(const void *buf, FileOfs size){ return mFile->insert(buf, size);}void FileLayer::pstat(pstat_t &s) const{ return mFile->pstat(s);}uint FileLayer::read(void *buf, uint size){ return mFile->read(buf, size);}void FileLayer::seek(FileOfs offset){ return mFile->seek(offset);}int FileLayer::setAccessMode(IOAccessMode mode){ return mFile->setAccessMode(mode);}File *FileLayer::getLayered() const{ return mFile;}void FileLayer::setLayered(File *newLayered, bool ownNewLayered){ mFile = newLayered; mOwnFile = ownNewLayered;}FileOfs FileLayer::tell() const{ return mFile->tell();}void FileLayer::truncate(FileOfs newsize){ return mFile->truncate(newsize);}int FileLayer::vcntl(uint cmd, va_list vargs){ return mFile->vcntl(cmd, vargs);}uint FileLayer::write(const void *buf, uint size){ return mFile->write(buf, size);}/* * LocalFileFD *//** * create open file */LocalFileFD::LocalFileFD(const String &aFilename, IOAccessMode am, FileOpenMode om) : File(), mFilename(aFilename){ mOpenMode = om; fd = -1; own_fd = false; int e = setAccessMode(am); if (e) throw IOException(e); mOpenMode = FOM_EXISTS;}/** * map a file descriptor [fd] */LocalFileFD::LocalFileFD(int f, bool own_f, IOAccessMode am) : File(){ mFilename = NULL; fd = f; own_fd = own_f; offset = 0; int e = File::setAccessMode(am); if (e) throw IOException(e);}LocalFileFD::~LocalFileFD(){ if (own_fd && (fd>=0)) ::close(fd);}String &LocalFileFD::getDesc(String &result) const{ result = mFilename; return result;}String &LocalFileFD::getFilename(String &result) const{ result = mFilename; return result;}FileOfs LocalFileFD::getSize() const{ FileOfs t = tell(); off_t r = ::lseek(fd, 0, SEEK_END); if (r == (off_t)-1) return 0; // hm... ::lseek(fd, t, SEEK_SET); return r;}uint LocalFileFD::read(void *buf, uint size){ if (!(getAccessMode() & IOAM_READ)) throw IOException(EACCES); errno = 0; uint r = ::read(fd, buf, size); int e = errno; if (e) { ::lseek(fd, 0, SEEK_SET); offset = 0; if (e != EAGAIN) throw IOException(e); return 0; } else { offset += r; return r; } }void LocalFileFD::seek(FileOfs o){ off_t r = ::lseek(fd, o, SEEK_SET); if (r == (off_t)-1) throw IOException(errno); offset = r; if (offset != o) throw IOException(EIO);}int LocalFileFD::setAccessMode(IOAccessMode am){ IOAccessMode orig_access_mode = getAccessMode(); int e = setAccessModeInternal(am); if (e && setAccessModeInternal(orig_access_mode)) throw IOException(e); return e;}int LocalFileFD::setAccessModeInternal(IOAccessMode am){//RETRY: if (getAccessMode() == am) return 0; if (fd >= 0) { // must own fd to change its access mode cause we can't // reopen a fd. right? if (!own_fd) throw NotImplementedException(HERE); // FIXME: race condition here, how to reopen a fd atomically? close(fd); fd = -1; } File::setAccessMode(IOAM_NULL); int mode = 0; if ((am & IOAM_READ) && (am & IOAM_WRITE)) mode = O_RDWR; else if (am & IOAM_READ) mode = O_RDONLY; else if (am & IOAM_WRITE) mode = O_WRONLY;// mode |= O_BINARY; switch (mOpenMode) { case FOM_APPEND: mode |= O_APPEND; break; case FOM_CREATE: mode |= O_CREAT | O_TRUNC; break; case FOM_EXISTS: ; } int e = 0; if (am != IOAM_NULL) { pstat_t s; fd = ::open(mFilename.contentChar(), mode); if (fd < 0) e = errno; if (!e) { own_fd = true; e = sys_pstat_fd(s, fd); if (!e) { if (HT_S_ISDIR(s.mode)) { e = EISDIR; } else if (!HT_S_ISREG(s.mode) && !HT_S_ISBLK(s.mode)) { e = EINVAL; } } } } return e ? e : File::setAccessMode(am);}FileOfs LocalFileFD::tell() const{ return offset;}void LocalFileFD::truncate(FileOfs newsize){ errno = 0; int e = sys_truncate_fd(fd, newsize); if (errno) e = errno; if (e) throw IOException(e);}int LocalFileFD::vcntl(uint cmd, va_list vargs){ switch (cmd) { case FCNTL_FLUSH_STAT: { IOAccessMode m = getAccessMode(); int e, f; e = setAccessMode(IOAM_NULL); f = setAccessMode(m); return e ? e : f; } case FCNTL_GET_FD: { // (int &fd) int *pfd = va_arg(vargs, int*); *pfd = fd; return 0; } } return File::vcntl(cmd, vargs);}uint LocalFileFD::write(const void *buf, uint size){ if (!(getAccessMode() & IOAM_WRITE)) throw IOException(EACCES); errno = 0; uint r = ::write(fd, buf, size); int e = errno; if (e) { ::lseek(fd, 0, SEEK_SET); offset = 0; if (e != EAGAIN) throw IOException(e); return 0; } else { offset += r; return r; } }/* * StdIoFile *//** * create open file */LocalFile::LocalFile(const String &aFilename, IOAccessMode am, FileOpenMode om)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -