#include "data.h" #include #if defined(WIN32) || defined(_WIN64) #else #include #include #endif //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // packet_data_base::packet_data_base() : pack_cmd_(0), pack_id_(0) , progress_notify_(PROGRESS_NOTIFYER()), user_data_(nullptr) {} packet_data_base::~packet_data_base() {} int packet_data_base::notify_progress(uint64_t total, uint64_t cur_size, uint32_t err) { if (progress_notify_) progress_notify_(total, cur_size, err, user_data_); else return ENOENT; } void packet_data_base::set_packet_param(uint32_t cmd, uint32_t id) { pack_cmd_ = cmd; pack_id_ = id; } int packet_data_base::get_packet_command(void) { return pack_cmd_; } int packet_data_base::get_packet_id(void) { return pack_id_; } void packet_data_base::set_progress_notify(PROGRESS_NOTIFYER notify, void* param) { progress_notify_ = notify; user_data_ = param; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // data_holder::data_holder() {} data_holder::~data_holder() {} //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // mem_holder::mem_holder(size_t size) : space_(size) { buf_ = (uint8_t*)malloc(size); if (buf_) memset(buf_, 0, size); } mem_holder::~mem_holder() { if (buf_) free(buf_); buf_ = nullptr; } int mem_holder::put_data(const void* data, uint32_t* size) { if (*size > space_ - wpos_) *size = space_ - wpos_; memcpy(buf_ + wpos_, data, *size); wpos_ += *size; return 0; } bool mem_holder::is_complete(void) { return wpos_ >= space_; } uint32_t mem_holder::get_required(void) { if (wpos_ >= space_) return 0; else return space_ - wpos_; } size_t mem_holder::data_length(void) { return wpos_; } uint8_t* mem_holder::data(void) { return buf_; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // empty_holer::empty_holer(uint64_t size) : size_(size), put_(0) {} empty_holer::~empty_holer() {} int empty_holer::put_data(const void* data, uint32_t* size) { if (*size >= size_ - put_) { *size -= size_ - put_; put_ = size_; } else { put_ += *size; } notify_progress(size_, put_, 0); return 0; } bool empty_holer::is_complete(void) { return size_ == put_; } uint32_t empty_holer::get_required(void) { return size_ - put_; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // file_saver::file_saver(void) : size_(0), wrote_(0), path_(""), check_(""), dst_(nullptr), pack_cmd_(0), pack_id_(0) {} file_saver::~file_saver() { close(); } void file_saver::close(void) { if(dst_) fclose(dst_); dst_ = nullptr; size_ = wrote_ = pack_cmd_ = pack_id_ = 0; path_ = check_ = ""; } int file_saver::open(const char* path, uint64_t size, const char* check) { int err = 0; close(); dst_ = fopen(path, "wb"); if(dst_) { unsigned long long space = 0; err = utils::get_disk_space(path, nullptr, &space, nullptr); if (err || space < size * 1.5) { fclose(dst_); dst_ = nullptr; remove(path); if (err == 0) err = ENOSPC; } else { path_ = path; size_ = size; check_ = check ? check : ""; } } else { err = errno; } return err; } int file_saver::put_data(const void* data, uint32_t* size/*[in] - total bytes of data; [out] - used bytes*/) { if(!dst_) return ENOENT; int w = *size > size_ - wrote_ ? size_ - wrote_ : *size, real_w = fwrite(data, 1, w, dst_), // should handle error here ! err = 0; *size = real_w; wrote_ += real_w; if(wrote_ >= size_) { fclose(dst_); dst_ = nullptr; } else if (real_w < w) // what happens ? { err = ferror(dst_); } notify_progress(size_, wrote_, err); return 0; } bool file_saver::is_complete(void) { return wrote_ >= size_; } uint32_t file_saver::get_required(void) { return size_ - wrote_; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // data_source::data_source() {} data_source::~data_source() {} ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // dyn_mem uint64_t dyn_mem::mem_used_bytes_ = 0; MUTEX dyn_mem::mem_lock_; dyn_mem::dyn_mem(size_t size) : buf_(nullptr), len_(0), space_(ALIGN_TO(size, 16)) { buf_ = (uint8_t*)malloc(space_); if (buf_) { SIMPLE_LOCK(dyn_mem::mem_lock_); dyn_mem::mem_used_bytes_ += space_; memset(buf_, 0, space_); } } dyn_mem::dyn_mem(void* buf, size_t size) : buf_((uint8_t*)buf), space_(size), len_(size) { } dyn_mem::~dyn_mem() { if (buf_) { free(buf_); { SIMPLE_LOCK(dyn_mem::mem_lock_); dyn_mem::mem_used_bytes_ -= space_; } } } uint64_t dyn_mem::mem_used(void) { return dyn_mem::mem_used_bytes_; } dyn_mem_ptr dyn_mem::memory(size_t size) { return new dyn_mem(size); } uint32_t dyn_mem::space(void) { return space_; } bool dyn_mem::set_len(size_t len) { if (len > space_) return false; len_ = len; return true; } int dyn_mem::put(const void* data, int len) { if (len + len_ > space_) len = space_ - len; if (len > 0) { memcpy(buf_ + len_, data, len); len_ += len; } else len = 0; return len; } void* dyn_mem::detach(size_t* size) { void* buf = buf_; if (size) *size = space_; space_ = len_ = 0; buf_ = nullptr; return buf; } size_t dyn_mem::used(size_t len) { if (len >= len_) { len_ = 0; } else if (len) { memcpy(buf_, buf_ + len, len_ - len); len_ -= len; } return len_; } dyn_mem& dyn_mem::operator+=(dyn_mem& r) { if (len_ + r.get_rest() > space_) { size_t size = ALIGN_TO(len_ + r.get_rest(), 16); uint8_t* buf = (uint8_t*)malloc(size); memcpy(buf, buf_, len_); free(buf_); buf_ = buf; { SIMPLE_LOCK(dyn_mem::mem_lock_); dyn_mem::mem_used_bytes_ += size - space_; } space_ = size; } memcpy(buf_ + len_, r.buf_, r.get_rest()); len_ += r.get_rest(); return *this; } bool dyn_mem::is_memory_block(void) { return true; } uint32_t dyn_mem::get_rest(void) { return len_; } // following API valid when is_memory_block() return true uint8_t* dyn_mem::ptr(void) { return buf_; } // following API valid when is_memory_block() return false int dyn_mem::fetch_data(void* buf, uint32_t* size) { if (*size >= len_) { memcpy(buf, buf_, len_); *size = len_; len_ = 0; } else { memcpy(buf, buf_, *size); used(*size); } return 0; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // file_reader::file_reader() : len_(0), src_(nullptr), path_(""), consume_(0) {} file_reader::~file_reader() { if(src_) fclose(src_); } int file_reader::open(const char* file) { if(src_) fclose(src_); src_ = fopen(file, "rb"); if(!src_) return errno; FSEEK(src_, 0, SEEK_END); len_ = FTELL(src_); FSEEK(src_, 0, SEEK_SET); path_ = file; consume_ = 0; return 0; } int file_reader::attach(FILE* f) { if (src_) { fclose(src_); src_ = nullptr; } uint64_t cur = FTELL(f); FSEEK(f, 0, SEEK_END); len_ = FTELL(f); FSEEK(f, cur, SEEK_SET); if (len_ <= cur) return EINVAL; src_ = f; len_ -= cur; consume_ = 0; return 0; } FILE* file_reader::detach(void) { FILE* ret = src_; src_ = nullptr; len_ = 0; path_ = ""; return ret; } bool file_reader::is_memory_block(void) { return false; } uint32_t file_reader::get_rest(void) { return len_ - consume_; } // following API valid when is_memory_block() return true uint8_t* file_reader::ptr(void) { return nullptr; } // following API valid when is_memory_block() return false int file_reader::fetch_data(void* buf, uint32_t* size) { if (!src_) return ENODATA; size_t r = fread(buf, 1, *size, src_); // fix me if ERROR occurs !!! consume_ += r; *size = r; if (consume_ >= len_) { fclose(src_); src_ = nullptr; } notify_progress(len_, consume_, 0); return 0; }