#
在移植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
|