#
在移植glib到wince环境时,发现wince的c runtime library不包含很多库函数,诸如 bsearch() 半則搜索法,其用法有点像 std::bind2nd(), 费了点时间将其刨了出来,相信对有些人有用
1 void * bsearch( 2 const void *key, 3 const void *base0, 4 size_t nmemb, 5 size_t size, 6 int (*compar)(const void *, const void *)) { 7 8 const char *base = base0; 9 size_t lim; 10 int cmp; 11 const void *p; 12 13 for (lim = nmemb; lim != 0; lim >>= 1) { 14 p = base + (lim >> 1) * size; 15 cmp = (*compar)(key, p); 16 if (cmp == 0) 17 return ((void *)p); 18 if (cmp > 0) { /* key > p: move right */ 19 base = (char *)p + size; 20 lim--; 21 } /* else move left */ 22 } 23 return (NULL); 24 }
代码很容易阅读,以前做蓝牙项目时用户电话本搜索只用
static public string GetChineseSpell(string strText) { int len = strText.Length; string myStr = ""; for(int i=0;i<len;i++) { myStr += getSpell(strText.Substring(i,1)); } return myStr; }
static public string getSpell(string myChar) { byte[] arrCN = System.Text.Encoding.Default.GetBytes(myChar); if(arrCN.Length > 1) { int area = (short)arrCN[0]; int pos = (short)arrCN[1]; int code = (area<<8) + pos; int[] areacode = {45217,45253,45761,46318,46826,47010,47297,47614,48119,48119,49062,49324,49896,50371,50614,50622,50906,51387,51446,52218,52698,52698,52698,52980,53689,54481}; for(int i=0;i<26;i++) { int max = 55290; if(i != 25) max = areacode[i+1]; if(areacode[i]<=code && code<max) { return System.Text.Encoding.Default.GetString(new byte[]{(byte)(65+i)}); } } return "*"; } else return myChar; }
昨天接到the9的人事mm的电话通知今天去公司面试,职位大概是开发岗位 这些年来也一直没有面试的经历,闲在家里没事所以今天就去看看。 the9.com =>张江高科技园区碧波路690号3号楼,google了一下具体位置,带了个导航仪开着桑哥走了。 外环比较拥挤,25公里开了45分钟便到了碧波路,一个大拐就进了690号,接着一个小拐又一个大拐,直接将车停就进了车位,"技术不错,可以打9.9分"。 the9也算是有点财力和规模,整个一片都是the9公司。 刚想推门下车,一个保安马上上来,我想这个服务到是周到。"先生,这里不能停车,这是我们老板的车位". 奶奶的,确实边上不是BMW就是A6之类的车子,仔细一看,确实车位上都有具体的车牌。一不小心把车停到the9老板 家了。接着就倒车,7拐八拐 找了个日光浴的位置。 来到the9的前台,说是要做题,领了份考卷就去2号会议室。 里面有2人,各一男女,没多时便走了,过了半小时又进来一位做题,看上去比我是年轻多了。 开始做题,好久没被面试了,有点兴奋。某些题目回答的太细且考虑过多,磨磨蹭蹭也搞了一个小时,看了下钟点15:30了。 接着等人来捞我去谈,等了30分钟也没人来,所以就踱到前台交予前台mm(长得不错哦)。然后我继续等,约莫20来分钟mm叫我,我便跟一个叫陈国*的Man去面试,陈**带我绕了几条走廊,那个走路的速度真是超级的慢,居然是我走在他前面,有点受不了。 进了一会议室,陈**不知为何一下子没开口,瞬即拿出笔在白板上写了起来。 "你现在做个题目哦,题目是这样的:1000~10000里面的4位平方数你给我找出来,数字的规则是 abcd, a=b c=d,我现在有个其他面试,过5分钟我再来",奶奶的,居然还让我做题,而且是这种小学生做的题目。说完陈Man就走了,真是来气,起来我也转身离开了the.com。 做了这么些年的开发,本来以为面试会跟我聊一下系统的架构,opensource,通信技巧,看了我的简历也不应该当成应届毕业生来对待啊,一些考官就是喜欢在面试过程中夹杂一些自己的小聪明搞一些旁门做到的东西,想想过去我做考官也不是这个样子的,还是比较对人尊重的,这么大的一个公司让面试的人左等右等,感觉这是不这么的好。 记得一个mm说的好,说是老板与员工不存在地位的差别,雇佣和被雇工是建立在平等的基础上的合作关系。 想到了 盖茨关于他的车位总是被员工占用,及员工总是跟盖茨借钱的故事;想到了以前一位博士领导整天给老总安装office的事情 中国人骨子里还是比较官僚的,阶级感比较强烈,老板永远是老板,是上帝,打工的就是一条狗。 不过我对狗这个字眼不感冒,我就是一条狗,但是是条有尊严的狗。 the9对其现在不这么感兴趣了,林子大了啥鸟都有,还是老实在家呆着。 the9的考题对于开发者的还是有点用的,凭着有点记忆的脑子回想一下考题,大致如下:
1.是非题: 10题 具体记不清楚了 2.解释: const 的作用(2种以上) 数据与链表的差异和作用 纯虚函数,重载的区别和作用
3.改错并解释: 1. void getmemory( char * p){ p = new char[20]; } main(){ char *str; getmemory(str); strcpy(str,"hello"); } 2. char * getmemory(){ char buf[]="ssssssssssssssss"; return buf; } main(){ sprintf(buf,"%d",100); printf( buf); }
4.编写函数: 1. strcmp int strcmp( char * s1,char * s2 ){ }
2. strstr // return pointer if s2 found in s1,else return NULL char * strstr(char* s1,char* s2){ }
3. void compress(char * in,char * out) 要求: in out abc abc aaabbbccc a2b2c2
5. 实现以下类成员函数并解释 class String(){ String(char* s=NULL); String( const String & other); String & operator+=(const String &other); bool operator==(const String & other ); operator double(); }; 6. 链表倒置 struct listNode{ struct listNode * next; int data; } 返回列表头节点 listNode * reverse(listNode * head){ } 这些题基本上是能考核一个c/cpp开发人员的基本技术能力的
return true if equal
1 bool strcmp( char* d,char * s){ 2 if( d==s) return true; 3 while( *d==*s && *d && *s){ 4 d++;s++; 5 } 6 if( *d==*s && *d==0){ 7 return true; 8 } 9 return false; 10 }
摘要: 经常会在编写流驱动接口的时候必须实现一系列的接口,诸如 xxx_init,xxx_open,xxx_write等等,某些接口函数虽然无需功能的实现但也必须定义一个空的函数接口。由于多年的c++思路,利用虚函数(virtual)和重载(override)把这些驱动的实现封装起来,来简化代码量。程序的实现,采用了两种方式: 宏定义和类继承希望对编写wince 流驱动的开发人员有所帮助
Code hi... 阅读全文
目前已经完成移植的开源项目列表: cairo.dll zlib1_2_3.lib cairomm.lib expat_wince.dll expat_wince.lib fontconfig-lib.lib freetype235.lib gdkpixbuf.dll glib-lite.lib gmodule.lib gobject.lib gthread.lib iconv.dll iconv.lib jpeg.lib libsigc++.lib libtinyxpath.lib libxml_ce.dll libxml_ce.lib mini-fribidi.lib opentype.lib pango1.18.dll pango1.18.lib pangocairo.lib pangoft2.lib papyrus0.7.1.lib png1.2.8.dll png1.2.8.lib zlib1_2_3.dll wxWidgets
未完成的移植内容: librsvg wxLua
Fontconfig 2.5.0
Cairo依赖Fontconfig部分,但未见其起初的时候调用fontconfig的初始化函数,诸如FcInit().
Fontconfig代码有WIN32条件编译的宏,且预定义了DllMain()入口,但也未调用FcInit()
Fontconfig要移植到wince,必须处理内部诸多的单字节与宽字符转换问题
Fontconfig将字体文件cached的过程就是将字体文件映射到内存地址空间
FontConfig 设有字体目录(font-dir),缓冲目录(cache-dir),配置目录(font-dir)
Cache-dir目录存放字体缓冲文件 ?????-x86- cache2,缓冲文件被mmap进内存
每个font目录都将创建一个cache文件,存放于cache-dir下
Cache文件内存放一个字体目录下(font-dir)所有字体的pattern信息集合和基本的FcCache对象的控制信息,系统扫描完字体之后的信息存于FcSerialize对象,之后绑定到FcCache对象,之后将FcCache对象及其关联的数据全部写入本地文件cache-file。
之后在加载cache-file时通过FcDirCacheMapHelper()->FcDirCacheMapFd()将cache-file进行mmap映射到虚拟地址空间,采用mmap方式可以允许多个进程同时访问这些字体信息。
系统初始化时FcInit()检测cache文件是否存在(文件锁控制),不存在则扫描字体目录创建缓冲文件(一个字体目录对应一个缓冲文件);否则打开缓冲文件并映射进入本地进程的地址空间(mmap),其起始地址被转换为FcCache*对象返回
如果字体目录下存在子目录,在生成的信息存放在FcCache::dirs处
FcSerialize过程
将不同类型的Fcxxxx对象序列化转储时,先将对象结构信息专储,对象内的指针指向的对象也进行转储到对象头信息之后,其位置由对象头结构内的intptr_t变量指定。
例如:
struct _FcCache {
int magic; /* FC_CACHE_MAGIC_MMAP or
FC_CACHE_ALLOC */
int version; /*
FC_CACHE_CONTENT_VERSION */
intptr_t size;
/* size of file */
intptr_t dir;
/* offset to dir name */
intptr_t dirs;
/* offset to subdirs */
int dirs_count;
/* number of subdir strings */
intptr_t set;
/* offset to font set */
int mtime;
/* low bits of directory mtime */
};
FcCache对象结构信息先被serialize, intptr_t变量指向的附属数据所在位置(本对象的当前偏移量)
struct _FcPattern {
int num;
int size;
intptr_t elts_offset;
int ref;
};
typedef struct _FcPatternElt {
FcObject object;
FcValueList *values;
} FcPatternElt;
每个FcPattern由若干个FcPatternElt组成FcPatternElt的数组的首地址与FcPattern对象地址的差值作为偏移量存储在FcPattern::elts_offset中
Fonts.conf
可以禁用部分字体或者启用字体(字体目录)
{ "acceptfont", FcElementAcceptfont },
{ "rejectfont", FcElementRejectfont },
如果没有定义acceptfont和rejectfont,则默认都是acceptfont的,所以<dir>font-dir</dir>默认是允许的
每个字体文件通过freetype进行访问,当在font目录下扫描字体文件是,将读取若干个patterns
FcSerialize 的FcSerializeBucket存储
SystemFont or ApplicationFont
不同字体被登记在不同类别的字体集合中管理
FcSerializebucket不能超过 8k个,字体文件也不能过8k个,每个字体文件名置入bucket
/**
*
container_of - cast a member of a structure out to the containing structure
*
*
@ptr: the pointer to the member.
*
@type: the type of the container
struct this is embedded in.
*
@member: the name of the member within the
struct.
*
*/
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
#define list_entry(ptr, type, member) \
container_of(ptr,
type, member)
#define offsetof(TYPE,
MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
Example:
struct user_struct *user;
user = list_entry(up, struct user_struct,
uidhash_list);
取成员变量偏移量:
struct testcls{
int
a;
int
b;
};
testcls *cls= new testcls;
UINT offset = (UINT)&((testcls*)0)->b;
编译
Fontconfig部分头文件需要在makefile时产生,比如fc-lang.h,fc-case.h,将其在linux下编译fontconfig.tgz,产生这几个头文件再拷贝出来
FONTCONFIG 的WINCE/WIN32移植
WinX版本去除了以下内容:
FcCache
FcSerialize 不支持对象的序列化存储
不支持多字体目录
不支持多cache目录
所以不支持多进程共用fontconfig 的cache内容,也就是不能用mmap进行map到自己的空间。这样每个进程必须消耗一系列的Pattern及其相关对象所占据的内存空间。
因为在嵌入式环境配置的字体可能只有1,2种,这种内存的消耗应该不会是很大
WINCE:
字体存储和配置信息储存在wince.h文件
#define FONTS_DIR "/nandflashpartition/fonts"
#define FONTS_CACHE_DIR "/nandflashpartition/fonts-cache"
#define FONTCONFIG_FILE FONTS_DIR##"/fonts.conf"
Fonts.conf
<fontconfig>
<dir>/nandflashpartition/fonts</dir>
<cachedir>/nandflashpartition</cachedir>
<font-file>simhei.ttf</font-file>
</fontconfig>
CMakefile的配置
#去除_WIN32 _WINDOWS定义
ADD_DEFINITIONS(-D_WINCE
-D_WIN32_WCE=0x500 -DUNDER_CE -DWINCE -DARM -D_ARM_ -D_UNICODE -DUNICODE)
INCLUDE_DIRECTORIES("../"
"C:/temp9/papyrus_dependencies/include" )
add_library (fontconfig
# fcatomic.c
fcblanks.c
# fccache.c
fccfg.c
fccharset.c
fcdbg.c
fcdefault.c
fcdir.c
fcfreetype.c
fcfs.c
fcinit.c
fclang.c
fclist.c
fcmatch.c
fcmatrix.c
fcname.c
fcpat.c
# fcserialize.c
fcstr.c
fcxml.c
ftglue.h
ftglue.c
wince.h
wince_imp.c
)
Fontconfig目前作为静态库生成并被使用,因为dll生成必须定义fontconfig.def(此操作费时)
cairo是opensource的项目,其在*nix上利用makefile,gcc便能很方便进行编译,客户程序也能很方便pkg-config进行链接.
cairo 依赖项目: FreeType,FontConfig,libPng,libExpat,libZ
Win32平台的编译也是非常简单,只要将makefile.in里面的东东搬到CMakefiles.txt中,然后用CMake(2.4)产生vs2005的工程即可
WINCE的编译可谓是异常的麻烦 FreeType倒是不错,自带了wince的工程档,FontConfig却是没有,且Fontconfig为了实现多进程共享字体资源而采用了cache机制,应用程序通过mmap()将字体信息映射到自己的地址空间来访问。这种模式在wince里可谓没有必要,所以对Fontconfig进行了比较大的手术,去除了FcSerialize,FcCache,FcPattern的内存映射机制,同时限定fonts.conf的存储位置,字体目录位置等等。
libPng: libpng的 png_convert_from_struct_tm ,png_convert_from_time_t 在wince得不到实现,因为部分的c runtime functions在wince没有实现,所以不得已自己实现这些功能函数
我编译的cairo特性: 支持win32_surface,freetype,fontconfig,image_surface,png_surface
#define OUT #define INOUT #define IN
#define INIT_LIST_HEAD(x)
#define btsc_TRUE 0 #define btsc_FALSE 1 #define btsc_NULL 0
struct list_head{ struct list_head* prev,*next; };
struct btsc_Property{ char * name; char * value; };
struct btsc_Packet{ /*struct list_head list;*/ struct btsc_Property** properties; int size; int capacity; struct btsc_Context * ctx; };
struct btsc_Packet* btsc_Packet_Alloc(struct btsc_Context* ); void btsc_Packet_Free(struct btsc_Packet*);
struct btsc_Property* btsc_Property_Alloc(struct btsc_Context* ,char * name,char * value); void btsc_Property_Free(struct btsc_Property*);
struct btsc_Property* btsc_Property_Get(struct btsc_Packet* packet,char * name); void btsc_Property_Append(struct btsc_Packet* packet,struct btsc_Property * );
struct btsc_Context{ void (*tx)(struct btsc_Context*,unsigned char * data,int len); int (*notifier)(struct btsc_Packet* packet);/*外部释放packet,返回NULL*/ int packet_cached_size; int recv_cached_capacity; char* recv_buff; int recv_size; void* user; // 外部数据传递 };
int btsc_init(struct btsc_Context* IN ctx); void btsc_cleanup(struct btsc_Context* IN ctx); int btsc_Pack(struct btsc_Context* IN ctx,struct btsc_Packet* packet,unsigned char * INOUT buff,int* INOUT size); void btsc_Parse(struct btsc_Context* , char * data,int len);
#define BTSC_PACKET_BEGIN(ctx) {\ struct btsc_Context* _ctx_internel;\ struct btsc_Packet * _pkt ;\ _ctx_internel= (ctx);\ _pkt = btsc_Packet_Alloc(_ctx_internel); /* key is not suitable for vairable*/ #define BTSC_NEW_PROPERTY(key,value) {\ struct btsc_Property * _ppt =btsc_Property_Alloc(_ctx_internel,key,value);\ btsc_Property_Append(_pkt,_ppt);\ } #define BTSC_PACKET_END() btsc_Pack(_ctx_internel,_pkt,btsc_NULL,0);\ btsc_Packet_Free(_pkt);\ }
#define BTSC_FOREACH(packet,ppt) {\ int n;\ for(n=0;n<packet->size;n++){\ ppt = packet->properties[n]; #define BTSC_END_FOREACH() }\ }
/* name: btsc serial communicating with bluetooth and app-user desc: pair parameter codec packet=[ key:name,...] implemented: zhangbin , 3 hours occupied date: 2007-01-26 */
#include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef _UNIX #include <unistd.h> #endif #include "btsc.h"
#define PACKET_HEAD '<' #define PACKET_TAIL '>' #define PROPERTY_DELIMITER ',' #define PAIR_DELIMITER '=' #define ESCAPE_CHAR '\\'
int calcEscapleLength(char * str); char* escape_copy(char * dest,char * src); void trim_escape_copy(char * dest,char * src,int size); int calcPacketLength(struct btsc_Packet* pkt); int is_escape_char(char c); void parseProperty(struct btsc_Packet * pkt,char * s,char * e); void parsePacket(struct btsc_Context* ctx,char * s,char* e); char* __memchr(char * s,char* e,char c);
char escape_ch_table[]={PACKET_HEAD,PACKET_TAIL,PROPERTY_DELIMITER,PAIR_DELIMITER,ESCAPE_CHAR,'\0'};
struct btsc_Packet* btsc_Packet_Alloc(struct btsc_Context* ctx){ struct btsc_Packet * pt = malloc(sizeof(struct btsc_Packet)); pt->size = 0; pt->capacity = ctx->packet_cached_size; pt->properties=malloc(pt->capacity*sizeof(struct btsc_Property*)); pt->ctx = ctx; return pt; }
void btsc_Packet_Free(struct btsc_Packet* pt){ struct btsc_Property** tmp; if( !pt ) return ; tmp = pt->properties; while(pt->size--){ btsc_Property_Free(*tmp++); } if( pt->properties){ free(pt->properties); } free(pt); }
struct btsc_Property* btsc_Property_Alloc(struct btsc_Context* ctx,char * name,char * value){ struct btsc_Property * ppt; printf("enter btsc_Property_Alloc()\n"); ppt = malloc( sizeof( struct btsc_Property) ); if(!ppt) printf("error: malloc failed (s1)\n"); ppt->name = malloc( strlen(name)+1); if( !ppt->name ) printf("error: malloc failed (s2)\n"); strcpy(ppt->name,name); ppt->value = malloc( strlen(value)+1); if( !ppt->value) printf("error: malloc failed (s3),str:%s, len: %d\n",value,strlen(value)+1); strcpy( ppt->value,value); return ppt; }
void btsc_Property_Free(struct btsc_Property* ppt){ if( !ppt ) return; free( ppt->name); free( ppt->value); free( ppt); }
/* scan pointer array */ struct btsc_Property* btsc_Property_Get(struct btsc_Packet* pkt,char * name){ int size; struct btsc_Property* ppt; size = pkt->size; while(size--){ ppt = pkt->properties[size]; if( !strcmp( name, ppt->name ) ){ return ppt;/*that's ok */ } } return btsc_NULL; }
/* low effeciency, memory allocation,more costs*/ void btsc_Property_Append(struct btsc_Packet* pt,struct btsc_Property * ppt){ struct btsc_Property** tmpppt; if( pt->size==pt->capacity){ pt->capacity += pt->ctx->packet_cached_size; tmpppt = pt->properties; pt->properties = malloc( pt->capacity * sizeof( struct btsc_Property**) ); memcpy( pt->properties, tmpppt, pt->size * sizeof( struct btsc_Property**)); free( tmpppt); } pt->properties[pt->size++]=ppt; }
int btsc_init(struct btsc_Context* ctx){ ctx->packet_cached_size = 10; if( ctx->recv_cached_capacity==0){ ctx->recv_cached_capacity = 1024*2; } ctx->recv_buff = malloc( ctx->recv_cached_capacity ); ctx->recv_size = 0; return btsc_TRUE; }
void btsc_cleanup(struct btsc_Context* ctx){ free(ctx->recv_buff); }
/* ** name: calcEscapleLength ** desc: 计算含转义字符串长度 */ int calcEscapleLength(char * str){ int len; char * pesc; len = 0; while( *str ){ pesc = escape_ch_table; while( *pesc ){ if( *pesc==*str){ len++; break; } pesc++; } str++; } return len; }
char* escape_copy(char * dest,char * src){ char * pesc; while( *src ){ pesc = escape_ch_table; while( *pesc ){ if( *pesc==*src){ *dest++=ESCAPE_CHAR; break; } pesc++; } *dest++=*src++; } return dest; }
void trim_escape_copy(char * dest,char * src,int size){ int last_escape = btsc_FALSE; while( size--){ if( *src == ESCAPE_CHAR && last_escape != btsc_TRUE){ last_escape = btsc_TRUE ; src++; continue; } last_escape = btsc_FALSE; *dest++=*src++; } }
int calcPacketLength(struct btsc_Packet* pkt){ int len; int size; struct btsc_Property* ppt; len = 0; size = pkt->size; while( size--){ ppt = pkt->properties[size]; len+=strlen(ppt->name)+strlen(ppt->value);
len+= calcEscapleLength(ppt->name); len+= calcEscapleLength(ppt->value); } len+= pkt->size*2+1; return len; }
int btsc_Pack(struct btsc_Context* ctx,struct btsc_Packet* pkt,unsigned char * obuff,int* osize){ struct btsc_Property* ppt; int size; int len; unsigned char * buff; char * pbuff; len = calcPacketLength( pkt); buff = malloc( len ); size = pkt->size; pbuff = (char*)buff; *pbuff++=PACKET_HEAD; while( size--){ ppt = pkt->properties[size]; pbuff = escape_copy(pbuff,ppt->name); *pbuff++=PAIR_DELIMITER; pbuff = escape_copy(pbuff,ppt->value); if( size ){ *pbuff++=PROPERTY_DELIMITER; } } *pbuff = PACKET_TAIL; if( ctx->tx ){ ctx->tx(ctx,buff,len); } if( obuff && *osize >=len){ memcpy( obuff, buff ,len); *osize = len; }
free(buff); return btsc_TRUE; }
/* e not in range*/ char* __memchr(char * s,char* e,char c){ while( s!=e){ if( *s == c){ return s; } s++; } return btsc_NULL; }
int is_escape_char(char c){ return btsc_FALSE; }
/* name: parseProperty desc: 指定内存范围中提取属性 key=>value 搜索包含e params: pkt -- 消息数据包 s -- 起始内存地址 e -- 结束地址 , */ void parseProperty(struct btsc_Packet * pkt,char * s,char * e){ char * p1,*p2; int n; struct btsc_Property* ppt; p1 = s ; p2 = e; __REPEAT: p1 = __memchr(p1,e+1,PAIR_DELIMITER); if( p1 ){ if( *(p1-1) == ESCAPE_CHAR ){ p1++; goto __REPEAT; } ppt = malloc( sizeof( struct btsc_Property )); n = p1-s; ppt->name = malloc( n+1 ); memset(ppt->name,0,n+1); trim_escape_copy(ppt->name,s,n); n =e-p1; ppt->value = malloc( n+1); memset(ppt->value,0,n+1); trim_escape_copy(ppt->value,p1+1,n); btsc_Property_Append(pkt,ppt); } }
/* name: parsePacket desc: 分解指定内存到包结构 成功分解出包立刻回送到应用接收者 ( btsc_Context::notifier) param: s,e 内存地址 (处e)
** 缓冲区还需进一步测试,包括缓冲区大小调节, 不完整协议包格式的容错 */ void parsePacket(struct btsc_Context* ctx,char * s,char* e){ char *p,*p1,*p2; struct btsc_Packet * pkt; if( e-s <=1 ){ return ; } pkt = btsc_Packet_Alloc(ctx); p1 = s+1; p2 = e-1; p = p1; __REPEAT: p = __memchr(p,e,PROPERTY_DELIMITER); if( p ){ if( *(p-1)==ESCAPE_CHAR){ p = p+1; goto __REPEAT; } parseProperty(pkt,p1,p-1); p1 = ++p; goto __REPEAT; } /*allow one property reside in*/ parseProperty(pkt,p1,e-1); if( ctx->notifier ){ if(ctx->notifier(pkt)){ /* nonzero value, delete internal*/ btsc_Packet_Free(pkt); } }else{ btsc_Packet_Free(pkt); } }
void btsc_Parse(struct btsc_Context* ctx, char * data,int size){ int len ; _RESTART: while( size ){ len = ctx->recv_cached_capacity - ctx->recv_size; if( len >0){ if( size <= len){ len = size; size = 0; }else{ size-=len; } memcpy( ctx->recv_buff+ctx->recv_size,data,len); ctx->recv_size+=len; data+=len; } { char * p1,*p2; _RESCAN: p1 = ctx->recv_buff; _RESCAN_HEAD: p1 = __memchr(p1,ctx->recv_buff+ctx->recv_size,PACKET_HEAD); if( !p1 ){ ctx->recv_size =0; if( size ){ goto _RESTART; } } if( p1>ctx->recv_buff && *(p1-1)==ESCAPE_CHAR){ /* "\<" */ p1++; goto _RESCAN_HEAD; } /*move backward*/ ctx->recv_size -=(p1-ctx->recv_buff); memmove(ctx->recv_buff,p1, ctx->recv_size); p1=ctx->recv_buff; p2 = p1+1; _RESCAN_TAIL: p2 = __memchr(p2,ctx->recv_buff+ctx->recv_size,PACKET_TAIL); if( !p2 ){ if( ctx->recv_size == ctx->recv_cached_capacity ){ ctx->recv_size = 0; } goto _RESTART; } if( *(p2-1) == ESCAPE_CHAR ){ p2++; goto _RESCAN_TAIL; } parsePacket(ctx,p1,p2); ctx->recv_size -=p2-p1+1; if( ctx->recv_size ){ memmove(ctx->recv_buff,p2+1,ctx->recv_size); goto _RESCAN; } } } }
/* debug */ #ifdef _DEBUGX void tx(unsigned char * data,int len); void notifier(struct btsc_Packet* packet); /*初始化上下文, tx=发送处理函数,notifier=接收函数*/ struct btsc_Context c={tx:tx,notifier:notifier};
/*测试数据接收并解析*/ void rx(){ char * msg="<MSG=HELLO,NAME=SCOTT>" "<MSG2=HELLO2,NAME2=SCOTT2>" "<MSG3=HELLO3,NAME3=SCOTT3>"; /*simulating data*/ int len = strlen(msg); btsc_Parse(&c,msg,len); } /*发送处理过程*/ void tx(unsigned char * buff,int len){ char *outmsg = malloc(1024*10); memset(outmsg,0,1024*10); memcpy(outmsg,buff,len); printf("encode str: %s\n",outmsg); free(outmsg); btsc_Parse(&c,buff,len); }
void notifier(struct btsc_Packet* packet){ struct btsc_Property * ppt; ppt = btsc_Property_Get(packet,"MSG"); if(ppt) printf("property get: MSG=>%s\n",ppt->value); /*遍历包内属性参数*/ BTSC_FOREACH(packet,ppt); printf("packet: %s=>%s\n",ppt->name,ppt->value); BTSC_END_FOREACH(); }
int main(){ int r; /*optional*/ c.recv_cached_capacity = 1024; /*初始化接收缓冲区大小 byte*/ c.packet_cached_size = 5; /*消息包缓冲属性个数*/ btsc_init(&c); /*上下文初始化*/ puts("test rx()..."); rx(); /*接*/ puts("escape testing..."); do{ /*构造消息包,并完成发送*/ BTSC_PACKET_BEGIN(&c); BTSC_NEW_PROPERTY("MSG","calling");
BTSC_PACKET_END(); usleep(1000*50); printf(">>seq:%d\n",r); }while(0); btsc_cleanup(&c); return 0; }
#endif
|