#pragma once // Objects IO // // created on 2023-03-10 #include "utils.h" #include "packet.h" #include #include #define CLS_PTR(cls) typedef cls* cls##_ptr; #ifndef uchar typedef unsigned char uchar; #endif //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // /* packet parameter keeper, parameter of corresponding packet */ static const uint64_t FINAL_NOTIFY = -1; #define PROGRESS_NOTIFYER std::function class packet_data_base : public refer { PROGRESS_NOTIFYER progress_notify_; void* user_data_; protected: uint32_t pack_cmd_ = 0; uint32_t pack_id_ = 0; uint32_t session_id_ = -1; public: packet_data_base(); protected: virtual ~packet_data_base(); public: void set_packet_param(uint32_t cmd, uint32_t id); void set_session_id(uint32_t session_id); int get_packet_command(void); int get_packet_id(void); uint32_t get_session_id(void); void set_progress_notify(PROGRESS_NOTIFYER notify = PROGRESS_NOTIFYER(), void* param = nullptr); int notify_progress(uint64_t total, uint64_t cur_size, uint32_t err); }; class file_map : public refer { bool read_only_ = false; // uint32_t os_map_size_ = 0; // desired mapping size of OS uint64_t total_ = 0; // total size of the whole file HANDLE map_ = INVALID_HANDLE_VALUE; // handle of the map-object std::string path_file_; // local file uint64_t map_off_ = 0; // offset in the file of current mapping buffer uint32_t map_size_ = 0; // size of current mapping buffer uint32_t off_ = 0; // offset to align to os_map_size_ uint8_t* buf_ = nullptr; // current mapping buffer void unmap(void); public: file_map(); protected: ~file_map(); public: int open(const char* file, uint64_t size, bool readonly); int close(void); uint64_t total_size(void); uint8_t* map(uint64_t off = 0, uint32_t* size = 0); // size - in: desired size, 0 is from off to end; out: real size uint8_t* buffer(void); }; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // /* data_holder, used when data is also required for a certain packet */ class data_holder : public packet_data_base { public: data_holder(); protected: virtual ~data_holder(); public: virtual int put_data(const void* data, uint32_t* size/*[in] - total bytes of data; [out] - used bytes*/) = 0; // return error code virtual bool is_complete(void) = 0; virtual uint32_t get_required(void) = 0; virtual void cancel(void); }; class mem_holder : public data_holder { uint8_t* buf_ = nullptr; size_t space_ = 0; size_t wpos_ = 0; public: mem_holder(size_t size); protected: virtual ~mem_holder(); // data_holder public: virtual int put_data(const void* data, uint32_t* size/*[in] - total bytes of data; [out] - used bytes*/) override; // return error code virtual bool is_complete(void) override; virtual uint32_t get_required(void) override; public: size_t data_length(void); uint8_t* data(void); }; class image_holder : public mem_holder { PACKIMAGE head_; public: image_holder(LPPACKIMAGE head); protected: virtual ~image_holder(); public: void set_info(LPPACKIMAGE head); LPPACKIMAGE get_info(void); int save_2_file(const char* root_dir, int alg_ind, const char* alg = nullptr); }; class empty_holer : public data_holder { uint64_t size_; uint64_t put_; public: empty_holer(uint64_t size); protected: ~empty_holer(); public: virtual int put_data(const void* data, uint32_t* size/*[in] - total bytes of data; [out] - used bytes*/) override; // return error code virtual bool is_complete(void) override; virtual uint32_t get_required(void) override; }; class file_saver : public data_holder { uint64_t size_; uint64_t wrote_; std::string path_; std::string check_; FILE *dst_; file_map *map_ = nullptr; uint32_t pack_cmd_; uint32_t pack_id_; void close(void); public: file_saver(void); protected: ~file_saver(); public: int set_verify_data(const char* data, size_t len); int open(const char* path, uint64_t size, bool in_mem = false, size_t off = 0); const char* path_file(void); public: virtual int put_data(const void* data, uint32_t* size/*[in] - total bytes of data; [out] - used bytes*/) override; virtual bool is_complete(void) override; virtual uint32_t get_required(void) override; virtual void cancel(void) override; }; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // /* data_source, can be a memory block or STREAM object */ class data_source : public packet_data_base { uint32_t pack_cmd_; uint32_t pack_id_; public: data_source(); protected: virtual ~data_source(); public: virtual bool is_memory_block(void) = 0; virtual uint32_t get_rest(void) = 0; // following API valid when is_memory_block() return true virtual uint8_t* ptr(void) = 0; // following API valid when is_memory_block() return false. return error code virtual int fetch_data(void* buf, uint32_t* size) = 0; }; // #define STAT_MEM #define BEFORE_DESTROY_RET void #define BEFORE_DESTROY_PARAM dyn_mem_shared* mem #define BEFORE_DESTROY_FUNC std::function class dyn_mem : public data_source { uint8_t* buf_; // data buf size_t space_; // occupy space in bytes size_t len_; // data length in bytes #ifdef STAT_MEM static MUTEX mem_lock_; static uint64_t mem_used_bytes_; #endif public: dyn_mem(size_t size); dyn_mem(void* buf, size_t size); #ifdef STAT_MEM static uint64_t mem_used(void); #endif static dyn_mem* memory(size_t size); protected: virtual ~dyn_mem(); public: uint32_t space(void); bool set_len(size_t len); int put(const void* data, int len); void* detach(size_t* size); // for constructed from dyn_mem(void* buf, size_t size) size_t used(size_t len); // used len bytes content, move following data to head and set data length, return rest data length dyn_mem& operator+=(dyn_mem& r); void clear_data(void); // data_source public: virtual bool is_memory_block(void) override; virtual uint32_t get_rest(void) override; // following API valid when is_memory_block() return true virtual uint8_t* ptr(void) override; // following API valid when is_memory_block() return false virtual int fetch_data(void* buf, uint32_t* size) override; }; class dyn_mem_shared : public dyn_mem { BEFORE_DESTROY_FUNC destroy_ = BEFORE_DESTROY_FUNC(); void* param_[4]; public: dyn_mem_shared(void* buf, size_t size, BEFORE_DESTROY_FUNC destroy = BEFORE_DESTROY_FUNC()); protected: ~dyn_mem_shared(); public: bool set_param(void* param, int index = 0); void* get_param(int index = 0); }; class file_reader : public data_source { size_t len_; size_t consume_; FILE *src_ = nullptr; file_map *map_ = nullptr; std::string path_; public: file_reader(); protected: ~file_reader(); public: int open(const char* file, bool in_mem, size_t off = 0); int attach(FILE* f); FILE* detach(void); const char* path_file(void); public: virtual bool is_memory_block(void) override; virtual uint32_t get_rest(void) override; // following API valid when is_memory_block() return true virtual uint8_t* ptr(void) override; // following API valid when is_memory_block() return false virtual int fetch_data(void* buf, uint32_t* size) override; }; class image_packet : public data_source { // dyn_mem* img_; std::shared_ptr> img_; dyn_mem* head_; uint32_t offset_; uint32_t paper_ind_ = 0; std::string info_; bool info_over_; std::string pos_str_; public: image_packet(LPPACKIMAGE head, std::shared_ptr> img, uint32_t scanid, const void* info = nullptr, size_t info_size = 0); protected: virtual ~image_packet(); public: virtual bool is_memory_block(void) override; virtual uint32_t get_rest(void) override; // following API valid when is_memory_block() return true virtual uint8_t* ptr(void) override; // following API valid when is_memory_block() return false. return error code virtual int fetch_data(void* buf, uint32_t* size) override; public: uint32_t get_paper_index(void); }; CLS_PTR(packet_data_base); CLS_PTR(data_holder); CLS_PTR(mem_holder); CLS_PTR(image_holder); CLS_PTR(data_source); CLS_PTR(dyn_mem); CLS_PTR(dyn_mem_shared); CLS_PTR(file_reader); CLS_PTR(image_packet); class dyn_mem_pool : public refer { volatile bool run_ = true; dyn_mem_ptr *pool_ = nullptr; uint32_t count_ = 0; uint32_t unit_ = 0; uint32_t wpos_ = 0; uint32_t rpos_ = 0; public: dyn_mem_pool(uint32_t cnt, uint32_t unit); protected: virtual ~dyn_mem_pool(); public: dyn_mem_ptr take(void); void put(dyn_mem_ptr buf); void stop(void); uint32_t count(void); uint32_t unit(void); uint32_t take_pos(void); }; // callback proto // // parameters: usb_functionfs_event* - the function event ptr // // dyn_mem_ptr - the packet buffer, read-only // // uint32_t* - to return how many data in bytes the handler consumed, the most high bit is to indicate whether should notify the returned packet has sent // // normally, the value should be sizeof(PACK_BASE) + PACK_BASE::payload_len, i.e. the handler consume all data of an entire packet // // when invalid packet, suggest use the entire data // // packet_data_base_ptr* - return data_holder or data_source or nullptr ��The number of bytes required for this packet, 0 is over for this packet�� // // data_holder: the packet/command need more data than dyn_mem_ptr provides to complete the business. such as 'write a large file' // // data_source: the reply content may be a large data (a large file content) // // return value of all routines is the reply packet, nullptr if the packet need not reply // // NOTE: when parameter uint32_t* and packet_data_base_ptr* both are nullptr, it is notifying the command reply packet has sent, callback should return nullptr only // #define FUNCTION_PROTO_PARAMETERS dyn_mem_ptr, uint32_t*, packet_data_base_ptr* #define FUNCTION_PROTO_COMMAND_HANDLE dyn_mem_ptr(FUNCTION_PROTO_PARAMETERS) #define REBUILD_IN_CIS_THREAD #define SENDER_PROTO data_source_ptr ptr, void* param #define RES_CHK_PROTO int type, bool wait, int to_ms, void* param