261 lines
7.0 KiB
C
261 lines
7.0 KiB
C
|
#pragma once
|
|||
|
|
|||
|
// Objects IO
|
|||
|
//
|
|||
|
// created on 2023-03-10
|
|||
|
|
|||
|
#include "utils.h"
|
|||
|
#include "packet.h"
|
|||
|
|
|||
|
#include <string>
|
|||
|
#include <functional>
|
|||
|
|
|||
|
#define CLS_PTR(cls) typedef cls* cls##_ptr;
|
|||
|
|
|||
|
|
|||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|||
|
//
|
|||
|
/* packet parameter keeper, parameter of corresponding packet
|
|||
|
*/
|
|||
|
#define PROGRESS_NOTIFYER std::function<int(uint64_t/*total*/, uint64_t/*cur-size*/, uint32_t/*err*/, void* /*user data*/)>
|
|||
|
|
|||
|
class packet_data_base : public refer
|
|||
|
{
|
|||
|
PROGRESS_NOTIFYER progress_notify_;
|
|||
|
void* user_data_;
|
|||
|
|
|||
|
protected:
|
|||
|
uint32_t pack_cmd_;
|
|||
|
uint32_t pack_id_;
|
|||
|
|
|||
|
public:
|
|||
|
packet_data_base();
|
|||
|
|
|||
|
protected:
|
|||
|
virtual ~packet_data_base();
|
|||
|
int notify_progress(uint64_t total, uint64_t cur_size, uint32_t err);
|
|||
|
|
|||
|
public:
|
|||
|
void set_packet_param(uint32_t cmd, uint32_t id);
|
|||
|
int get_packet_command(void);
|
|||
|
int get_packet_id(void);
|
|||
|
|
|||
|
void set_progress_notify(PROGRESS_NOTIFYER notify = PROGRESS_NOTIFYER(), void* param = nullptr);
|
|||
|
};
|
|||
|
|
|||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|||
|
//
|
|||
|
/* 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;
|
|||
|
};
|
|||
|
|
|||
|
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:
|
|||
|
~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 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_;
|
|||
|
uint32_t pack_cmd_;
|
|||
|
uint32_t pack_id_;
|
|||
|
|
|||
|
void close(void);
|
|||
|
|
|||
|
public:
|
|||
|
file_saver(void);
|
|||
|
protected:
|
|||
|
~file_saver();
|
|||
|
|
|||
|
public:
|
|||
|
int open(const char* path, uint64_t size, const char* check = nullptr);
|
|||
|
|
|||
|
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;
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|||
|
//
|
|||
|
/* 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;
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
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
|
|||
|
|
|||
|
static MUTEX mem_lock_;
|
|||
|
static uint64_t mem_used_bytes_;
|
|||
|
|
|||
|
public:
|
|||
|
dyn_mem(size_t size);
|
|||
|
dyn_mem(void* buf, size_t size);
|
|||
|
|
|||
|
static uint64_t mem_used(void);
|
|||
|
static dyn_mem* memory(size_t size);
|
|||
|
|
|||
|
protected:
|
|||
|
~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);
|
|||
|
|
|||
|
// 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 file_reader : public data_source
|
|||
|
{
|
|||
|
size_t len_;
|
|||
|
size_t consume_;
|
|||
|
FILE *src_;
|
|||
|
std::string path_;
|
|||
|
|
|||
|
public:
|
|||
|
file_reader();
|
|||
|
|
|||
|
protected:
|
|||
|
~file_reader();
|
|||
|
|
|||
|
public:
|
|||
|
int open(const char* file);
|
|||
|
int attach(FILE* f);
|
|||
|
FILE* detach(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;
|
|||
|
};
|
|||
|
|
|||
|
CLS_PTR(packet_data_base);
|
|||
|
CLS_PTR(data_holder);
|
|||
|
CLS_PTR(mem_holder);
|
|||
|
CLS_PTR(data_source);
|
|||
|
CLS_PTR(dyn_mem);
|
|||
|
CLS_PTR(file_reader);
|
|||
|
|
|||
|
|
|||
|
// 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 <20><>The number of bytes required for this packet, 0 is over for this packet<65><74>
|
|||
|
//
|
|||
|
// 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)
|
|||
|
|