实现读取nand的id,正在编写坏块管理算法
This commit is contained in:
180
source/soft/buff.c
Normal file
180
source/soft/buff.c
Normal file
@@ -0,0 +1,180 @@
|
||||
#include "buff.h"
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include "stdio.h"
|
||||
|
||||
|
||||
|
||||
#ifdef RT_THREAD
|
||||
#include "rthw.h"
|
||||
#define IRQ_DISABLE() rt_base_t irq_stat=rt_hw_interrupt_disable( )
|
||||
#define IRQ_ENABLE() rt_hw_interrupt_enable (irq_stat)
|
||||
#define MUTEX_INIT(buff,name) buff->mutex=rt_mutex_create(name,RT_IPC_FLAG_FIFO)
|
||||
#define MUTEX_TAKE(buff) rt_mutex_take(buff->mutex,RT_WAITING_FOREVER)
|
||||
#define MUTEX_RELEASE(buff) rt_mutex_release(buff->mutex);
|
||||
#else
|
||||
#define IRQ_DISABLE() { }
|
||||
#define IRQ_ENABLE() { }
|
||||
#define MUTEX_INIT(buff,name) {}
|
||||
#define MUTEX_TAKE(buff) {}
|
||||
#define MUTEX_RELEASE(buff) {}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static int g_buff_num=0;
|
||||
|
||||
|
||||
int buff_init(data_buff *buff,int size,int use_frame,int frame_start,int frame_end)
|
||||
{
|
||||
int buff_index;
|
||||
char str[20];
|
||||
if(buff==0) return -1;
|
||||
if(buff->buff==0)
|
||||
{
|
||||
IRQ_DISABLE();
|
||||
buff_index=g_buff_num;
|
||||
g_buff_num++;
|
||||
IRQ_ENABLE();
|
||||
buff->buff=malloc(size);
|
||||
if(buff->buff==0) return -1;
|
||||
memset(buff->buff,0,sizeof(size));
|
||||
buff->buff_len= size;
|
||||
buff->use_frame=use_frame;
|
||||
buff->frame_start=frame_start;
|
||||
buff->frame_end=frame_end;
|
||||
sprintf(str,"buff_#%d",buff_index);
|
||||
MUTEX_INIT(buff,str);
|
||||
}
|
||||
buff_clear(buff);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int buff_deinit(data_buff *buff)
|
||||
{
|
||||
if(buff==0) return -1;
|
||||
if(buff->buff)
|
||||
{
|
||||
free(buff->buff);
|
||||
buff->buff=0;
|
||||
buff->buff_len=0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int buff_get_used(data_buff *buff)
|
||||
{
|
||||
int ret=-1;
|
||||
IRQ_DISABLE();
|
||||
ret=buff->buff_used;
|
||||
IRQ_ENABLE();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int buff_save_byte(data_buff *buff,uint8_t data)
|
||||
{
|
||||
if(buff==0) return -1;
|
||||
int ret=-1;
|
||||
IRQ_DISABLE();
|
||||
if((!buff->use_frame)||(data==buff->frame_start)) buff->active=1;
|
||||
if((buff->buff_used<buff->buff_len)&&buff->active)
|
||||
{
|
||||
buff->buff[buff->save_ptr]=data;
|
||||
buff->buff_used++;
|
||||
if((buff->use_frame)&&(data==buff->frame_end)) {
|
||||
buff->frame_num++;
|
||||
buff->active=0;
|
||||
}
|
||||
buff->save_ptr++;
|
||||
if (buff->save_ptr>=buff->buff_len)
|
||||
buff->save_ptr=0;
|
||||
ret= 0;
|
||||
}
|
||||
IRQ_ENABLE();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int buff_save_bytes(data_buff *buff,const uint8_t *data,int len)
|
||||
{
|
||||
if(buff==0) return -1;
|
||||
int ret=-1;
|
||||
MUTEX_TAKE(buff);
|
||||
if (buff->buff_used+len<=buff->buff_len)
|
||||
{
|
||||
while(len--)
|
||||
{
|
||||
ret=buff_save_byte(buff,*data);data++;
|
||||
if(ret!=0) break;
|
||||
}
|
||||
}
|
||||
MUTEX_RELEASE(buff);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int buff_read_byte(data_buff *buff,uint8_t *data)
|
||||
{
|
||||
if(buff==0) return -1;
|
||||
int ret=-1;
|
||||
IRQ_DISABLE();
|
||||
if (((buff->frame_num)&&(buff->buff_used))||((!buff->use_frame)&&(buff->buff_used)))
|
||||
{
|
||||
*data=buff->buff[buff->read_ptr];
|
||||
buff->buff_used--;
|
||||
if((buff->use_frame)&&(*data==buff->frame_end)) buff->frame_num--;
|
||||
buff->read_ptr++;
|
||||
if (buff->read_ptr>=buff->buff_len)
|
||||
buff->read_ptr=0;
|
||||
ret= 0;
|
||||
}
|
||||
IRQ_ENABLE();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int buff_read_bytes(data_buff *buff,uint8_t *data,int len)
|
||||
{
|
||||
if(buff==0) return -1;
|
||||
int ret=-1;
|
||||
MUTEX_TAKE(buff);
|
||||
if (buff->buff_used>=len)
|
||||
{
|
||||
while(len--)
|
||||
{
|
||||
ret=buff_read_byte(buff,data);data++;
|
||||
if(ret!=0) break;
|
||||
}
|
||||
}
|
||||
MUTEX_RELEASE(buff);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int buff_clear(data_buff *buff)
|
||||
{
|
||||
if(buff==0) return -1;
|
||||
IRQ_DISABLE();
|
||||
buff->buff_used=0;
|
||||
buff->read_ptr=0;
|
||||
buff->save_ptr=0;
|
||||
buff->frame_num=0;
|
||||
buff->active=0;
|
||||
IRQ_ENABLE();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
60
source/soft/buff.h
Normal file
60
source/soft/buff.h
Normal file
@@ -0,0 +1,60 @@
|
||||
|
||||
#ifndef BUFF_H__
|
||||
#define BUFF_H__
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int buff_len;
|
||||
int buff_used;
|
||||
int read_ptr;
|
||||
int save_ptr;
|
||||
int use_frame; //使用帧
|
||||
int frame_start; //帧开始
|
||||
int frame_end; //帧结束
|
||||
int frame_num; //完整帧数
|
||||
int active; //在接收到帧开始之后进入活跃状态
|
||||
uint8_t *buff;
|
||||
void *mutex;
|
||||
} data_buff;
|
||||
|
||||
|
||||
// 初始化一个指定长度的缓冲区,返回0成功
|
||||
int buff_init(data_buff *buff,int size,int use_frame,int frame_start,int frame_end);
|
||||
|
||||
// 去初始化一个指定长度的缓冲区,返回0成功
|
||||
int buff_deinit(data_buff *buff);
|
||||
|
||||
// 获取buff的使用量
|
||||
int buff_get_used(data_buff *buff);
|
||||
|
||||
// 保存一个字节数据,返回0,成功
|
||||
int buff_save_byte(data_buff *buff,uint8_t data);
|
||||
|
||||
// 保存多个字节,返回0成功
|
||||
int buff_save_bytes(data_buff *buff,const uint8_t *data,int len);
|
||||
|
||||
// 读取一个字节数据,返回0,成功
|
||||
int buff_read_byte(data_buff *buff,uint8_t *data);
|
||||
|
||||
// 读取多个字节,返回0,成功
|
||||
int buff_read_bytes(data_buff *buff,uint8_t *data,int len);
|
||||
|
||||
|
||||
// 清除缓冲区,返回0,成功
|
||||
int buff_clear(data_buff *buff);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
208
source/soft/bytearray.c
Normal file
208
source/soft/bytearray.c
Normal file
@@ -0,0 +1,208 @@
|
||||
#include "bytearray.h"
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include "stdio.h"
|
||||
#include "board.h"
|
||||
#include "mystdlib.h"
|
||||
#include "debug.h"
|
||||
#include "rtthread.h"
|
||||
|
||||
|
||||
|
||||
#define ARR_MAX_PRINT_LEN 20
|
||||
|
||||
#define ARRAY_APPEND_SKIP 50
|
||||
|
||||
|
||||
|
||||
// 使用时保证不要在不同线程同时修改,可以不用保护以提高速度
|
||||
#define rt_mutex_create(...) 0
|
||||
#define rt_mutex_delete(...)
|
||||
#define rt_mutex_take(...)
|
||||
#define rt_mutex_release(...)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct _array_def{
|
||||
int32_t all;
|
||||
int32_t used;
|
||||
rt_mutex_t mutex;
|
||||
uint8_t data[0];
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
array_def *arr_creat(void)
|
||||
{
|
||||
array_def *a;
|
||||
static uint16_t count=0;
|
||||
char s1[16]={0};
|
||||
sprintf(s1,"arr_mut#%d",count);
|
||||
int size=0;
|
||||
size+=sizeof(array_def);
|
||||
size+=ARRAY_APPEND_SKIP;
|
||||
a=malloc(size);
|
||||
param_check(a);
|
||||
a->all=ARRAY_APPEND_SKIP;
|
||||
a->used=0;
|
||||
a->mutex=rt_mutex_create(s1,RT_IPC_FLAG_FIFO);
|
||||
count++;
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static array_def *arr_expend(array_def *a)
|
||||
{
|
||||
array_def *r;
|
||||
int size=0;
|
||||
int cpysize=0;
|
||||
size+=sizeof(array_def);
|
||||
size+=a->all+ARRAY_APPEND_SKIP;
|
||||
r=malloc(size);
|
||||
param_check(r);
|
||||
cpysize=sizeof(array_def)+a->used;
|
||||
memcpy(r,a,cpysize);
|
||||
r->all+=ARRAY_APPEND_SKIP;
|
||||
free(a);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
array_def *_arr_append(array_def **a,uint8_t d)
|
||||
{
|
||||
param_check(a);
|
||||
param_check(*a);
|
||||
array_def *r=*a;
|
||||
rt_mutex_take(r->mutex,RT_WAITING_FOREVER);
|
||||
if((*a)->used>=(*a)->all)
|
||||
{
|
||||
r=arr_expend(*a);
|
||||
}
|
||||
r->data[r->used]=d;
|
||||
r->used++;
|
||||
rt_mutex_release(r->mutex);
|
||||
*a=r;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
uint8_t arr_get(array_def *a,int index)
|
||||
{
|
||||
uint8_t ret=0;
|
||||
param_check(a);
|
||||
rt_mutex_take(a->mutex,RT_WAITING_FOREVER);
|
||||
if(index<0) index=a->used+index;
|
||||
if((index>=0&&index<a->used)==0) ret=0;
|
||||
else ret=a->data[index];
|
||||
rt_mutex_release(a->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
uint8_t *arr_data(array_def *a)
|
||||
{
|
||||
param_check(a);
|
||||
return a->data;
|
||||
}
|
||||
|
||||
|
||||
int arr_length(array_def *a)
|
||||
{
|
||||
param_check(a);
|
||||
return a->used;
|
||||
}
|
||||
|
||||
|
||||
// 截取数组
|
||||
array_def *arr_mid(array_def *a,int start,int len)
|
||||
{
|
||||
param_check(a);
|
||||
array_def *r;
|
||||
r=arr_creat();
|
||||
if(start<0) start=a->used+start;
|
||||
if((start>=0&&start<a->used)==0)
|
||||
{
|
||||
return r;
|
||||
}
|
||||
if(start+len>a->used)
|
||||
{
|
||||
len=a->used-start;
|
||||
}
|
||||
for(int i=0;i<len;i++)
|
||||
{
|
||||
//_arr_append(&r,arr_get(a,i+start));
|
||||
_arr_append(&r,a->data[i+start]);
|
||||
}
|
||||
//return tappend(r,0);
|
||||
return r;
|
||||
}
|
||||
|
||||
// 移除一些数据,返回实际移除的数据长度
|
||||
int arr_remove(array_def *a,int start,int len)
|
||||
{
|
||||
param_check(a);
|
||||
if(start<0) start=a->used+start;
|
||||
if((start>=0&&start<a->used)==0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if(start+len>a->used)
|
||||
{
|
||||
len=a->used-start;
|
||||
}
|
||||
int move_len=a->used-(start+len);
|
||||
memcpy(&a->data[start],&a->data[start+len],move_len);
|
||||
a->used-=len;
|
||||
return len;
|
||||
}
|
||||
|
||||
// 输出打印字符串
|
||||
char *arr_string(array_def *a)
|
||||
{
|
||||
param_check(a);
|
||||
array_def *d=arr_creat();
|
||||
param_check(d);
|
||||
// DBG_LOG("d=%08x,a=%08x",d,a);
|
||||
// DBG_LOG("%s:length(a)==%d.",__func__,arr_length(a));
|
||||
int len=0;
|
||||
char s[20];
|
||||
int index=0;
|
||||
arr_append(d,'[');
|
||||
for(int i=0;i<arr_length(a);i++)
|
||||
{
|
||||
sprintf(s,"%02x",arr_get(a,i));
|
||||
// sprintf(s,"%02x",(uint8_t)i);
|
||||
len=strlen(s);
|
||||
arr_appends(d,s,len);
|
||||
arr_append(d,',');
|
||||
index++;
|
||||
if(index>=ARR_MAX_PRINT_LEN){
|
||||
// 超过20字节的 只打印前20字节
|
||||
sprintf(s,"...(%d)",arr_length(a));
|
||||
len=strlen(s);
|
||||
arr_appends(d,s,len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
arr_append(d,']');
|
||||
len=arr_length(d);
|
||||
char *ptr=malloc(len+1);
|
||||
param_check(ptr);
|
||||
memcpy(ptr,arr_data(d),len);
|
||||
arr_delete(d);
|
||||
ptr[len]=0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
46
source/soft/bytearray.h
Normal file
46
source/soft/bytearray.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef bytearray_h__
|
||||
#define bytearray_h__
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
struct _array_def;
|
||||
typedef struct _array_def array_def;
|
||||
|
||||
|
||||
|
||||
array_def *arr_creat(void);
|
||||
uint8_t arr_get(array_def *a,int index);
|
||||
array_def *arr_mid(array_def *a,int start,int len);
|
||||
uint8_t *arr_data(array_def *a);
|
||||
int arr_length(array_def *a);
|
||||
int arr_remove(array_def *a,int start,int len);
|
||||
char *arr_string(array_def *a);
|
||||
|
||||
|
||||
#define arr_delete(a) {free(a);a=0;}
|
||||
#define arr_append(a,d) _arr_append(&a,d)
|
||||
#define arr_appends(a,d,len) for(int i=0;i<len;i++){_arr_append(&a,((uint8_t *)d)[i]);}
|
||||
#define arr_appends_from(a,b) {\
|
||||
uint8_t *d=arr_data(b);\
|
||||
arr_appends(a,d,arr_length(b));}
|
||||
#define arr_append_num(a,num,d) for(int i=0;i<num;i++){_arr_append(&a,d);}
|
||||
#define arr_clear(a) arr_remove(a,0,arr_length(a))
|
||||
#define arr_duplicate(a) arr_mid(a,0,arr_length(a))
|
||||
|
||||
// 转化为临时指针
|
||||
#define arr_temp(a) tappend(a,0)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
array_def *_arr_append(array_def **a,uint8_t d);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
641
source/soft/cJSON.c
Normal file
641
source/soft/cJSON.c
Normal file
@@ -0,0 +1,641 @@
|
||||
/*
|
||||
Copyright (c) 2009 Dave Gamble
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* cJSON */
|
||||
/* JSON parser in C. */
|
||||
|
||||
|
||||
//#define MY_NUMTOSTR //使用自己的数字转字符串函数,以防使用sprintf导致的浮点数输出始终为0的情况
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <float.h>
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
#include "cJSON.h"
|
||||
|
||||
|
||||
static const char *ep;
|
||||
|
||||
const char *cJSON_GetErrorPtr(void) {return ep;}
|
||||
|
||||
static int cJSON_strcasecmp(const char *s1,const char *s2)
|
||||
{
|
||||
if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
|
||||
for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0;
|
||||
return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
|
||||
}
|
||||
|
||||
static void *(*cJSON_malloc)(size_t sz) = malloc;
|
||||
static void (*cJSON_free)(void *ptr) = free;
|
||||
|
||||
static char* cJSON_strdup(const char* str)
|
||||
{
|
||||
size_t len;
|
||||
char* copy;
|
||||
|
||||
len = strlen(str) + 1;
|
||||
if ((copy = (char*)cJSON_malloc(len)),copy==0) return 0;
|
||||
memcpy(copy,(void *)str,len);
|
||||
return copy;
|
||||
}
|
||||
|
||||
void cJSON_InitHooks(cJSON_Hooks* hooks)
|
||||
{
|
||||
if (!hooks) { /* Reset hooks */
|
||||
cJSON_malloc = malloc;
|
||||
cJSON_free = free;
|
||||
return;
|
||||
}
|
||||
|
||||
cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
|
||||
cJSON_free = (hooks->free_fn)?hooks->free_fn:free;
|
||||
}
|
||||
|
||||
/* Internal constructor. */
|
||||
static cJSON *cJSON_New_Item(void)
|
||||
{
|
||||
cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
|
||||
if (node) memset(node,0,sizeof(cJSON));
|
||||
return node;
|
||||
}
|
||||
|
||||
/* Delete a cJSON structure. */
|
||||
void cJSON_Delete(cJSON *c)
|
||||
{
|
||||
cJSON *next;
|
||||
while (c)
|
||||
{
|
||||
next=c->next;
|
||||
if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);
|
||||
if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
|
||||
if (c->string) cJSON_free(c->string);
|
||||
cJSON_free(c);
|
||||
c=next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse the input text to generate a number, and populate the result into item. */
|
||||
static const char *parse_number(cJSON *item,const char *num)
|
||||
{
|
||||
double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;
|
||||
|
||||
if (*num=='-') sign=-1,num++; /* Has sign? */
|
||||
if (*num=='0') num++; /* is zero */
|
||||
if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */
|
||||
if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */
|
||||
if (*num=='e' || *num=='E') /* Exponent? */
|
||||
{ num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */
|
||||
while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */
|
||||
}
|
||||
|
||||
n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */
|
||||
|
||||
item->valuedouble=n;
|
||||
item->valueint=(int)n;
|
||||
item->type=cJSON_Number;
|
||||
return num;
|
||||
}
|
||||
|
||||
#ifdef MY_NUMTOSTR
|
||||
|
||||
//把数字转换成字符串
|
||||
void num_to_str (u8 *str,u8 num1,u8 num2)
|
||||
{
|
||||
if (num1>9)
|
||||
{
|
||||
*str++=num1/10+'0';
|
||||
*str++=num1%10+'0';
|
||||
}
|
||||
else
|
||||
{
|
||||
*str++=num1+'0';
|
||||
}
|
||||
*str++='.';
|
||||
if (num2<10)
|
||||
{
|
||||
*str++=num2+'0';
|
||||
}
|
||||
else
|
||||
{
|
||||
*str++=num2/10+'0';
|
||||
*str++=num2%10+'0';
|
||||
}
|
||||
*str=0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Render the number nicely from the given item into a string. */
|
||||
static char *print_number(cJSON *item)
|
||||
{
|
||||
char *str;
|
||||
double d=item->valuedouble;
|
||||
if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
|
||||
{
|
||||
str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */
|
||||
if (str) sprintf(str,"%d",item->valueint);
|
||||
}
|
||||
else
|
||||
{
|
||||
str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */
|
||||
if (str)
|
||||
{
|
||||
if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d);
|
||||
else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d);
|
||||
else
|
||||
{
|
||||
#ifndef MY_NUMTOSTR
|
||||
sprintf(str,"%f",d);
|
||||
#else
|
||||
num_to_str((u8*)str,(u8)d,(u8)((d-(u8)d)*10));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
static unsigned parse_hex4(const char *str)
|
||||
{
|
||||
unsigned h=0;
|
||||
if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
|
||||
h=h<<4;str++;
|
||||
if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
|
||||
h=h<<4;str++;
|
||||
if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
|
||||
h=h<<4;str++;
|
||||
if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
|
||||
return h;
|
||||
}
|
||||
|
||||
/* Parse the input text into an unescaped cstring, and populate item. */
|
||||
static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
|
||||
static const char *parse_string(cJSON *item,const char *str)
|
||||
{
|
||||
const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
|
||||
if (*str!='\"') {ep=str;return 0;} /* not a string! */
|
||||
|
||||
while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */
|
||||
|
||||
out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */
|
||||
if (!out) return 0;
|
||||
|
||||
ptr=str+1;ptr2=out;
|
||||
while (*ptr!='\"' && *ptr)
|
||||
{
|
||||
if (*ptr!='\\') *ptr2++=*ptr++;
|
||||
else
|
||||
{
|
||||
ptr++;
|
||||
switch (*ptr)
|
||||
{
|
||||
case 'b': *ptr2++='\b'; break;
|
||||
case 'f': *ptr2++='\f'; break;
|
||||
case 'n': *ptr2++='\n'; break;
|
||||
case 'r': *ptr2++='\r'; break;
|
||||
case 't': *ptr2++='\t'; break;
|
||||
case 'u': /* transcode utf16 to utf8. */
|
||||
uc=parse_hex4(ptr+1);ptr+=4; /* get the unicode char. */
|
||||
|
||||
if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; /* check for invalid. */
|
||||
|
||||
if (uc>=0xD800 && uc<=0xDBFF) /* UTF16 surrogate pairs. */
|
||||
{
|
||||
if (ptr[1]!='\\' || ptr[2]!='u') break; /* missing second-half of surrogate. */
|
||||
uc2=parse_hex4(ptr+3);ptr+=6;
|
||||
if (uc2<0xDC00 || uc2>0xDFFF) break; /* invalid second-half of surrogate. */
|
||||
uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
|
||||
}
|
||||
|
||||
len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;
|
||||
|
||||
switch (len) {
|
||||
case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
|
||||
case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
|
||||
case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
|
||||
case 1: *--ptr2 =(uc | firstByteMark[len]);
|
||||
}
|
||||
ptr2+=len;
|
||||
break;
|
||||
default: *ptr2++=*ptr; break;
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
*ptr2=0;
|
||||
if (*ptr=='\"') ptr++;
|
||||
item->valuestring=out;
|
||||
item->type=cJSON_String;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* Render the cstring provided to an escaped version that can be printed. */
|
||||
static char *print_string_ptr(const char *str)
|
||||
{
|
||||
const char *ptr;char *ptr2,*out;int len=0;unsigned char token;
|
||||
|
||||
if (!str) return cJSON_strdup("");
|
||||
ptr=str;while ((token=*ptr),token && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
|
||||
|
||||
out=(char*)cJSON_malloc(len+3);
|
||||
if (!out) return 0;
|
||||
|
||||
ptr2=out;ptr=str;
|
||||
*ptr2++='\"';
|
||||
while (*ptr)
|
||||
{
|
||||
if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
|
||||
else
|
||||
{
|
||||
*ptr2++='\\';
|
||||
switch (token=*ptr++)
|
||||
{
|
||||
case '\\': *ptr2++='\\'; break;
|
||||
case '\"': *ptr2++='\"'; break;
|
||||
case '\b': *ptr2++='b'; break;
|
||||
case '\f': *ptr2++='f'; break;
|
||||
case '\n': *ptr2++='n'; break;
|
||||
case '\r': *ptr2++='r'; break;
|
||||
case '\t': *ptr2++='t'; break;
|
||||
default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */
|
||||
}
|
||||
}
|
||||
}
|
||||
*ptr2++='\"';*ptr2++=0;
|
||||
return out;
|
||||
}
|
||||
/* Invote print_string_ptr (which is useful) on an item. */
|
||||
static char *print_string(cJSON *item) {return print_string_ptr(item->valuestring);}
|
||||
|
||||
/* Predeclare these prototypes. */
|
||||
static const char *parse_value(cJSON *item,const char *value);
|
||||
static char *print_value(cJSON *item,int depth,int fmt);
|
||||
static const char *parse_array(cJSON *item,const char *value);
|
||||
static char *print_array(cJSON *item,int depth,int fmt);
|
||||
static const char *parse_object(cJSON *item,const char *value);
|
||||
static char *print_object(cJSON *item,int depth,int fmt);
|
||||
|
||||
/* Utility to jump whitespace and cr/lf */
|
||||
static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;}
|
||||
|
||||
/* Parse an object - create a new root, and populate. */
|
||||
cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated)
|
||||
{
|
||||
const char *end=0;
|
||||
cJSON *c=cJSON_New_Item();
|
||||
ep=0;
|
||||
if (!c) return 0; /* memory fail */
|
||||
|
||||
end=parse_value(c,skip(value));
|
||||
if (!end) {cJSON_Delete(c);return 0;} /* parse failure. ep is set. */
|
||||
|
||||
/* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
|
||||
if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}}
|
||||
if (return_parse_end) *return_parse_end=end;
|
||||
return c;
|
||||
}
|
||||
/* Default options for cJSON_Parse */
|
||||
cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);}
|
||||
|
||||
/* Render a cJSON item/entity/structure to text. */
|
||||
char *cJSON_Print(cJSON *item) {return print_value(item,0,1);}
|
||||
char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0);}
|
||||
|
||||
/* Parser core - when encountering text, process appropriately. */
|
||||
static const char *parse_value(cJSON *item,const char *value)
|
||||
{
|
||||
if (!value) return 0; /* Fail on null. */
|
||||
if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; }
|
||||
if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; }
|
||||
if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; }
|
||||
if (*value=='\"') { return parse_string(item,value); }
|
||||
if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); }
|
||||
if (*value=='[') { return parse_array(item,value); }
|
||||
if (*value=='{') { return parse_object(item,value); }
|
||||
|
||||
ep=value;return 0; /* failure. */
|
||||
}
|
||||
|
||||
/* Render a value to text. */
|
||||
static char *print_value(cJSON *item,int depth,int fmt)
|
||||
{
|
||||
char *out=0;
|
||||
if (!item) return 0;
|
||||
switch ((item->type)&255)
|
||||
{
|
||||
case cJSON_NULL: out=cJSON_strdup("null"); break;
|
||||
case cJSON_False: out=cJSON_strdup("false");break;
|
||||
case cJSON_True: out=cJSON_strdup("true"); break;
|
||||
case cJSON_Number: out=print_number(item);break;
|
||||
case cJSON_String: out=print_string(item);break;
|
||||
case cJSON_Array: out=print_array(item,depth,fmt);break;
|
||||
case cJSON_Object: out=print_object(item,depth,fmt);break;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/* Build an array from input text. */
|
||||
static const char *parse_array(cJSON *item,const char *value)
|
||||
{
|
||||
cJSON *child;
|
||||
if (*value!='[') {ep=value;return 0;} /* not an array! */
|
||||
|
||||
item->type=cJSON_Array;
|
||||
value=skip(value+1);
|
||||
if (*value==']') return value+1; /* empty array. */
|
||||
|
||||
item->child=child=cJSON_New_Item();
|
||||
if (!item->child) return 0; /* memory fail */
|
||||
value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */
|
||||
if (!value) return 0;
|
||||
|
||||
while (*value==',')
|
||||
{
|
||||
cJSON *new_item;
|
||||
if ((new_item=cJSON_New_Item()),new_item==0) return 0; /* memory fail */
|
||||
child->next=new_item;new_item->prev=child;child=new_item;
|
||||
value=skip(parse_value(child,skip(value+1)));
|
||||
if (!value) return 0; /* memory fail */
|
||||
}
|
||||
|
||||
if (*value==']') return value+1; /* end of array */
|
||||
ep=value;return 0; /* malformed. */
|
||||
}
|
||||
|
||||
/* Render an array to text */
|
||||
static char *print_array(cJSON *item,int depth,int fmt)
|
||||
{
|
||||
char **entries;
|
||||
char *out=0,*ptr,*ret;int len=5;
|
||||
cJSON *child=item->child;
|
||||
int numentries=0,i=0,fail=0;
|
||||
|
||||
/* How many entries in the array? */
|
||||
while (child) numentries++,child=child->next;
|
||||
/* Explicitly handle numentries==0 */
|
||||
if (!numentries)
|
||||
{
|
||||
out=(char*)cJSON_malloc(3);
|
||||
if (out) strcpy(out,"[]");
|
||||
return out;
|
||||
}
|
||||
/* Allocate an array to hold the values for each */
|
||||
entries=(char**)cJSON_malloc(numentries*sizeof(char*));
|
||||
if (!entries) return 0;
|
||||
memset(entries,0,numentries*sizeof(char*));
|
||||
/* Retrieve all the results: */
|
||||
child=item->child;
|
||||
while (child && !fail)
|
||||
{
|
||||
ret=print_value(child,depth+1,fmt);
|
||||
entries[i++]=ret;
|
||||
if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
|
||||
child=child->next;
|
||||
}
|
||||
|
||||
/* If we didn't fail, try to malloc the output string */
|
||||
if (!fail) out=(char*)cJSON_malloc(len);
|
||||
/* If that fails, we fail. */
|
||||
if (!out) fail=1;
|
||||
|
||||
/* Handle failure. */
|
||||
if (fail)
|
||||
{
|
||||
for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
|
||||
cJSON_free(entries);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compose the output array. */
|
||||
*out='[';
|
||||
ptr=out+1;*ptr=0;
|
||||
for (i=0;i<numentries;i++)
|
||||
{
|
||||
strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
|
||||
if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
|
||||
cJSON_free(entries[i]);
|
||||
}
|
||||
cJSON_free(entries);
|
||||
*ptr++=']';*ptr++=0;
|
||||
return out;
|
||||
}
|
||||
|
||||
/* Build an object from the text. */
|
||||
static const char *parse_object(cJSON *item,const char *value)
|
||||
{
|
||||
cJSON *child;
|
||||
if (*value!='{') {ep=value;return 0;} /* not an object! */
|
||||
|
||||
item->type=cJSON_Object;
|
||||
value=skip(value+1);
|
||||
if (*value=='}') return value+1; /* empty array. */
|
||||
|
||||
item->child=child=cJSON_New_Item();
|
||||
if (!item->child) return 0;
|
||||
value=skip(parse_string(child,skip(value)));
|
||||
if (!value) return 0;
|
||||
child->string=child->valuestring;child->valuestring=0;
|
||||
if (*value!=':') {ep=value;return 0;} /* fail! */
|
||||
value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
|
||||
if (!value) return 0;
|
||||
|
||||
while (*value==',')
|
||||
{
|
||||
cJSON *new_item;
|
||||
if ((new_item=cJSON_New_Item()),new_item==0) return 0; /* memory fail */
|
||||
child->next=new_item;new_item->prev=child;child=new_item;
|
||||
value=skip(parse_string(child,skip(value+1)));
|
||||
if (!value) return 0;
|
||||
child->string=child->valuestring;child->valuestring=0;
|
||||
if (*value!=':') {ep=value;return 0;} /* fail! */
|
||||
value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
|
||||
if (!value) return 0;
|
||||
}
|
||||
|
||||
if (*value=='}') return value+1; /* end of array */
|
||||
ep=value;return 0; /* malformed. */
|
||||
}
|
||||
|
||||
/* Render an object to text. */
|
||||
static char *print_object(cJSON *item,int depth,int fmt)
|
||||
{
|
||||
char **entries=0,**names=0;
|
||||
char *out=0,*ptr,*ret,*str;int len=7,i=0,j;
|
||||
cJSON *child=item->child;
|
||||
int numentries=0,fail=0;
|
||||
/* Count the number of entries. */
|
||||
while (child) numentries++,child=child->next;
|
||||
/* Explicitly handle empty object case */
|
||||
if (!numentries)
|
||||
{
|
||||
out=(char*)cJSON_malloc(fmt?depth+4:3);
|
||||
if (!out) return 0;
|
||||
ptr=out;*ptr++='{';
|
||||
if (fmt) {*ptr++='\n';for (i=0;i<depth-1;i++) *ptr++='\t';}
|
||||
*ptr++='}';*ptr++=0;
|
||||
return out;
|
||||
}
|
||||
/* Allocate space for the names and the objects */
|
||||
entries=(char**)cJSON_malloc(numentries*sizeof(char*));
|
||||
if (!entries) return 0;
|
||||
names=(char**)cJSON_malloc(numentries*sizeof(char*));
|
||||
if (!names) {cJSON_free(entries);return 0;}
|
||||
memset(entries,0,sizeof(char*)*numentries);
|
||||
memset(names,0,sizeof(char*)*numentries);
|
||||
|
||||
/* Collect all the results into our arrays: */
|
||||
child=item->child;depth++;if (fmt) len+=depth;
|
||||
while (child)
|
||||
{
|
||||
names[i]=str=print_string_ptr(child->string);
|
||||
entries[i++]=ret=print_value(child,depth,fmt);
|
||||
if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
|
||||
child=child->next;
|
||||
}
|
||||
|
||||
/* Try to allocate the output string */
|
||||
if (!fail) out=(char*)cJSON_malloc(len);
|
||||
if (!out) fail=1;
|
||||
|
||||
/* Handle failure */
|
||||
if (fail)
|
||||
{
|
||||
for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
|
||||
cJSON_free(names);cJSON_free(entries);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compose the output: */
|
||||
*out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
|
||||
for (i=0;i<numentries;i++)
|
||||
{
|
||||
if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
|
||||
strcpy(ptr,names[i]);ptr+=strlen(names[i]);
|
||||
*ptr++=':';if (fmt) *ptr++='\t';
|
||||
strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
|
||||
if (i!=numentries-1) *ptr++=',';
|
||||
if (fmt) *ptr++='\n';*ptr=0;
|
||||
cJSON_free(names[i]);cJSON_free(entries[i]);
|
||||
}
|
||||
|
||||
cJSON_free(names);cJSON_free(entries);
|
||||
if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
|
||||
*ptr++='}';*ptr++=0;
|
||||
return out;
|
||||
}
|
||||
|
||||
/* Get Array size/item / object item. */
|
||||
int cJSON_GetArraySize(cJSON *array) {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
|
||||
cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;}
|
||||
cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
|
||||
|
||||
/* Utility for array list handling. */
|
||||
static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
|
||||
/* Utility for handling references. */
|
||||
static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;}
|
||||
|
||||
/* Add item to array/object. */
|
||||
void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}}
|
||||
void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);}
|
||||
void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));}
|
||||
void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));}
|
||||
|
||||
cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
|
||||
if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;}
|
||||
void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));}
|
||||
cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;}
|
||||
void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}
|
||||
|
||||
/* Replace array/object items with new ones. */
|
||||
void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return;
|
||||
newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;
|
||||
if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}
|
||||
void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}}
|
||||
|
||||
/* Create basic types: */
|
||||
cJSON *cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
|
||||
cJSON *cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}
|
||||
cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;}
|
||||
cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}
|
||||
cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;}
|
||||
cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;}
|
||||
cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}
|
||||
cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}
|
||||
|
||||
/* Create Arrays: */
|
||||
cJSON *cJSON_CreateIntArray(const int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
|
||||
cJSON *cJSON_CreateFloatArray(const float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
|
||||
cJSON *cJSON_CreateDoubleArray(const double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
|
||||
cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
|
||||
|
||||
/* Duplication */
|
||||
cJSON *cJSON_Duplicate(cJSON *item,int recurse)
|
||||
{
|
||||
cJSON *newitem,*cptr,*nptr=0,*newchild;
|
||||
/* Bail on bad ptr */
|
||||
if (!item) return 0;
|
||||
/* Create new item */
|
||||
newitem=cJSON_New_Item();
|
||||
if (!newitem) return 0;
|
||||
/* Copy over all vars */
|
||||
newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble;
|
||||
if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}}
|
||||
if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}}
|
||||
/* If non-recursive, then we're done! */
|
||||
if (!recurse) return newitem;
|
||||
/* Walk the ->next chain for the child. */
|
||||
cptr=item->child;
|
||||
while (cptr)
|
||||
{
|
||||
newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */
|
||||
if (!newchild) {cJSON_Delete(newitem);return 0;}
|
||||
if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */
|
||||
else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */
|
||||
cptr=cptr->next;
|
||||
}
|
||||
return newitem;
|
||||
}
|
||||
|
||||
void cJSON_Minify(char *json)
|
||||
{
|
||||
char *into=json;
|
||||
while (*json)
|
||||
{
|
||||
if (*json==' ') json++;
|
||||
else if (*json=='\t') json++; // Whitespace characters.
|
||||
else if (*json=='\r') json++;
|
||||
else if (*json=='\n') json++;
|
||||
else if (*json=='/' && json[1]=='/') while (*json && *json!='\n') json++; // double-slash comments, to end of line.
|
||||
else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;} // multiline comments.
|
||||
else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} // string literals, which are \" sensitive.
|
||||
else *into++=*json++; // All other characters.
|
||||
}
|
||||
*into=0; // and null-terminate.
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
146
source/soft/cJSON.h
Normal file
146
source/soft/cJSON.h
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
Copyright (c) 2009 Dave Gamble
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef cJSON__h
|
||||
#define cJSON__h
|
||||
|
||||
#include <stddef.h>
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* cJSON Types: */
|
||||
#define cJSON_False 0
|
||||
#define cJSON_True 1
|
||||
#define cJSON_NULL 2
|
||||
#define cJSON_Number 3
|
||||
#define cJSON_String 4
|
||||
#define cJSON_Array 5
|
||||
#define cJSON_Object 6
|
||||
|
||||
#define cJSON_IsReference 256
|
||||
|
||||
/* The cJSON structure: */
|
||||
typedef struct cJSON {
|
||||
struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
|
||||
struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
|
||||
|
||||
int type; /* The type of the item, as above. */
|
||||
|
||||
char *valuestring; /* The item's string, if type==cJSON_String */
|
||||
int valueint; /* The item's number, if type==cJSON_Number */
|
||||
double valuedouble; /* The item's number, if type==cJSON_Number */
|
||||
|
||||
char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
|
||||
} cJSON;
|
||||
|
||||
|
||||
|
||||
typedef struct cJSON_Hooks {
|
||||
void *(*malloc_fn)(size_t sz);
|
||||
void (*free_fn)(void *ptr);
|
||||
} cJSON_Hooks;
|
||||
|
||||
/* Supply malloc, realloc and free functions to cJSON */
|
||||
extern void cJSON_InitHooks(cJSON_Hooks* hooks);
|
||||
|
||||
|
||||
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
|
||||
extern cJSON *cJSON_Parse(const char *value);
|
||||
/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
|
||||
extern char *cJSON_Print(cJSON *item);
|
||||
/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
|
||||
extern char *cJSON_PrintUnformatted(cJSON *item);
|
||||
/* Delete a cJSON entity and all subentities. */
|
||||
extern void cJSON_Delete(cJSON *c);
|
||||
|
||||
/* Returns the number of items in an array (or object). */
|
||||
extern int cJSON_GetArraySize(cJSON *array);
|
||||
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
|
||||
extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);
|
||||
/* Get item "string" from object. Case insensitive. */
|
||||
extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
|
||||
|
||||
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
|
||||
extern const char *cJSON_GetErrorPtr(void);
|
||||
|
||||
/* These calls create a cJSON item of the appropriate type. */
|
||||
extern cJSON *cJSON_CreateNull(void);
|
||||
extern cJSON *cJSON_CreateTrue(void);
|
||||
extern cJSON *cJSON_CreateFalse(void);
|
||||
extern cJSON *cJSON_CreateBool(int b);
|
||||
extern cJSON *cJSON_CreateNumber(double num);
|
||||
extern cJSON *cJSON_CreateString(const char *string);
|
||||
extern cJSON *cJSON_CreateArray(void);
|
||||
extern cJSON *cJSON_CreateObject(void);
|
||||
|
||||
/* These utilities create an Array of count items. */
|
||||
extern cJSON *cJSON_CreateIntArray(const int *numbers,int count);
|
||||
extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count);
|
||||
extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count);
|
||||
extern cJSON *cJSON_CreateStringArray(const char **strings,int count);
|
||||
|
||||
/* Append item to the specified array/object. */
|
||||
extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
|
||||
extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
|
||||
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
|
||||
extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
|
||||
extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);
|
||||
|
||||
/* Remove/Detatch items from Arrays/Objects. */
|
||||
extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);
|
||||
extern void cJSON_DeleteItemFromArray(cJSON *array,int which);
|
||||
extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
|
||||
extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string);
|
||||
|
||||
/* Update array items. */
|
||||
extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
|
||||
extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
|
||||
|
||||
/* Duplicate a cJSON item */
|
||||
extern cJSON *cJSON_Duplicate(cJSON *item,int recurse);
|
||||
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
|
||||
need to be released. With recurse!=0, it will duplicate any children connected to the item.
|
||||
The item->next and ->prev pointers are always zero on return from Duplicate. */
|
||||
|
||||
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
|
||||
extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated);
|
||||
|
||||
extern void cJSON_Minify(char *json);
|
||||
|
||||
/* Macros for creating things quickly. */
|
||||
#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull())
|
||||
#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
|
||||
#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
|
||||
#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
|
||||
#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
|
||||
#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
|
||||
|
||||
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
|
||||
#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
109
source/soft/crc.c
Normal file
109
source/soft/crc.c
Normal file
@@ -0,0 +1,109 @@
|
||||
#include "crc.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
uint8_t crc_crc8(const uint8_t *data,int num)
|
||||
{
|
||||
uint8_t crc = 0;
|
||||
uint16_t j,i;
|
||||
for (j = 0; j < num; j++)
|
||||
{
|
||||
crc ^= *(data+j);
|
||||
for ( i = 0; i < 8; i++)
|
||||
{
|
||||
if ((crc & 0x01) != 0)
|
||||
{
|
||||
crc >>= 1;
|
||||
crc ^= 0x8c;
|
||||
}
|
||||
else
|
||||
{
|
||||
crc >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void crc_crc16(const uint8_t *data, int len,uint8_t *lb,uint8_t *hb)
|
||||
{
|
||||
if (len > 0)
|
||||
{
|
||||
uint16_t crc = 0xFFFF;
|
||||
int i = 0;
|
||||
for (; i < len; i++)
|
||||
{
|
||||
crc = (uint16_t)(crc ^ (data[i]));
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
crc = (crc & 1) != 0 ? (uint16_t)((crc >> 1) ^ 0xA001) : (uint16_t)(crc >> 1);
|
||||
}
|
||||
}
|
||||
uint8_t hi = (uint8_t)((crc & 0xFF00) >> 8); //高位置
|
||||
uint8_t lo = (uint8_t)(crc & 0x00FF); //低位置
|
||||
*lb=lo;*hb=hi;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint32_t crc_crc32(const uint8_t *data,int size)
|
||||
{
|
||||
uint32_t temp,crc=0xffffffff;
|
||||
int i=0,j=0;
|
||||
if((size%4)!=0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
while(i<size)
|
||||
{
|
||||
temp=data[i]|(data[i+1]<<8)|(data[i+2]<<16)|(data[i+3]<<24);
|
||||
i+=4;
|
||||
for(j=0;j<32;j++)
|
||||
{
|
||||
if((crc^temp)&0x80000000)
|
||||
crc=0x04c11db7^(crc<<1);
|
||||
else
|
||||
crc<<=1;
|
||||
temp<<=1;
|
||||
}
|
||||
crc&=0xffffffff;
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void crc_sumcheck(const uint8_t *data,int size,uint8_t *chka,uint8_t *chkb)
|
||||
{
|
||||
if(chka==0) return;
|
||||
if(chkb==0) return;
|
||||
*chka=0;
|
||||
*chkb=0;
|
||||
for(int i=0;i<size;i++)
|
||||
{
|
||||
*chka+=data[i];
|
||||
*chkb+=*chka;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
29
source/soft/crc.h
Normal file
29
source/soft/crc.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef crc_h__
|
||||
#define crc_h__
|
||||
|
||||
#include "stdint.h"
|
||||
#include "bytearray.h"
|
||||
|
||||
|
||||
|
||||
|
||||
uint8_t crc_crc8(const uint8_t *data,int num);
|
||||
|
||||
void crc_crc16(const uint8_t *data, int len,uint8_t *lb,uint8_t *hb);
|
||||
|
||||
uint32_t crc_crc32(const uint8_t *data,int size);
|
||||
|
||||
void crc_sumcheck(const uint8_t *data,int size,uint8_t *chka,uint8_t *chkb);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
80
source/soft/debug.c
Normal file
80
source/soft/debug.c
Normal file
@@ -0,0 +1,80 @@
|
||||
|
||||
|
||||
#include "if_rtt.h"
|
||||
//#include "log.h"
|
||||
#include "stdio.h"
|
||||
#include "stdarg.h"
|
||||
#include "debug.h"
|
||||
#include "string.h"
|
||||
#ifdef RT_THREAD
|
||||
#include "rtthread.h"
|
||||
#define DBG_DEV rtt()
|
||||
#else
|
||||
#define DBG_DEV rtt()
|
||||
#endif
|
||||
|
||||
|
||||
#define CONSOLEBUF_SIZE 1024
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct{
|
||||
int inited;
|
||||
#ifdef RT_THREAD
|
||||
struct rt_mutex mutex;
|
||||
#endif
|
||||
}self_def;
|
||||
|
||||
static self_def g_data;
|
||||
|
||||
int debug_init(void)
|
||||
{
|
||||
if(g_data.inited==0)
|
||||
{
|
||||
#ifdef RT_THREAD
|
||||
rt_mutex_init(&g_data.mutex,"debug_mutex",RT_IPC_FLAG_FIFO);
|
||||
#endif
|
||||
DBG_DEV->init();
|
||||
DBG_DEV->write((const uint8_t *)"\r\n",2);
|
||||
g_data.inited=1;
|
||||
DBG_LOG("debug inited.\r\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void debug_log(const char *file,const char *fun,int line,int level,const char *fmt, ...)
|
||||
{
|
||||
if(g_data.inited==0) return;
|
||||
va_list args;
|
||||
size_t length;
|
||||
static char log_buf[CONSOLEBUF_SIZE];
|
||||
static const char *level_str[]={"[info] ","[log] ","[warn] ","[err] "};
|
||||
static int level_str_len[]={7,6,7,6};
|
||||
if(level<DBG_LEVEL_INFO||level>DBG_LEVEL_ERR) return;
|
||||
#ifdef RT_THREAD
|
||||
rt_mutex_take(&g_data.mutex,RT_WAITING_FOREVER);
|
||||
#endif
|
||||
memcpy(log_buf,level_str[level],level_str_len[level]);
|
||||
length=level_str_len[level];
|
||||
length+=sprintf(log_buf + length,"%s|%s|%d| ",file,fun,line);
|
||||
|
||||
va_start(args, fmt);
|
||||
length += vsnprintf(log_buf + length, sizeof(log_buf) - length - 1, fmt, args);
|
||||
if (length > CONSOLEBUF_SIZE - 1)
|
||||
length = CONSOLEBUF_SIZE - 1;
|
||||
va_end(args);
|
||||
memcpy(&log_buf[length],"\r\n",2);
|
||||
length+=2;
|
||||
DBG_DEV->write((const uint8_t *)log_buf,length);
|
||||
#ifdef RT_THREAD
|
||||
rt_mutex_release(&g_data.mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
57
source/soft/debug.h
Normal file
57
source/soft/debug.h
Normal file
@@ -0,0 +1,57 @@
|
||||
|
||||
|
||||
|
||||
|
||||
#include "stdint.h"
|
||||
#include "stdio.h"
|
||||
|
||||
|
||||
|
||||
|
||||
/*r{ 修改日志打印等级 }c*/
|
||||
#define DBG_LOG_LEVEL DBG_LEVEL_INFO
|
||||
|
||||
|
||||
|
||||
/*r{ 定义打印数据等级 }c*/
|
||||
#define DBG_LEVEL_INFO 0
|
||||
#define DBG_LEVEL_LOG 1
|
||||
#define DBG_LEVEL_WARN 2
|
||||
#define DBG_LEVEL_ERR 3
|
||||
|
||||
|
||||
#if (DBG_LOG_LEVEL<=DBG_LEVEL_INFO)
|
||||
#define DBG_INFO( ml_msg_, ...) \
|
||||
DBG_LOG_(DBG_LEVEL_INFO, (ml_msg_), ##__VA_ARGS__)
|
||||
#else
|
||||
#define DBG_INFO( ml_msg_, ...)
|
||||
#endif
|
||||
#if (DBG_LOG_LEVEL<=DBG_LEVEL_LOG)
|
||||
#define DBG_LOG( ml_msg_, ...) \
|
||||
DBG_LOG_(DBG_LEVEL_LOG, (ml_msg_), ##__VA_ARGS__)
|
||||
#else
|
||||
#define DBG_LOG( ml_msg_, ...)
|
||||
#endif
|
||||
#if (DBG_LOG_LEVEL<=DBG_LEVEL_WARN)
|
||||
#define DBG_WARN( ml_msg_, ...) \
|
||||
DBG_LOG_(DBG_LEVEL_WARN, (ml_msg_), ##__VA_ARGS__)
|
||||
#else
|
||||
#define DBG_WARN( ml_msg_, ...)
|
||||
#endif
|
||||
#if (DBG_LOG_LEVEL<=DBG_LEVEL_ERR)
|
||||
#define DBG_ERR( ml_msg_, ...) \
|
||||
DBG_LOG_(DBG_LEVEL_ERR, (ml_msg_), ##__VA_ARGS__)
|
||||
#else
|
||||
#define DBG_ERR( ml_msg_, ...)
|
||||
#endif
|
||||
|
||||
|
||||
#define DBG_LOG_(type_,msg_,...)\
|
||||
debug_log(__FILE__,__func__,__LINE__,type_,(msg_),##__VA_ARGS__)
|
||||
|
||||
|
||||
int debug_init(void);
|
||||
|
||||
void debug_log(const char *file,const char *fun,int line,int level,const char *fmt, ...);
|
||||
|
||||
|
588
source/soft/list.c
Normal file
588
source/soft/list.c
Normal file
@@ -0,0 +1,588 @@
|
||||
#include "list.h"
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include "stdio.h"
|
||||
#include "board.h"
|
||||
#include "mystdlib.h"
|
||||
#include "debug.h"
|
||||
#include "bytearray.h"
|
||||
#include "rtthread.h"
|
||||
|
||||
#define LIST_APPEND_SKIP 10
|
||||
|
||||
|
||||
typedef struct{
|
||||
int32_t next;
|
||||
int32_t prev;
|
||||
uint32_t data[0];
|
||||
}list_node_def;
|
||||
|
||||
|
||||
struct _list_def{
|
||||
int32_t all;
|
||||
int32_t used;
|
||||
int32_t block_size;
|
||||
int32_t block_size4;
|
||||
rt_mutex_t mutex;
|
||||
int32_t head;
|
||||
int32_t tail;
|
||||
sub_fun_def sub;
|
||||
del_fun_def del;
|
||||
str_fun_def str;
|
||||
uint32_t data[0];
|
||||
};
|
||||
|
||||
//#define list_enter_mutex(l)\
|
||||
// rt_mutex_take((l)->mutex,RT_WAITING_FOREVER)
|
||||
//
|
||||
//#define list_exit_mutex(l)\
|
||||
// rt_mutex_release((l)->mutex)
|
||||
|
||||
#define list_enter_mutex(l)
|
||||
#define list_exit_mutex(l)
|
||||
#define rt_mutex_create(...) 0
|
||||
#define rt_mutex_delete(l)
|
||||
|
||||
list_def *list_creat(int block_size,sub_fun_def sub,del_fun_def del,str_fun_def str)
|
||||
{
|
||||
static uint16_t count=0;
|
||||
char s1[16]={0};
|
||||
sprintf(s1,"list_mut#%d",count);
|
||||
int size=0;
|
||||
int block_size4;
|
||||
list_def *l;
|
||||
size+=sizeof(list_def);
|
||||
// 4字节对齐
|
||||
block_size4=((block_size+3)/4)*4;
|
||||
size+=(sizeof(list_node_def)+block_size4)*LIST_APPEND_SKIP;
|
||||
l=malloc(size);
|
||||
param_check(l);
|
||||
l->all=LIST_APPEND_SKIP;
|
||||
l->used=0;
|
||||
l->block_size=block_size;
|
||||
l->block_size4=block_size4;
|
||||
l->mutex=rt_mutex_create(s1,RT_IPC_FLAG_FIFO);
|
||||
l->head=-1;
|
||||
l->tail=-1;
|
||||
l->sub=sub;
|
||||
l->del=del;
|
||||
l->str=str;
|
||||
|
||||
// 初始化列表
|
||||
list_node_def *node;
|
||||
node=(list_node_def *)l->data;
|
||||
for(int i=0;i<l->all;i++)
|
||||
{
|
||||
node->next=-1;
|
||||
node->prev=-1;
|
||||
node=(list_node_def *)((uint32_t)node+sizeof(list_node_def)+l->block_size4);
|
||||
}
|
||||
count++;
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
// 对于数据里有指针数据的成员,需要提供del函数
|
||||
void _list_delete(list_def **l)
|
||||
{
|
||||
param_check(l);
|
||||
param_check(*l);
|
||||
list_enter_mutex(*l);
|
||||
if((*l)->del)
|
||||
{
|
||||
for(int i=0;i<(*l)->used;i++)
|
||||
{
|
||||
(*l)->del(list_get(*l,i));
|
||||
}
|
||||
}
|
||||
list_exit_mutex(*l);
|
||||
rt_mutex_delete((*l)->mutex);
|
||||
free(*l);
|
||||
*l=0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int list_block_size4(list_def *l)
|
||||
{
|
||||
param_check(l);
|
||||
return l->block_size4;
|
||||
}
|
||||
|
||||
|
||||
//static void cpy4byte(uint32_t *dst,uint32_t *src,int num_4byte)
|
||||
//{
|
||||
// for(int i=0;i<num_4byte;i++)
|
||||
// {
|
||||
// dst[i]=src[i];
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
|
||||
static list_def *list_expend(list_def *l)
|
||||
{
|
||||
int size=0;
|
||||
int cpysize=0;
|
||||
list_def *r;
|
||||
size+=sizeof(list_def);
|
||||
size+=(sizeof(list_node_def)+l->block_size4)*(l->all);
|
||||
cpysize=size;
|
||||
size+=(sizeof(list_node_def)+l->block_size4)*(LIST_APPEND_SKIP);
|
||||
r=malloc(size);
|
||||
param_check(r);
|
||||
cpy4byte((uint32_t *)r,(uint32_t *)l,cpysize/4);
|
||||
// 初始化列表
|
||||
list_node_def *node;
|
||||
node=(list_node_def *)((uint32_t)r->data+r->all*(sizeof(list_node_def)+r->block_size4));
|
||||
for(int i=0;i<LIST_APPEND_SKIP;i++)
|
||||
{
|
||||
node->next=-1;
|
||||
node->prev=-1;
|
||||
node=(list_node_def *)((uint32_t)node+sizeof(list_node_def)+r->block_size4);
|
||||
}
|
||||
r->all+=LIST_APPEND_SKIP;
|
||||
free(l);
|
||||
return r;
|
||||
}
|
||||
|
||||
// 查找一个未使用的节点
|
||||
static list_node_def *list_unused_node(list_def *l,int *index)
|
||||
{
|
||||
list_node_def *node=0;
|
||||
node=(list_node_def *)l->data;
|
||||
for(int i=0;i<l->all;i++)
|
||||
{
|
||||
if((node->next==-1)&&(node->prev==-1)){
|
||||
if(index) *index=i;
|
||||
return node;
|
||||
}
|
||||
node=(list_node_def *)((uint32_t)node+sizeof(list_node_def)+l->block_size4);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
// 取得指定序号的节点
|
||||
static list_node_def *list_node(list_def *l,int index)
|
||||
{
|
||||
list_node_def *node;
|
||||
param_check(index>=0&&index<l->all);
|
||||
node=(list_node_def *)((uint32_t)l->data+index*(sizeof(list_node_def)+l->block_size4));
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
// 取得节点的物理索引
|
||||
static int list_phy_index(list_def *l,list_node_def *n)
|
||||
{
|
||||
return ((uint32_t)n-(uint32_t)l->data)/(sizeof(list_node_def)+l->block_size4);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
// 改为统一使用insert函数
|
||||
list_def *list_append(list_def **l,void *data)
|
||||
{
|
||||
param_check(l);
|
||||
param_check(*l);
|
||||
list_def *r=*l;
|
||||
if((*l)->used>=(*l)->all)
|
||||
{
|
||||
r=list_expend(*l);
|
||||
}
|
||||
list_node_def *node;
|
||||
int index;
|
||||
node=list_unused_node(r,&index);
|
||||
param_check(node);
|
||||
memcpy(node->data,data,r->block_size);
|
||||
if(r->head==-1&&r->tail==-1)
|
||||
{
|
||||
r->head=index;
|
||||
r->tail=index;
|
||||
node->next=index;
|
||||
node->prev=index;
|
||||
}
|
||||
else if(r->head!=-1&&r->tail!=-1)
|
||||
{
|
||||
node->prev=r->tail;
|
||||
node->next=list_node(r,r->tail)->next;
|
||||
list_node(r,r->tail)->next=index;
|
||||
r->tail=index;
|
||||
list_node(r,r->head)->prev=index;
|
||||
}
|
||||
else
|
||||
{
|
||||
param_check(0);
|
||||
}
|
||||
r->used++;
|
||||
*l=r;
|
||||
return r;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
// 返回指定index的已使用节点
|
||||
static list_node_def *list_used_node(list_def *l,int index)
|
||||
{
|
||||
list_node_def *node=0;
|
||||
if(index>l->used/2)
|
||||
{
|
||||
index=l->used-1-index;
|
||||
node=list_node(l,l->tail);
|
||||
for(int i=0;i<index;i++)
|
||||
{
|
||||
node=list_node(l,node->prev);
|
||||
}
|
||||
}
|
||||
else{
|
||||
node=list_node(l,l->head);
|
||||
for(int i=0;i<index;i++)
|
||||
{
|
||||
node=list_node(l,node->next);
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 获取第index项数据,不删除
|
||||
// index支持负数,-1表示最后一项
|
||||
// 返回数据引用
|
||||
void *list_get(list_def *l,int index)
|
||||
{
|
||||
param_check(l);
|
||||
void *ret=0;
|
||||
list_enter_mutex(l);
|
||||
list_node_def *node;
|
||||
if(index<0) index=l->used+index;
|
||||
if((index>=0&&index<l->used)==0)
|
||||
ret=0;
|
||||
else{
|
||||
node=list_used_node(l,index);
|
||||
param_check(node);
|
||||
ret=node->data;
|
||||
}
|
||||
list_exit_mutex(l);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// 删除第index项数据
|
||||
// index支持负数,-1表示最后一项
|
||||
void list_remove(list_def *l,int index)
|
||||
{
|
||||
param_check(l);
|
||||
list_node_def *node;
|
||||
int phy_index;
|
||||
if(index<0) index=l->used+index;
|
||||
list_enter_mutex(l);
|
||||
if((index>=0&&index<l->used)){
|
||||
node=list_used_node(l,index);
|
||||
param_check(node);
|
||||
phy_index=list_phy_index(l,node);
|
||||
if(l->used==1)
|
||||
{
|
||||
l->head=-1;
|
||||
l->tail=-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(l->head==phy_index)
|
||||
{
|
||||
l->head=node->next;
|
||||
}
|
||||
if(l->tail==phy_index)
|
||||
{
|
||||
l->tail=node->prev;
|
||||
}
|
||||
list_node(l,node->prev)->next=node->next;
|
||||
list_node(l,node->next)->prev=node->prev;
|
||||
}
|
||||
node->next=-1;
|
||||
node->prev=-1;
|
||||
if(l->del) l->del(node->data);
|
||||
l->used--;
|
||||
}
|
||||
list_enter_mutex(l);
|
||||
}
|
||||
|
||||
|
||||
// 获取指定index的数据,随后删除
|
||||
// 返回数据的临时指针
|
||||
// 对于存在动态指针的对象,由于take之后会自动删除,take操作会出现野指针
|
||||
// 建议使用list_get + list_remove的方式代替list_take
|
||||
void *list_take(list_def *l,int index)
|
||||
{
|
||||
param_check(l);
|
||||
void *p;
|
||||
p=list_get(l,index);
|
||||
void *t=tmalloc(l->block_size);
|
||||
param_check(t);
|
||||
memcpy(t,p,l->block_size);
|
||||
list_remove(l,index);
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
// 清空
|
||||
void list_clear(list_def *l)
|
||||
{
|
||||
param_check(l);
|
||||
list_enter_mutex(l);
|
||||
while(l->used>0)
|
||||
{
|
||||
list_remove(l,0);
|
||||
}
|
||||
list_exit_mutex(l);
|
||||
}
|
||||
|
||||
|
||||
int list_length(list_def *l)
|
||||
{
|
||||
param_check(l);
|
||||
return l->used;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// 在指定位置插入
|
||||
// index为节点插入之后所在的位置
|
||||
list_def *_list_insert(list_def **l,void *data,int index)
|
||||
{
|
||||
param_check(l);
|
||||
param_check(*l);
|
||||
list_enter_mutex(*l);
|
||||
if(index<0) index=(*l)->used+index+1;
|
||||
if((index>=0&&index<=(*l)->used)==0){
|
||||
list_exit_mutex(*l);
|
||||
return *l;
|
||||
}
|
||||
list_def *r=*l;
|
||||
if((*l)->used>=(*l)->all)
|
||||
{
|
||||
r=list_expend(*l);
|
||||
}
|
||||
list_node_def *node;
|
||||
int phy_index;
|
||||
node=list_unused_node(r,&phy_index);
|
||||
param_check(node);
|
||||
memcpy(node->data,data,r->block_size);
|
||||
if(r->head==-1&&r->tail==-1)
|
||||
{
|
||||
r->head=phy_index;
|
||||
r->tail=phy_index;
|
||||
node->next=phy_index;
|
||||
node->prev=phy_index;
|
||||
}
|
||||
else if(r->head!=-1&&r->tail!=-1)
|
||||
{
|
||||
list_node_def *n;
|
||||
int n_phy_index;
|
||||
if(index<r->used)
|
||||
{
|
||||
n=list_used_node(r,index);
|
||||
n_phy_index=list_phy_index(r,n);
|
||||
list_node(r,n->prev)->next=phy_index;
|
||||
node->prev=n->prev;
|
||||
node->next=n_phy_index;
|
||||
n->prev=phy_index;
|
||||
if(index==0)
|
||||
{
|
||||
r->head=phy_index;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
node->prev=r->tail;
|
||||
node->next=list_node(r,r->tail)->next;
|
||||
list_node(r,r->tail)->next=phy_index;
|
||||
r->tail=index;
|
||||
list_node(r,r->head)->prev=phy_index;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
param_check(0);
|
||||
}
|
||||
r->used++;
|
||||
*l=r;
|
||||
list_exit_mutex(*l);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
void list_sort(list_def *l)
|
||||
{
|
||||
param_check(l);
|
||||
list_enter_mutex(l);
|
||||
if(l->sub){
|
||||
_list_sort(l,l->sub);
|
||||
}
|
||||
else{
|
||||
DBG_WARN("obj->sub fun is null.");
|
||||
}
|
||||
list_exit_mutex(l);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// 在列表内返回1,不在返回0
|
||||
int list_contains(list_def *l,void *d)
|
||||
{
|
||||
param_check(l);
|
||||
list_enter_mutex(l);
|
||||
if(l->sub)
|
||||
{
|
||||
for(int i=0;i<list_length(l);i++)
|
||||
{
|
||||
if(l->sub(list_get(l,i),d)==0){
|
||||
list_exit_mutex(l);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
DBG_WARN("obj->sub fun is null.");
|
||||
}
|
||||
list_exit_mutex(l);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// 交换两个位置
|
||||
void list_swap(list_def *l,int index_a,int index_b)
|
||||
{
|
||||
param_check(l);
|
||||
list_enter_mutex(l);
|
||||
void *a_=list_get(l,index_a);
|
||||
void *b_=list_get(l,index_b);
|
||||
void *t_=0;
|
||||
if(a_&&b_)
|
||||
{
|
||||
t_=calloc(1,sizeof(l->block_size4));
|
||||
cpy4byte(t_,a_,l->block_size4/4);
|
||||
cpy4byte(a_,b_,l->block_size4/4);
|
||||
cpy4byte(b_,t_,l->block_size4/4);
|
||||
free(t_);
|
||||
}
|
||||
list_exit_mutex(l);
|
||||
}
|
||||
|
||||
|
||||
// 向后循环移动
|
||||
void list_shift(list_def *l)
|
||||
{
|
||||
param_check(l);
|
||||
list_enter_mutex(l);
|
||||
if(l->used>0){
|
||||
l->head=list_node(l,l->head)->next;
|
||||
l->tail=list_node(l,l->tail)->next;
|
||||
}
|
||||
list_exit_mutex(l);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 输出打印字符串
|
||||
char *list_string(list_def *l)
|
||||
{
|
||||
param_check(l);
|
||||
list_enter_mutex(l);
|
||||
array_def *d=arr_creat();
|
||||
param_check(d);
|
||||
int len=0;
|
||||
char *s=0;
|
||||
arr_append(d,'(');
|
||||
if(l->str)
|
||||
{
|
||||
for(int i=0;i<list_length(l);i++)
|
||||
{
|
||||
s=l->str(list_get(l,i));
|
||||
len=strlen(s);
|
||||
arr_appends(d,s,len);
|
||||
free(s);
|
||||
arr_append(d,',');
|
||||
arr_append(d,' ');
|
||||
}
|
||||
}
|
||||
arr_append(d,')');
|
||||
len=arr_length(d);
|
||||
s=malloc(len+1);
|
||||
param_check(s);
|
||||
memcpy(s,arr_data(d),len);
|
||||
arr_delete(d);
|
||||
s[len]=0;
|
||||
list_exit_mutex(l);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// int sub函数
|
||||
int _list_int_sub(void *a,void *b)
|
||||
{
|
||||
return *(int *)a-*(int *)b;
|
||||
}
|
||||
|
||||
|
||||
// int 打印函数
|
||||
char *_list_int_str(void *a)
|
||||
{
|
||||
char *s=malloc(20);
|
||||
param_check(s);
|
||||
sprintf(s,"%d",*(int *)a);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
// str sub函数
|
||||
int _list_str_sub(void *a,void *b)
|
||||
{
|
||||
char *a_=*(char **)a;
|
||||
char *b_=*(char **)b;
|
||||
return strcmp(a_,b_);
|
||||
}
|
||||
|
||||
|
||||
// str删除函数
|
||||
int _list_str_del(void *d)
|
||||
{
|
||||
char **c=d;
|
||||
if(*c) free(*c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// str 打印函数
|
||||
char *_list_str_str(void *a)
|
||||
{
|
||||
char *a_=*(char **)a;
|
||||
int len=strlen(a_);
|
||||
char *s=malloc(len+1);
|
||||
param_check(s);
|
||||
memcpy(s,a_,len+1);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 延迟删除,不需要修改指针
|
||||
void _list_delete_later(list_def *l)
|
||||
{
|
||||
_list_delete(&l);
|
||||
}
|
||||
|
||||
|
||||
|
90
source/soft/list.h
Normal file
90
source/soft/list.h
Normal file
@@ -0,0 +1,90 @@
|
||||
#ifndef list_h__
|
||||
#define list_h__
|
||||
|
||||
#include "stdint.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
|
||||
|
||||
struct _list_def;
|
||||
typedef struct _list_def list_def;
|
||||
|
||||
|
||||
|
||||
typedef int (*sub_fun_def)(void *a,void *b);
|
||||
typedef int (*del_fun_def)(void *p);
|
||||
// 生成打印字符串指针,列表获取后会使用free释放
|
||||
typedef char *(*str_fun_def)(void *p);
|
||||
|
||||
#define INT_SUB _list_int_sub
|
||||
#define INT_DEL 0
|
||||
#define INT_STR _list_int_str
|
||||
#define STR_SUB _list_str_sub
|
||||
#define STR_DEL _list_str_del
|
||||
#define STR_STR _list_str_str
|
||||
|
||||
|
||||
/*r{ 基本操作函数 }c*/
|
||||
list_def *list_creat(int block_size,sub_fun_def sub,del_fun_def del,str_fun_def str);
|
||||
void *list_get(list_def *l,int index);
|
||||
void list_remove(list_def *l,int index);
|
||||
void *list_take(list_def *l,int index);/*temp_ptr*/
|
||||
void list_clear(list_def *l);
|
||||
int list_length(list_def *l);
|
||||
int list_block_size4(list_def *l);
|
||||
void list_sort(list_def *l);
|
||||
int list_contains(list_def *l,void *d);
|
||||
void list_swap(list_def *l,int index_a,int index_b);
|
||||
char *list_string(list_def *l);
|
||||
void list_shift(list_def *l);
|
||||
|
||||
|
||||
|
||||
|
||||
/*r{ 宏函数 }c*/
|
||||
#define list_creat_int() list_creat(sizeof(int),INT_SUB,INT_DEL,INT_STR)
|
||||
#define list_creat_str() list_creat(sizeof(char *),STR_SUB,STR_DEL,STR_STR)
|
||||
#define list_delete(l) _list_delete(&(l))
|
||||
#define list_insert(l,data,index) _list_insert(&(l),data,index)
|
||||
#define list_append(l,data) list_insert(l,data,-1)
|
||||
#define list_insert_int(l,int_,index) list_insert(l,(uint32_t []){int_},index)
|
||||
#define list_append_int(l,int_) list_insert_int(l,int_,-1)
|
||||
#define list_append_str(l,str) list_insert_str(l,str,-1)
|
||||
#define list_get_int(l,index) (*(int *)list_get(l,index))
|
||||
#define list_get_str(sl,index) (*(char **)list_get(sl,index))
|
||||
#define list_take_str(sl,index) (*(char **)list_take(sl,index))
|
||||
#define list_take_int(l,index) (*(int *)list_take(l,index))
|
||||
#define list_insert_str(l,str,index)\
|
||||
{\
|
||||
char *c=malloc(strlen(str)+1);\
|
||||
param_check(c);\
|
||||
memcpy(c,str,strlen(str)+1);\
|
||||
list_insert(l,(uint32_t []){(uint32_t)(c)},index);}
|
||||
// 要保证a,b的类型相同
|
||||
#define list_append_from(a,b) \
|
||||
for(int i=0;i<list_length(b);i++) {list_append(a,list_get(b,i));}
|
||||
#define list_appends(a,d,num) \
|
||||
for(int i=0;i<num;i++) {list_append(a,&d[i]);}
|
||||
|
||||
// 转化为列表的临时指针
|
||||
#define list_temp(l) tappend(l,_list_delete_later)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*r{ 用户不应直接调用的函数 }c*/
|
||||
list_def *_list_insert(list_def **l,void *data,int index);
|
||||
void _list_delete(list_def **l);
|
||||
void _list_delete_later(list_def *l);
|
||||
int _list_int_sub(void *a,void *b);
|
||||
char *_list_int_str(void *a);
|
||||
int _list_str_sub(void *a,void *b);
|
||||
int _list_str_del(void *d);
|
||||
char *_list_str_str(void *a);
|
||||
void _list_sort(list_def *l,sub_fun_def sub);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
45
source/soft/mymisc.c
Normal file
45
source/soft/mymisc.c
Normal file
@@ -0,0 +1,45 @@
|
||||
#include "rtthread.h"
|
||||
#include "stdlib.h"
|
||||
#include "stdint.h"
|
||||
#include "stdio.h"
|
||||
|
||||
|
||||
typedef struct{
|
||||
void (*later_fun)(void *t);
|
||||
void *t;
|
||||
rt_timer_t timer;
|
||||
}later_def;
|
||||
|
||||
|
||||
static void later_fun_exe(void *t)
|
||||
{
|
||||
later_def *l=t;
|
||||
rt_timer_delete(l->timer);
|
||||
if(l->later_fun){
|
||||
l->later_fun(l->t);
|
||||
}
|
||||
free(l);
|
||||
}
|
||||
|
||||
// 延迟一段时间调用函数
|
||||
void later_execute(void (*fun)(void *t),void *t,int ms)
|
||||
{
|
||||
static uint16_t count;
|
||||
char s1[16]={0};
|
||||
sprintf(s1,"later_t#%d",count);
|
||||
later_def *l=calloc(1,sizeof(later_def));
|
||||
l->later_fun=fun;
|
||||
l->t=t;
|
||||
l->timer=rt_timer_create(s1,later_fun_exe,l,
|
||||
rt_tick_from_millisecond(ms),
|
||||
RT_TIMER_FLAG_ONE_SHOT|RT_TIMER_FLAG_SOFT_TIMER);
|
||||
rt_timer_start(l->timer);
|
||||
count++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
20
source/soft/mymisc.h
Normal file
20
source/soft/mymisc.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef mymisc_h__
|
||||
#define mymisc_h__
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void later_execute(void (*fun)(void *t),void *t,int ms);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
352
source/soft/mystdlib.c
Normal file
352
source/soft/mystdlib.c
Normal file
@@ -0,0 +1,352 @@
|
||||
|
||||
#include "stdint.h"
|
||||
#include "string.h"
|
||||
#include "rtthread.h"
|
||||
#include "board.h"
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t *membase; // 内存池
|
||||
uint8_t memrdy; // 内存管理是否就绪
|
||||
uint16_t *memmap; // 内存管理状态表
|
||||
// 内存管理参数
|
||||
uint32_t memtblsize ; // 内存表大小
|
||||
uint32_t memblksize; // 内存分块大小
|
||||
uint32_t memsize ; // 内存总大小
|
||||
void *mutex;
|
||||
}mallco_dev;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define SRAM_USER_SIZE (256*1024)
|
||||
#define MEM_BLOCK_SIZE (32)
|
||||
#define MEM_MAX_SIZE (((SRAM_USER_SIZE))*MEM_BLOCK_SIZE/(MEM_BLOCK_SIZE+2))
|
||||
#define MEM_ALLOC_TABLE_SIZE ((MEM_MAX_SIZE/MEM_BLOCK_SIZE)&(~3))
|
||||
#define SRAM_USER_ADDR ((uint32_t)g_sram_mem)
|
||||
|
||||
//分配的内存都是双字对齐的
|
||||
#define MEM_BASE ((uint8_t *)(SRAM_USER_ADDR+MEM_ALLOC_TABLE_SIZE*2))
|
||||
#define MEMMAP_BASE ((uint16_t *)(SRAM_USER_ADDR))
|
||||
|
||||
static uint8_t g_sram_mem[SRAM_USER_SIZE];
|
||||
//内存管理控制器
|
||||
static mallco_dev g_self;
|
||||
|
||||
|
||||
|
||||
|
||||
//内存管理初始化
|
||||
void mem_init(void)
|
||||
{
|
||||
mallco_dev *self=&g_self;
|
||||
if(self->memrdy) return;
|
||||
|
||||
self->memtblsize = MEM_ALLOC_TABLE_SIZE;
|
||||
self->memblksize = MEM_BLOCK_SIZE;
|
||||
self->memsize = MEM_MAX_SIZE;
|
||||
self->membase=MEM_BASE;
|
||||
self->memmap=MEMMAP_BASE;
|
||||
|
||||
memset(self->memmap, 0,self->memtblsize*2);
|
||||
memset(self->membase, 0,self->memsize);
|
||||
self->mutex=rt_mutex_create("mem",RT_IPC_FLAG_FIFO);
|
||||
self->memrdy=1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 获取内存使用率
|
||||
// 返回值:使用率(0~100)
|
||||
int mem_perused(void)
|
||||
{
|
||||
mallco_dev *self=&g_self;
|
||||
uint32_t used=0;
|
||||
uint32_t i;
|
||||
for(i=0;i<self->memtblsize;i++)
|
||||
{
|
||||
if(self->memmap[i])used++;
|
||||
}
|
||||
//return (used*100)/(self->memtblsize);
|
||||
return used;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 内存分配(内部调用)
|
||||
// size:要分配的内存大小(字节)
|
||||
// 返回值:0XFFFFFFFF,代表错误;其他,内存偏移地址
|
||||
static uint32_t mem_malloc(uint32_t size)
|
||||
{
|
||||
mallco_dev *self=&g_self;
|
||||
signed long offset=0;
|
||||
uint16_t nmemb;
|
||||
uint16_t cmemb=0;
|
||||
uint32_t i;
|
||||
uint32_t ret=0xffffffff;
|
||||
if(size==0)return ret;
|
||||
rt_mutex_take(self->mutex,RT_WAITING_FOREVER);
|
||||
nmemb=size/self->memblksize;
|
||||
if(size%self->memblksize)nmemb++;
|
||||
for(offset=self->memtblsize-1;offset>=0;offset--)
|
||||
{
|
||||
if(!self->memmap[offset])cmemb++;
|
||||
else cmemb=0;
|
||||
if(cmemb==nmemb)
|
||||
{
|
||||
for(i=0;i<nmemb;i++)
|
||||
{
|
||||
self->memmap[offset+i]=nmemb;
|
||||
}
|
||||
ret= (offset*self->memblksize);
|
||||
break;
|
||||
}
|
||||
}
|
||||
rt_mutex_release(self->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//释放内存(内部调用)
|
||||
//offset:内存地址偏移
|
||||
//返回值:0,释放成功;1,释放失败;
|
||||
static int mem_free(uint32_t offset)
|
||||
{
|
||||
mallco_dev *self=&g_self;
|
||||
int i;
|
||||
int ret=1;
|
||||
rt_mutex_take(self->mutex,RT_WAITING_FOREVER);
|
||||
if(offset<self->memsize)
|
||||
{
|
||||
int index=offset/self->memblksize;
|
||||
int nmemb=self->memmap[index];
|
||||
for(i=0;i<nmemb;i++)
|
||||
{
|
||||
self->memmap[index+i]=0;
|
||||
}
|
||||
ret= 0;
|
||||
}
|
||||
rt_mutex_release(self->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void *malloc(uint32_t size)
|
||||
{
|
||||
mallco_dev *self=&g_self;
|
||||
uint32_t offset;
|
||||
void *ret_addr=NULL;
|
||||
offset=mem_malloc(size);
|
||||
if (offset!=0XFFFFFFFF)
|
||||
{
|
||||
ret_addr=(void*)((uint32_t)self->membase+offset);
|
||||
}
|
||||
return ret_addr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void self_free(void *ptr)
|
||||
{
|
||||
mallco_dev *self=&g_self;
|
||||
uint32_t offset;
|
||||
if(ptr==NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset=(uint32_t)ptr-(uint32_t)self->membase;
|
||||
mem_free(offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void *calloc(size_t nmemb, size_t size)
|
||||
{
|
||||
void *p;
|
||||
p=malloc(nmemb*size);
|
||||
if(p) memset(p,0,size);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
void *realloc(void *p,size_t size)
|
||||
{
|
||||
param_check(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define MEM_TEMP_PTR_NUM 400
|
||||
typedef void (*del_fun_def)(void *t);
|
||||
|
||||
typedef struct{
|
||||
void *temp_ptr[MEM_TEMP_PTR_NUM];
|
||||
void *del_ptr[MEM_TEMP_PTR_NUM];
|
||||
int used;
|
||||
uint32_t bitmap[(MEM_TEMP_PTR_NUM+31)/32];
|
||||
void *mutex;
|
||||
}temp_def;
|
||||
static temp_def g_tempptr;
|
||||
|
||||
|
||||
// 在位图中找到一个0/1
|
||||
static int bitmap_find(uint32_t *bitmap,int num,int bit)
|
||||
{
|
||||
for(int i=0;i<num;i++)
|
||||
{
|
||||
if((bitmap[i/32]&(1<<(i%32)))==(bit<<(i%32)))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
// 设置位图中指定位
|
||||
static void bitmap_set(uint32_t *bitmap,int index)
|
||||
{
|
||||
bitmap[index/32]|=1<<(index%32);
|
||||
}
|
||||
static void bitmap_clear(uint32_t *bitmap,int index)
|
||||
{
|
||||
bitmap[index/32]&=~(1<<(index%32));
|
||||
}
|
||||
static int bitmap_get(uint32_t *bitmap,int index)
|
||||
{
|
||||
return (bitmap[index/32]&(1<<(index%32)))==(1<<(index%32));
|
||||
}
|
||||
static void *tempptr_append(temp_def *t,void *p,void *del_fun)
|
||||
{
|
||||
if(p==NULL) return p;
|
||||
void *ret=NULL;
|
||||
if(del_fun==0) del_fun=self_free;
|
||||
if(t->used<MEM_TEMP_PTR_NUM)
|
||||
{
|
||||
int index=bitmap_find(t->bitmap,MEM_TEMP_PTR_NUM,0);
|
||||
param_check(index>=0);
|
||||
t->temp_ptr[index]=p;
|
||||
t->del_ptr[index]=del_fun;
|
||||
bitmap_set(t->bitmap,index);
|
||||
ret= p;
|
||||
t->used++;
|
||||
}
|
||||
else{
|
||||
param_check(0);
|
||||
}
|
||||
if(ret==NULL) ((del_fun_def)del_fun)(p);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// 查询指针是否已存在
|
||||
static int tempptr_find(temp_def *t,void *p)
|
||||
{
|
||||
int index;
|
||||
for(int i=0;i<MEM_TEMP_PTR_NUM;i++)
|
||||
{
|
||||
if(bitmap_get(t->bitmap,i))
|
||||
{
|
||||
if(t->temp_ptr[i]==p)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void tempptr_free(void)
|
||||
{
|
||||
int index;
|
||||
void *p=NULL;
|
||||
del_fun_def del=NULL;
|
||||
temp_def *t=&g_tempptr;
|
||||
rt_mutex_take(t->mutex,RT_WAITING_FOREVER);
|
||||
if(index=bitmap_find(t->bitmap,MEM_TEMP_PTR_NUM,1),index>=0)
|
||||
{
|
||||
// DBG_LOG("%s:free tempptr",__func__);
|
||||
p=t->temp_ptr[index];
|
||||
t->temp_ptr[index]=0;
|
||||
del=(del_fun_def)t->del_ptr[index];
|
||||
bitmap_clear(t->bitmap,index);
|
||||
t->used--;
|
||||
}
|
||||
rt_mutex_release(t->mutex);
|
||||
if(del) del(p);
|
||||
}
|
||||
|
||||
|
||||
void tempptr_init(void)
|
||||
{
|
||||
temp_def *t=&g_tempptr;
|
||||
t->mutex=rt_mutex_create("tempptr",RT_IPC_FLAG_FIFO);
|
||||
rt_thread_idle_sethook(tempptr_free);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// 申请临时内存,在任务结束后自动释放
|
||||
void *tmalloc(uint32_t size)
|
||||
{
|
||||
void *p;
|
||||
temp_def *t=&g_tempptr;
|
||||
p=malloc(size);
|
||||
rt_mutex_take(t->mutex,RT_WAITING_FOREVER);
|
||||
p=tempptr_append(&g_tempptr,p,NULL);
|
||||
rt_mutex_release(t->mutex);
|
||||
return p;
|
||||
}
|
||||
|
||||
// 把指针添加为临时指针
|
||||
void *tappend(void *p,void *del)
|
||||
{
|
||||
mallco_dev *self=&g_self;
|
||||
temp_def *t=&g_tempptr;
|
||||
void *ret=NULL;
|
||||
rt_mutex_take(t->mutex,RT_WAITING_FOREVER);
|
||||
if(((uint32_t)p>=(uint32_t)self->membase)&&
|
||||
((uint32_t)p<(uint32_t)(self->membase+self->memsize)))
|
||||
{
|
||||
if(tempptr_find(t,p)==0)
|
||||
{
|
||||
ret= tempptr_append(t,p,del);
|
||||
}
|
||||
}
|
||||
rt_mutex_release(t->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 释放内存,如果在临时表中则退出
|
||||
void free(void *p)
|
||||
{
|
||||
if(p==NULL) return;
|
||||
mallco_dev *self=&g_self;
|
||||
temp_def *t=&g_tempptr;
|
||||
int ret=0;
|
||||
rt_mutex_take(t->mutex,RT_WAITING_FOREVER);
|
||||
ret=tempptr_find(t,p);
|
||||
rt_mutex_release(t->mutex);
|
||||
if(ret){
|
||||
return;
|
||||
}else{
|
||||
self_free(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
27
source/soft/mystdlib.h
Normal file
27
source/soft/mystdlib.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef mystdlib_h__
|
||||
#define mystdlib_h__
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
|
||||
void mem_init(void);
|
||||
|
||||
int mem_perused(void);
|
||||
|
||||
void tempptr_init(void);
|
||||
|
||||
void *tmalloc(uint32_t size);
|
||||
|
||||
void *tappend(void *p,void *del);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
345
source/soft/mystring.c
Normal file
345
source/soft/mystring.c
Normal file
@@ -0,0 +1,345 @@
|
||||
|
||||
|
||||
#include "stdlib.h"
|
||||
#include "mystdlib.h"
|
||||
#include "mystring.h"
|
||||
#include "bytearray.h"
|
||||
#include "board.h"
|
||||
#include "string.h"
|
||||
|
||||
/*
|
||||
*
|
||||
* 从左向右找到字符串s中首次出现字符c的指针,没找到返回0
|
||||
* 例如 char *s=str_find_char_right("abcdef",'c')
|
||||
* s="cdef"
|
||||
*
|
||||
*/
|
||||
const char *str_find_char_right(const char *s,char c)
|
||||
{
|
||||
while(*s){
|
||||
if(*s==c) return s;
|
||||
s++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* 从左向右找到字符串s中首次出现字符c的指针,没找到返回0,
|
||||
* 指针p是向右检索的终点
|
||||
* 例如 char *s=str_find_char_right("abcdef",'c')
|
||||
* s="cdef"
|
||||
*
|
||||
*/
|
||||
const char *str_find_char_right_p(const char *s, const char *const p, char c)
|
||||
{
|
||||
while (*s++)
|
||||
{
|
||||
if (*s == c) return s;
|
||||
if (s >= p) break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* 从右向左找到字符串s中首次出现字符c的指针,没找到返回0
|
||||
* 指针p是向左检索的终点,s检索开始
|
||||
* char *t="abcdef";
|
||||
* char *s;
|
||||
* s=str_find_char_left(t,t+4,'b');
|
||||
* s="bcdef"
|
||||
*
|
||||
*/
|
||||
const char *str_find_char_left(const char *const p,const char *s,char c)
|
||||
{
|
||||
while(*s--)
|
||||
{
|
||||
if(*s==c) return s;
|
||||
if(s<=p) break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* 计算字符串 s 的长度
|
||||
*
|
||||
*/
|
||||
int str_len(const char *s)
|
||||
{
|
||||
int len=0;
|
||||
while(*s++) len++;
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* 把 s2 中的内容复制到 s1 中,长度为 n
|
||||
*
|
||||
*/
|
||||
void str_memcpy(char *s1,const char *s2,int n)
|
||||
{
|
||||
while(n--)
|
||||
*s1++=*s2++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* 把 s2 中第一个 c 字符前的字符复制到 s1 中,如果没找到则全部复制,返回复制的字符个数
|
||||
*
|
||||
*/
|
||||
int str_cpystr(char *s1,const char *s2,char c)
|
||||
{
|
||||
int len;
|
||||
const char *str=str_find_char_right((char *)s2,c);
|
||||
if(str==0) len=str_len(s2);
|
||||
else len=str-s2;
|
||||
str_memcpy(s1,s2,len);
|
||||
s1[len]=0;
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* 把整数字符串传化为int,直到遇到非数字字符
|
||||
*
|
||||
*/
|
||||
static int str_ainttoi(const char *s)
|
||||
{
|
||||
int ret=0;
|
||||
int sig=1;
|
||||
if(*s=='-'){
|
||||
s++;
|
||||
sig=-1;
|
||||
}
|
||||
while(*s)
|
||||
{
|
||||
if(*s>='0'&&*s<='9')
|
||||
{
|
||||
ret*=10;
|
||||
ret+=*s-'0';
|
||||
}
|
||||
else return ret;
|
||||
s++;
|
||||
}
|
||||
return ret*sig;
|
||||
}
|
||||
static int str_ahextoi(const char *s)
|
||||
{
|
||||
int ret=0;
|
||||
while(*s)
|
||||
{
|
||||
if(*s>='0'&&*s<='9')
|
||||
{
|
||||
ret*=16;
|
||||
ret+=*s-'0';
|
||||
}
|
||||
else if(*s>='a'&&*s<='f')
|
||||
{
|
||||
ret*=16;
|
||||
ret+=*s-'a'+10;
|
||||
}
|
||||
else if(*s>='A'&&*s<='F')
|
||||
{
|
||||
ret*=16;
|
||||
ret+=*s-'A'+10;
|
||||
}
|
||||
else return ret;
|
||||
s++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
int str_atoi(const char *s)
|
||||
{
|
||||
if(s[0]=='0'&&s[1]=='x'){
|
||||
return str_ahextoi(&s[2]);
|
||||
}else{
|
||||
return str_ainttoi(s);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* 把字符串以字符c分割为列表
|
||||
*
|
||||
*/
|
||||
list_def *str_split(const char *s,char c)
|
||||
{
|
||||
int len=str_len(s)+1;
|
||||
char *t=malloc(len);
|
||||
char *ptr1,*ptr2;
|
||||
list_def *l=list_creat_str();
|
||||
str_memcpy(t,s,len);
|
||||
ptr1=t;
|
||||
ptr2=t;
|
||||
while(*ptr1)
|
||||
{
|
||||
if(*ptr1==c){
|
||||
*ptr1=0;
|
||||
list_append_str(l,ptr2);
|
||||
ptr2=ptr1+1;
|
||||
}
|
||||
ptr1++;
|
||||
}
|
||||
list_append_str(l,ptr2);
|
||||
free(t);
|
||||
return list_temp(l);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* 把字符串转化为数字列表,每个数字之间分隔符是c
|
||||
*
|
||||
*/
|
||||
list_def *str_atod_list(const char *s, char c)
|
||||
{
|
||||
list_def *sl=str_split(s,c);
|
||||
list_def *dl=list_creat_int();
|
||||
for(int i=0;i<list_length(sl);i++)
|
||||
{
|
||||
int n;
|
||||
char *d=list_get_str(sl,i);
|
||||
n=str_atoi(d);
|
||||
list_append_int(dl,n);
|
||||
}
|
||||
return tappend(dl,0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* 判断字符是否是空白字符,是返回1,不是返回0
|
||||
*
|
||||
*/
|
||||
static inline int str_is_empty_char(char c)
|
||||
{
|
||||
const char table[]="\t\n\v\f\r ";
|
||||
if(str_find_char_right(table,c)!=0)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* 判断字符串是否是可打印,是返回1,不是返回0
|
||||
*
|
||||
*/
|
||||
int str_is_print_str(const char *str)
|
||||
{
|
||||
int len=str_len(str);
|
||||
for(int i=0;i<len;i++)
|
||||
{
|
||||
// 既不是空白字符也不是可打印字符
|
||||
if(!(str_is_empty_char(str[i])||(str[i]>=' '&&str[i]<='~')))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* 去除字符串中多余的空白字符 '\t', '\n', '\v', '\f', '\r', and ' ',返回临时指针
|
||||
*
|
||||
*/
|
||||
char *str_simplified(const char *str)
|
||||
{
|
||||
int is_empty=0;
|
||||
array_def *arr=arr_creat();
|
||||
param_check(arr);
|
||||
while(str_is_empty_char(*str)){
|
||||
str++;
|
||||
}
|
||||
while(*str){
|
||||
if(str_is_empty_char(*str)==0){
|
||||
if(is_empty==1){
|
||||
arr_append(arr,' ');
|
||||
is_empty=0;
|
||||
}
|
||||
arr_append(arr,*str);
|
||||
}else{
|
||||
is_empty=1;
|
||||
}
|
||||
str++;
|
||||
}
|
||||
char *ret=tmalloc(arr_length(arr)+1);
|
||||
param_check(ret);
|
||||
memcpy(ret,arr_data(arr),arr_length(arr));
|
||||
ret[arr_length(arr)]=0;
|
||||
arr_delete(arr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* 给字符串指针设置值
|
||||
*
|
||||
*/
|
||||
void _str_set(char **p,const char *str)
|
||||
{
|
||||
param_check(p);
|
||||
int len=0;
|
||||
if(str)
|
||||
len=str_len(str);
|
||||
else
|
||||
len=0;
|
||||
if(*p!=0)
|
||||
{
|
||||
free(*p);
|
||||
}
|
||||
*p=malloc(len+1);
|
||||
str_cpystr(*p,str,len);
|
||||
(*p)[len]=0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* 创建一个字符串副本
|
||||
*
|
||||
*/
|
||||
char *str_duplicate(char *p)
|
||||
{
|
||||
int len=str_len(p);
|
||||
char *s=malloc(len+1);
|
||||
param_check(s);
|
||||
str_cpystr(s,p,len+1);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
49
source/soft/mystring.h
Normal file
49
source/soft/mystring.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#ifndef mystring_h__
|
||||
#define mystring_h__
|
||||
|
||||
#include "list.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
const char *str_find_char_right(const char *s, char c);
|
||||
const char *str_find_char_right_p(const char *s,const char *const p, char c);
|
||||
const char *str_find_char_left(const char *const p,const char *s, char c);
|
||||
int str_atoi(const char *s);
|
||||
int str_len(const char *s);
|
||||
int str_cpystr(char *s1, const char *s2, char c);
|
||||
list_def *str_split(const char *s,char c);/*temp_ptr*/
|
||||
list_def *str_atod_list(const char *s, char c);/*temp_ptr*/
|
||||
char *str_simplified(const char *str);/*temp_ptr*/
|
||||
char *str_duplicate(char *p);
|
||||
int str_is_print_str(const char *str);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define str_set(p,str) _str_set(&p,str)
|
||||
#define str_temp(p) tappend(p,0)
|
||||
|
||||
|
||||
void _str_set(char **p,const char *str);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
296
source/soft/signal.c
Normal file
296
source/soft/signal.c
Normal file
@@ -0,0 +1,296 @@
|
||||
|
||||
|
||||
#include "signal.h"
|
||||
#include "board.h"
|
||||
#include "stdlib.h"
|
||||
#include "stdio.h"
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct{
|
||||
void *mutex;
|
||||
signal_list *head;
|
||||
}self_def;
|
||||
|
||||
|
||||
static self_def g_self;
|
||||
|
||||
|
||||
|
||||
int signal_init(void)
|
||||
{
|
||||
self_def *s=&g_self;
|
||||
if(s->mutex==0)
|
||||
{
|
||||
s->mutex=rt_mutex_create("signal_",RT_IPC_FLAG_FIFO);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void cpy4byte(uint32_t *dst,uint32_t *src,int num_4byte)
|
||||
{
|
||||
for(int i=0;i<num_4byte;i++)
|
||||
{
|
||||
dst[i]=src[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#define SLOT_FUN_RUN(fun,param) \
|
||||
((slot_fun_def)(fun))(param[0],param[1],param[2],\
|
||||
param[3],param[4],param[5],param[6],param[7])
|
||||
|
||||
typedef void (*slot_fun_def)(uint32_t a,uint32_t b,uint32_t c,uint32_t d,uint32_t e,uint32_t f,uint32_t g,uint32_t h);
|
||||
|
||||
static void slot_run(void *t)
|
||||
{
|
||||
param_check(t);
|
||||
slot_run_def *s=t;
|
||||
int msg_size=sizeof(slot_msg_def)+sizeof(uint32_t)*8;
|
||||
slot_msg_def *msg=calloc(1,msg_size);
|
||||
while(s->run)
|
||||
{
|
||||
rt_mq_recv(s->mb,msg,msg_size,RT_WAITING_FOREVER);
|
||||
SLOT_FUN_RUN(msg->fun,msg->param);
|
||||
}
|
||||
free(msg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 创建一个线程
|
||||
sig_thread thread_creat(int pro)
|
||||
{
|
||||
static uint16_t count=0;
|
||||
char name[20]={0};
|
||||
slot_run_def *run=calloc(1,sizeof(slot_run_def));
|
||||
run->run=1;
|
||||
sprintf(name,"sig_mq#%d",count);
|
||||
run->mb=rt_mq_create(name,(sizeof(slot_msg_def)+sizeof(uint32_t)*8),50,RT_IPC_FLAG_FIFO);
|
||||
sprintf(name,"sig_t#%d",count);
|
||||
rt_thread_t rt_t=rt_thread_create(name,slot_run,run,2048,pro,20);
|
||||
rt_thread_startup(rt_t);
|
||||
count++;
|
||||
return run->mb;
|
||||
}
|
||||
|
||||
|
||||
void thread_delete(sig_thread t)
|
||||
{
|
||||
// 删除线程需要删除与此线程相关的所有信号槽
|
||||
// 删除消息队列
|
||||
param_check(0);
|
||||
}
|
||||
|
||||
|
||||
// 如果这个类的信号已注册
|
||||
static signal_list *find(void *sig_obj,void *signal_)
|
||||
{
|
||||
self_def *s=&g_self;
|
||||
signal_list *l=s->head;
|
||||
while(l!=0)
|
||||
{
|
||||
if(l->signal_==signal_&&l->sig_obj==sig_obj)
|
||||
return l;
|
||||
l=l->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int connect(void *sig_obj,void *signal_,sig_thread t,void *slot_obj,void *slot)
|
||||
{
|
||||
self_def *s=&g_self;
|
||||
signal_def *sig;
|
||||
sig=signal_find(signal_);
|
||||
if(sig==0) return -1;
|
||||
rt_mutex_take(s->mutex,RT_WAITING_FOREVER);
|
||||
slot_list *slo=calloc(1,sizeof(slot_list));
|
||||
param_check(slo);
|
||||
slo->fun=slot;
|
||||
slo->mb=t;
|
||||
slo->next=0;
|
||||
slo->obj=slot_obj;
|
||||
signal_list *sig_l=find(sig_obj,signal_);
|
||||
|
||||
if(sig_l==0){
|
||||
sig_l=calloc(1,sizeof(signal_list));
|
||||
param_check(sig_l);
|
||||
sig_l->signal_=signal_;
|
||||
sig_l->sig_obj=sig_obj;
|
||||
sig_l->next=s->head;
|
||||
s->head=sig_l;
|
||||
}
|
||||
slo->next=sig_l->head;
|
||||
sig_l->head=slo;
|
||||
//DBG_LOG("signal connect:%08x",slo);
|
||||
rt_mutex_release(s->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int disconnect(void *sig_obj,void *signal_,sig_thread t,void *slot_obj,void *slot)
|
||||
{
|
||||
self_def *s=&g_self;
|
||||
signal_list *sig;
|
||||
sig=find(sig_obj,signal_);
|
||||
if(sig==0) return -1;
|
||||
int ret=-1;
|
||||
rt_mutex_take(s->mutex,RT_WAITING_FOREVER);
|
||||
slot_list *next=sig->head;
|
||||
slot_list *prev=0;
|
||||
while(next!=0)
|
||||
{
|
||||
if(next->fun==slot&&next->obj==slot_obj)
|
||||
{
|
||||
if(prev) prev->next=next->next;
|
||||
else sig->head=next->next;
|
||||
//DBG_LOG("signal disconnect:%08x",next);
|
||||
free(next);
|
||||
ret=0;
|
||||
break;
|
||||
}
|
||||
prev=next;
|
||||
next=next->next;
|
||||
}
|
||||
rt_mutex_release(s->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// 消除与指定对象相关的所有信号槽连接
|
||||
int disconnect_sig(void *sig_obj)
|
||||
{
|
||||
self_def *s=&g_self;
|
||||
rt_mutex_take(s->mutex,RT_WAITING_FOREVER);
|
||||
signal_list *sig=s->head;
|
||||
signal_list *prev_sig=0;
|
||||
while(sig!=0)
|
||||
{
|
||||
if(sig->sig_obj==sig_obj)
|
||||
{
|
||||
slot_list *next=sig->head;
|
||||
while(next!=0)
|
||||
{
|
||||
sig->head=next->next;
|
||||
free(next);
|
||||
next=sig->head;
|
||||
}
|
||||
if(prev_sig) prev_sig=sig->next;
|
||||
else s->head=sig->next;
|
||||
free(sig);
|
||||
break;
|
||||
}
|
||||
prev_sig=sig;
|
||||
sig=sig->next;
|
||||
}
|
||||
rt_mutex_release(s->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// 消除与指定对象相关的所有信号槽连接
|
||||
int disconnect_slot(void *slot_obj)
|
||||
{
|
||||
self_def *s=&g_self;
|
||||
rt_mutex_take(s->mutex,RT_WAITING_FOREVER);
|
||||
signal_list *sig=s->head;
|
||||
while(sig!=0)
|
||||
{
|
||||
slot_list *next=sig->head;
|
||||
slot_list *prev=0;
|
||||
while(next!=0)
|
||||
{
|
||||
if(next->obj==slot_obj)
|
||||
{
|
||||
if(prev) prev->next=next->next;
|
||||
else sig->head=next->next;
|
||||
free(next);
|
||||
break;
|
||||
}
|
||||
prev=next;
|
||||
next=next->next;
|
||||
}
|
||||
sig=sig->next;
|
||||
}
|
||||
rt_mutex_release(s->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
signal_def *signal_find(void *signal_)
|
||||
{
|
||||
extern const int signalstruct$$Base;
|
||||
extern const int signalstruct$$Limit;
|
||||
signal_def *start=(signal_def *)&signalstruct$$Base;
|
||||
signal_def *end=(signal_def *)&signalstruct$$Limit;
|
||||
for(signal_def *t=start;t<end;t++)
|
||||
{
|
||||
if(t->signal_==signal_)
|
||||
{
|
||||
return t;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// 发送信号
|
||||
int _signal_emit(void *sig_obj,void *signal_,uint32_t *param,int param_num)
|
||||
{
|
||||
self_def *s=&g_self;
|
||||
signal_list *sig=find(sig_obj,signal_);
|
||||
if(sig==0) return -1;
|
||||
if(param_num>7) return -2;
|
||||
int size=sizeof(slot_msg_def)+sizeof(uint32_t)*(8);
|
||||
slot_msg_def *m=malloc(size);
|
||||
rt_mutex_take(s->mutex,RT_WAITING_FOREVER);
|
||||
slot_list *h=sig->head;
|
||||
m->param_num=param_num;
|
||||
m->src=signal_;
|
||||
while(h)
|
||||
{
|
||||
m->fun=h->fun;
|
||||
if(h->obj)
|
||||
{
|
||||
cpy4byte(m->param+1,param,param_num);
|
||||
m->param[0]=(uint32_t)h->obj;
|
||||
}else{
|
||||
cpy4byte(m->param,param,param_num);
|
||||
}
|
||||
if(h->mb){
|
||||
rt_mq_send(h->mb,m,size);
|
||||
}else{
|
||||
SLOT_FUN_RUN(m->fun,m->param);
|
||||
}
|
||||
h=h->next;
|
||||
}
|
||||
rt_mutex_release(s->mutex);
|
||||
free(m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
96
source/soft/signal.h
Normal file
96
source/soft/signal.h
Normal file
@@ -0,0 +1,96 @@
|
||||
#ifndef signal_h__
|
||||
#define signal_h__
|
||||
|
||||
|
||||
#include "stdint.h"
|
||||
#include "rtthread.h"
|
||||
#include <rthw.h>
|
||||
#include "string.h"
|
||||
|
||||
|
||||
|
||||
|
||||
#define signal void
|
||||
#define emit
|
||||
|
||||
typedef struct _slot_list{
|
||||
struct _slot_list *next;
|
||||
void *fun;
|
||||
void *mb;
|
||||
void *obj;
|
||||
}slot_list;
|
||||
|
||||
|
||||
typedef struct _signal_list{
|
||||
struct _signal_list *next;
|
||||
slot_list *head;
|
||||
void *sig_obj;
|
||||
void *signal_;
|
||||
}signal_list;
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct{
|
||||
const char *name;
|
||||
void *signal_;
|
||||
// slot_list *head;
|
||||
}signal_def;
|
||||
|
||||
|
||||
typedef struct{
|
||||
void *fun;
|
||||
void *src;
|
||||
int param_num;
|
||||
uint32_t param[0];
|
||||
}slot_msg_def;
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct{
|
||||
void *mb;
|
||||
int run;
|
||||
}slot_run_def;
|
||||
|
||||
|
||||
typedef void * sig_thread;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define signal_export(name_) \
|
||||
const static char __sig_##name_##_name[] SECTION(".rodata.sigstr") = #name_; \
|
||||
RT_USED static signal_def _signal_##name_ SECTION("signalstruct")= \
|
||||
{\
|
||||
.name=__sig_##name_##_name,\
|
||||
.signal_=name_,\
|
||||
};
|
||||
|
||||
|
||||
|
||||
sig_thread thread_creat(int pro);
|
||||
void thread_delete(sig_thread t);
|
||||
signal_def *signal_find(void *signal_);
|
||||
int connect(void *sig_obj,void *signal_,sig_thread t,void *slot_obj,void *slot);
|
||||
int disconnect(void *sig_obj,void *signal_,sig_thread t,void *slot_obj,void *slot);
|
||||
int signal_init(void);
|
||||
int disconnect_sig(void *sig_obj);
|
||||
int disconnect_slot(void *slot_obj);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int _signal_emit(void *sig_obj,void *signal_,uint32_t *param,int param_num);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
131
source/soft/sort.c
Normal file
131
source/soft/sort.c
Normal file
@@ -0,0 +1,131 @@
|
||||
|
||||
#include "list.h"
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include "stdio.h"
|
||||
#include "board.h"
|
||||
#include "mystdlib.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 计算对应节点序号
|
||||
#define GET_FATHER_INDEX(index) (((index)-1)/2)
|
||||
#define GET_LEFT_INDEX(index) ((((index)+1)*2)-1)
|
||||
#define GET_RIGHT_INDEX(index) (((index)+1)*2)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//static void cpy4byte(uint32_t *dst,uint32_t *src,int num_4byte)
|
||||
//{
|
||||
// for(int i=0;i<num_4byte;i++)
|
||||
// {
|
||||
// dst[i]=src[i];
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 数据下沉
|
||||
// 输入:待排序列,要下沉的父节点序号,待排序列长度
|
||||
static void heap_sink(list_def *l, sub_fun_def sub,int start,int size)
|
||||
{
|
||||
int left, right, index;
|
||||
int temp_size=list_block_size4(l);
|
||||
void *temp=malloc(temp_size);
|
||||
void *l_left,*l_right,*l_i,*l_index;
|
||||
param_check(temp);
|
||||
for (int i = start; i < size;)
|
||||
{
|
||||
left = GET_LEFT_INDEX(i);
|
||||
right = GET_RIGHT_INDEX(i);
|
||||
l_left=list_get(l,left);
|
||||
l_right=list_get(l,right);
|
||||
if (right < size)
|
||||
{
|
||||
if(sub(l_left,l_right)>0)
|
||||
{
|
||||
cpy4byte(temp,l_left,temp_size/4);
|
||||
index = left;
|
||||
}
|
||||
else
|
||||
{
|
||||
cpy4byte(temp,l_right,temp_size/4);
|
||||
index = right;
|
||||
}
|
||||
}
|
||||
else if (left < size)
|
||||
{
|
||||
cpy4byte(temp,l_left,temp_size/4);
|
||||
index = left;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 序号超出堆范围
|
||||
break;
|
||||
}
|
||||
// 子节点比父节点小
|
||||
l_i=list_get(l,i);
|
||||
if(sub(temp,l_i)<=0)
|
||||
break;
|
||||
l_index=list_get(l,index);
|
||||
//array[index] = array[i];
|
||||
cpy4byte(l_index,l_i,temp_size/4);
|
||||
//array[i] = temp;
|
||||
cpy4byte(l_i,temp,temp_size/4);
|
||||
i = index;
|
||||
}
|
||||
free(temp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 把序列初始化为大顶堆
|
||||
static void heap_init(list_def *l, sub_fun_def sub,int size)
|
||||
{
|
||||
// 最后一层没有子节点,所以从倒数第二层开始
|
||||
// 当然,从最后一层开始也不影响结果
|
||||
for (int i = size/2; i > 0; i--)
|
||||
{
|
||||
heap_sink(l, sub,i - 1, size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void _list_sort(list_def *l,sub_fun_def sub)
|
||||
{
|
||||
param_check(l);
|
||||
param_check(sub);
|
||||
int temp_size=list_block_size4(l);
|
||||
void *temp=malloc(temp_size);
|
||||
void *l_i,*l_0;
|
||||
int size=list_length(l);
|
||||
heap_init(l, sub,size);
|
||||
//heap_print(array, size);
|
||||
for (int i = size; i > 0; i--)
|
||||
{
|
||||
l_0=list_get(l,0);
|
||||
l_i=list_get(l,i-1);
|
||||
//temp = array[0];
|
||||
cpy4byte(temp,l_0,temp_size/4);
|
||||
//array[0] = array[i-1];
|
||||
cpy4byte(l_0,l_i,temp_size/4);
|
||||
//array[i - 1] = temp;
|
||||
cpy4byte(l_i,temp,temp_size/4);
|
||||
heap_sink(l,sub,0, i - 1);
|
||||
}
|
||||
free(temp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
0
source/soft/sort.h
Normal file
0
source/soft/sort.h
Normal file
Reference in New Issue
Block a user