⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tarstream.cc

📁 本人收集整理的一份c/c++跨平台网络库
💻 CC
📖 第 1 页 / 共 2 页
字号:
#include "basicdefs.h"#include "basictypes.h"#include "tarstream.h"#include "pathutils.h"#include "stringutils.h"#include "common.h"using namespace utils_base;///////////////////////////////////////////////////////////////////////////////// TarStream///////////////////////////////////////////////////////////////////////////////TarStream::TarStream() : mode_(M_NONE), next_block_(NB_NONE), block_pos_(0),                         current_(NULL), current_bytes_(0) {}TarStream::~TarStream() {  Close();}bool TarStream::AddFilter(const std::string& pathname) {  if (pathname.empty())    return false;  Pathname archive_path(pathname);  archive_path.SetFolderDelimiter('/');  archive_path.Normalize();  filters_.push_back(archive_path.pathname());  return true;}bool TarStream::Open(const std::string& folder, bool read) {  Close();  Pathname root_folder;  root_folder.SetFolder(folder);  root_folder.Normalize();  root_folder_.assign(root_folder.folder());  if (read) {    std::string pattern(root_folder_);    DirectoryIterator *iter = new DirectoryIterator();    if (iter->Iterate(pattern) == false) {      delete iter;      return false;    }    mode_ = M_READ;    find_.push_front(iter);    next_block_ = NB_FILE_HEADER;    block_pos_ = BLOCK_SIZE;    int error;    if (SR_SUCCESS != ProcessNextEntry(find_.front(), &error)) {      return false;    }  } else {    if (!Filesystem::CreateFolder(root_folder_)) {      return false;    }    mode_ = M_WRITE;    next_block_ = NB_FILE_HEADER;    block_pos_ = 0;  }  return true;}StreamState TarStream::GetState() const {  return (M_NONE == mode_) ? SS_CLOSED : SS_OPEN;}StreamResult TarStream::Read(void* buffer, size_t buffer_len,                             size_t* read, int* error) {  if (M_READ != mode_) {    return SR_EOS;  }  return ProcessBuffer(buffer, buffer_len, read, error);}StreamResult TarStream::Write(const void* data, size_t data_len,                              size_t* written, int* error) {  if (M_WRITE != mode_) {    return SR_EOS;  }  // Note: data is not modified unless M_READ == mode_  return ProcessBuffer(const_cast<void*>(data), data_len, written, error);}void TarStream::Close() {  root_folder_.clear();  next_block_ = NB_NONE;  block_pos_ = 0;  delete current_;  current_ = NULL;  current_bytes_ = 0;  for (DirectoryList::iterator it = find_.begin(); it != find_.end(); ++it) {    delete(*it);  }  find_.clear();  subfolder_.clear();}StreamResult TarStream::ProcessBuffer(void* buffer, size_t buffer_len,                                      size_t* consumed, int* error) {  size_t local_consumed;  if (!consumed) consumed = &local_consumed;  int local_error;  if (!error) error = &local_error;  StreamResult result = SR_SUCCESS;  *consumed = 0;  while (*consumed < buffer_len) {    size_t available = BLOCK_SIZE - block_pos_;    if (available == 0) {      result = ProcessNextBlock(error);      if (SR_SUCCESS != result) {        break;      }    } else {      size_t bytes_to_copy = utils_base::_min(available, buffer_len - *consumed);      char* buffer_ptr = static_cast<char*>(buffer) + *consumed;      char* block_ptr = block_ + block_pos_;      if (M_READ == mode_) {        memcpy(buffer_ptr, block_ptr, bytes_to_copy);      } else {        memcpy(block_ptr, buffer_ptr, bytes_to_copy);      }      *consumed += bytes_to_copy;      block_pos_ += bytes_to_copy;    }  }  // SR_EOS means no data was consumed on this operation.  So we may need to  // return SR_SUCCESS instead, and then we will return SR_EOS next time.  if ((SR_EOS == result) && (*consumed > 0)) {    result = SR_SUCCESS;  }  return result;}StreamResult TarStream::ProcessNextBlock(int* error) {  ASSERT(NULL != error);  ASSERT(M_NONE != mode_);  ASSERT(BLOCK_SIZE == block_pos_);  StreamResult result;  if (NB_NONE == next_block_) {    return SR_EOS;  } else if (NB_TRAILER == next_block_) {    // Trailer block is zeroed    result = ProcessEmptyBlock(0, error);    if (SR_SUCCESS != result)      return result;    next_block_ = NB_NONE;  } else if (NB_FILE_HEADER == next_block_) {    if (M_READ == mode_) {      result = ReadNextFile(error);    } else {      result = WriteNextFile(error);    }    // If there are no more files, we are at the first trailer block    if (SR_EOS == result) {      block_pos_ = 0;      next_block_ = NB_TRAILER;      result = ProcessEmptyBlock(0, error);    }    if (SR_SUCCESS != result)      return result;  } else if (NB_DATA == next_block_) {    size_t block_consumed = 0;    size_t block_available = utils_base::_min<size_t>(BLOCK_SIZE, current_bytes_);    while (block_consumed < block_available) {      void* block_ptr = static_cast<char*>(block_) + block_consumed;      size_t available = block_available - block_consumed, consumed;      if (M_READ == mode_) {        ASSERT(NULL != current_);        result = current_->Read(block_ptr, available, &consumed, error);      } else if (current_) {        result = current_->Write(block_ptr, available, &consumed, error);      } else {        consumed = available;        result = SR_SUCCESS;      }      switch (result) {      case SR_ERROR:        return result;      case SR_BLOCK:      case SR_EOS:        ASSERT(false);        *error = 0; // TODO: make errors        return SR_ERROR;      case SR_SUCCESS:        block_consumed += consumed;        break;      }    }    current_bytes_ -= block_consumed;    if (current_bytes_ == 0) {      // The remainder of the block is zeroed      result = ProcessEmptyBlock(block_consumed, error);      if (SR_SUCCESS != result)        return result;      delete current_;      current_ = NULL;      next_block_ = NB_FILE_HEADER;    }  } else {    ASSERT(false);  }  block_pos_ = 0;  return SR_SUCCESS;}StreamResult TarStream::ProcessEmptyBlock(size_t start, int* error) {  ASSERT(NULL != error);  ASSERT(M_NONE != mode_);  if (M_READ == mode_) {    memset(block_ + start, 0, BLOCK_SIZE - start);  } else {    if (!utils_base::memory_check(block_ + start, 0, BLOCK_SIZE - start)) {      *error = 0; // TODO: make errors      return SR_ERROR;    }  }  return SR_SUCCESS;}StreamResult TarStream::ReadNextFile(int* error) {  ASSERT(NULL != error);  ASSERT(M_READ == mode_);  ASSERT(NB_FILE_HEADER == next_block_);  ASSERT(BLOCK_SIZE == block_pos_);  ASSERT(NULL == current_);  // ReadNextFile conducts a depth-first recursive search through the directory  // tree.  find_ maintains a stack of open directory handles, which  // corresponds to our current position in the tree.  At any point, the  // directory at the top (front) of the stack is being enumerated.  If a  // directory is found, it is opened and pushed onto the top of the stack.  // When a directory enumeration completes, that directory is popped off the  // top of the stack.  // Note: Since ReadNextFile can only return one block of data at a time, we  // cannot simultaneously return the entry for a directory, and the entry for  // the first element in that directory at the same time.  In this case, we  // push a NULL entry onto the find_ stack, which indicates that the next  // iteration should begin enumeration of the "new" directory.  StreamResult result = SR_SUCCESS;  while (BLOCK_SIZE == block_pos_) {    ASSERT(!find_.empty());    if (NULL != find_.front()) {      if (find_.front()->Next()) {	result = ProcessNextEntry(find_.front(), error);        if (SR_SUCCESS != result) {          return result;        }        continue;      }      delete(find_.front());    } else {      Pathname pattern(root_folder_);      pattern.AppendFolder(subfolder_);      find_.front() = new DirectoryIterator();      if (find_.front()->Iterate(pattern.pathname())) {        result = ProcessNextEntry(find_.front(), error);        if (SR_SUCCESS != result) {          return result;        }        continue;      }      // TODO: should this be an error?      LOG_F(LS_WARNING) << "Couldn't open folder: " << pattern.pathname();    }    find_.pop_front();    subfolder_ = Pathname(subfolder_).parent_folder();    if (find_.empty()) {      return SR_EOS;    }  }  ASSERT(0 == block_pos_);  return SR_SUCCESS;}StreamResult TarStream::WriteNextFile(int* error) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -