123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475 |
- /*=====================================TINYLog======================================================
- **用于单片表的轻量级紧凑型记录队列,目的是能够实现静态的添加记录并查找记录,但是并不关系内部的数据内容与长度
- **由于是队列方式每次更新插入记录都只会将最旧的记录清除,很适合用于历史功能类的相关记录工作
- **
- **由于只是用于支持单片机的,所以支持的缓冲大小只要65K,同时单条消息只到255长度,这也是根据现实情况来考量的 ,以此为基础,
- **也限制了最大的条目数为65K
- **版本V0.1.0
- **author : LXZ
- **history:
- **19.12.07 LXZ 编写第一个版本
- **19.12.12 LXZ 调试完毕,去掉多余接,口实现预计功能
- =====================================================================================================*/
- #include "TinyLog.h"
- #include "MathHelper.h"
- #include <string.h>
- /*================================================================================================
- * 保存的数据结构
- * | 标志位 ’T' 'L' 两字节
- * | 第一条数据开始位置 两字节
- * | 最后一调数据开始位置 两字节
- * | 总记录数 两字节
- * | 预留功能到16字节
- * | 数据缓冲 N字节
- * | CRC两字节
- ==================================================================================================*/
- typedef struct
- {
- unsigned char flag1;
- unsigned char flag2;
- unsigned short first_index;
- unsigned short last_index;
- unsigned short total;
- unsigned short res[4];
- } tiny_log_head_t;
- /**
- * 通过缓冲初始化一个记录,缓冲必须包含有效的记录
- *
- * @author xuzhenglim:276137500 (2019-12-7)
- *
- * @param log
- * @param buf
- * @param size
- */
- void tiny_log_init(tiny_log_t *log, void *buf, int size)
- {
- unsigned char *dat = (unsigned char *)buf;
- //判断是否存在有效的记录
- if (mh_crc16_calc(buf, size) == 0 && dat[0] == 'T' && dat[1] == 'L')
- {
- //存在有效的记录,开始解析记录的数据
- log->log = &dat[sizeof(tiny_log_head_t)];
- log->size = size - sizeof(tiny_log_head_t) - 2;
- log->first = dat[2] + (dat[3] << 8);
- log->last = dat[4] + (dat[5] << 8);
- log->total = dat[6] + (dat[7] << 8);
- log->buf = dat;
- log->cur_site = log->first;
- log->last_index = 0;
- } else
- {
- //存在有效的记录,开始解析记录的数据
- log->log = (void *)((unsigned int)buf + sizeof(tiny_log_head_t));
- log->size = size - sizeof(tiny_log_head_t) - 2;
- log->first = 0;
- log->last = log->first;
- log->total = log->total;
- log->buf = (unsigned char *)buf;
- log->cur_site = log->first;
- log->last_index = 0;
- }
- }
- /**
- * 清空记录
- *
- * @author xuzhenglim:276137500 (2019-12-7)
- *
- * @param log
- */
- void tiny_log_clear(tiny_log_t *log)
- {
- log->first = 0;
- log->last = 0;
- log->total = 0;
- log->idle_size = log->size;
- log->cur_site = log->first;
- }
- /**
- * 查找下一个
- *
- * @author xuzhenglim:276137500 (2019-12-9)
- *
- * @param log
- *
- * @return int -1 表示没有记录
- * 大于等于0数值,表示有数据,并且直接表示记录长度
- */
- int tiny_log_foreach_entry(tiny_log_t *log)
- {
- if (log->total > 0 && (log->last_index + 1) < log->total)
- {
- int size = 0;
- int start = 0;
- if (log->last_index < 0)
- {
- log->last_index = 0;
- log->cur_site = log->first;
- }
- else
- {
- log->last_index++;
- log->cur_site = log->cur_site + log->log[log->cur_site] + 2;
- if (log->cur_site >= log->size)
- {
- log->cur_site -= log->size;
- }
- }
-
- size = log->log[start];
- return size;
- }
- return -1;
- }
- /**
- * 读取当前记录下的标志
- *
- * @author xuzhenglim:276137500 (2019-12-9)
- *
- * @param log
- * @param log_flg
- *
- * @return int -1 表示没有记录
- * 大于等于0数值,表示有数据,并且直接表示记录长度
- */
- int tiny_log_read_type(tiny_log_t *log,char * log_flg)
- {
- if (log->last_index >= 0 && log->total > 0)
- {
- int start = log->cur_site + 1;
- if (start >= log->size)
- {
- start -= log->size;
- }
- *log_flg = log->log[start];
- return log->log[log->cur_site];
- }
- return -1;
- }
- /**
- * 读取记录
- *
- * @author xuzhenglim:276137500 (2019-12-9)
- *
- * @param log
- * @param buf
- *
- * @return int -1 表示没有记录
- * 大于等于0数值,表示有数据,并且直接表示记录长度
- */
- int tiny_log_read_log(tiny_log_t *log,void * buf)
- {
- if (log->last_index >= 0 && log->total > 0)
- {
- unsigned char *dat = (unsigned char *)buf;
- int start = log->cur_site + 2;
- int size = log->log[log->cur_site];
- if (start >= log->size)
- {
- start -= log->size;
- }
- if (size > 0)
- {
- if ((start + size) <= log->size) //可以单次读完
- {
- memcpy(dat, &log->log[start],size);
- }
- else
- {
- //单次无法复制完的情况
- memcpy(dat, &log->log[start], log->size - start);
- memcpy(dat, &log->log[0], start + size - log->size);
- }
- }
- return size;
- }
- return -1;
- }
- /**
- * 定位到对应编号下的记录
- *
- * @author xuzhenglim:276137500 (2019-12-9)
- *
- * @param log
- * @param index
- *
- * @return int -1 表示没有记录
- * 大于等于0数值,表示有数据,并且直接表示记录长度
- */
- int tiny_log_index(tiny_log_t * log, unsigned short index)
- {
- if (index < log->total)
- {
- int start = log->first;
-
- while (index > 0)
- {
- index--;
- start = start + log->log[start] + 2;
- if (start >= log->size)
- {
- start -= log->size;
- }
- }
- log->cur_site = start;
- log->last_index = index;
- return log->log[start];
- }
- return -1;
- }
- /**
- * 在执行快读读取接口的时候必须先调用该接口,用于无效化上一次查找状态
- *
- * @author xuzhenglim:276137500 (2019-12-11)
- *
- * @param log
- * @param log_flg
- * @param buf
- *
- * @return int -1 表示没有记录
- * 大于等于0数值,表示有数据,并且直接表示记录长度
- */
- void tiny_log_beign_read(tiny_log_t * log)
- {
- log->last_index = -1;
- }
- /**
- * 读取下一条记录
- *
- * @author xuzhenglim:276137500 (2019-12-11)
- *
- * @param log
- * @param log_flg
- * @param buf
- *
- * @return int -1 表示没有记录
- * 大于等于0数值,表示有数据,并且直接表示记录长度
- */
- int tiny_log_foreace_read(tiny_log_t * log,char * log_flg,void *dat)
- {
- if (log->total > 0 && (log->last_index + 1) < log->total)
- {
- int size = 0;
- int start = 0;
- if (log->last_index < 0)
- {
- log->last_index = 0;
- log->cur_site = log->first;
- }
- else
- {
- log->last_index++;
- log->cur_site = log->cur_site + log->log[log->cur_site] + 2;
- if (log->cur_site >= log->size)
- {
- log->cur_site -= log->size;
- }
- }
- start = log->cur_site;
- size = log->log[start];
- ++start;
- if (start >= log->size)
- {
- start -= log->size;
- }
-
- *log_flg = log->log[start];
- ++start;
- if (start >= log->size)
- {
- start -= log->size;
- }
- if (size > 0)
- {
- if (start + size <= log->size)
- {
- memcpy(dat, &log->log[start],size);
- }
- else
- {
- memcpy(dat, &log->log[start],log->size - start);
- memcpy(((unsigned char *)dat) + log->size - start, &log->log[0], size - (log->size - start));
- }
- }
- return size;
- }
- return -1;
- }
- /**
- * 插入一条新的记录
- *
- * @author xuzhenglim:276137500 (2019-12-9)
- *
- * @param log
- * @param dat
- * @param size
- */
- void tiny_log_insert(tiny_log_t *log, char log_flg, void *dat, unsigned char size)
- {
- //首先判断当前剩余大小是否足够
- //计算最后一个数据结尾位置
- int tail = 0;
- // int restore = log->size; //剩余大小
- // int index = 0;
- //当有保存数据的时候
- if (log->total > 0)
- {
- tail = log->last + log->log[log->last] + 2;
- if (tail >= log->size)
- {
- tail -= log->size;
- }
- do
- {
- if (log->first >= tail) //剩余空间是在中间部分
- {
- if (log->first - tail > size)
- {
- //剩余空间足够
- break;
- } else
- {
- //减少一条记录
- log->first += log->log[log->first] + 2;
- if (log->first >= log->size)
- {
- log->first -= log->size;
- }
- if (log->total > 0)
- {
- log->total--;
- } else
- {
- break;
- }
- }
- }
- else if((log->size - tail + log->first) < size) //第一条信息地址未必是0,
- {
- //空间依然不够的情况下
- //减少一条记录
- log->first += log->log[log->first] + 2;
- if (log->first >= log->size)
- {
- log->first -= log->size;
- }
- if (log->total > 0)
- {
- log->total--;
- } else
- {
- break;
- }
-
- }
- else
- {
- //这种情况下是肯定满足大小的
- break;
- }
- } while (1);
- }
- if (log->total <= 0)
- {
- //记录空了,直接从头开始存储
- tiny_log_clear(log);
- tail = 0;
- }
- //先保存一个字节的长度信息
- log->last = tail;
- log->log[tail] = (unsigned char)size;
- if (++tail >= log->size)
- {
- tail = 0;
- }
- //保存包标志位
- log->log[tail] = (unsigned char)log_flg;
- if (++tail >= log->size)
- {
- tail = 0;
- }
- //b保存数据
- if (size > 0)
- {
- if (log->size > tail + size)
- {
- //可以满足一次拷贝完成
- memcpy(&log->log[tail], dat, size);
- } else
- {
- //需要分两次拷贝完成
- memcpy(&log->log[tail], dat, log->size - tail);
- //拷贝剩余的数据
- memcpy(&log->log[0], ((unsigned char *)dat) + log->size - tail, size + tail - log->size);
- }
- }
- //总条目数加1
- log->total++;
- //顺序乱掉后,需要重新寻址了
- log->last_index = -1;
- }
- /**
- * 对记录进行保存时需要调用一次
- *
- * @author xuzhenglim:276137500 (2019-12-9)
- *
- * @param log
- */
- void tiny_log_save(tiny_log_t *log)
- {
- unsigned short crc;
- //更新头部信息
- memset(log->buf, 0, sizeof(tiny_log_head_t));
- log->buf[0] = 'T';
- log->buf[1] = 'L';
- log->buf[2] = (log->first & 0xff);
- log->buf[3] = (log->first >> 8);
- log->buf[4] = (log->last & 0xff);
- log->buf[5] = (log->last >> 8);
- log->buf[6] = (log->total & 0xff);
- log->buf[7] = (log->total >> 8);
- crc = mh_crc16_calc(log->buf, log->size + sizeof(tiny_log_head_t));
- log->buf[log->size + sizeof(tiny_log_head_t)] = crc;
- log->buf[log->size + sizeof(tiny_log_head_t) + 1] = crc >> 8;
- }
|