same - 云代码空间
——
/** 1.使用PJSIP函数创建XML结构树,保存进文件和从文件加载到链表 2.需要PJ_SIP开发库 */ /* <RecordData> <Log> <record Name="aaa" Number="123" Account="0" StartTime="1234567890" EndTime="0" Type="1" ViewFlag="1"/> <record Name="bbb" Number="456" Account="0" StartTime="1234569890" EndTime="1234569999" Type="0" ViewFlag="0"/> </Log> </RecordData> */ //XML Record static const pj_str_t STR_RECORDDATA = {"RecordData", 10}; static const pj_str_t STR_LOG = {"Log", 3}; static const pj_str_t STR_RECORD = {"record", 6}; static const pj_str_t STR_NAME = { "Name", 4}; static const pj_str_t STR_NUMBER = { "Number", 6}; static const pj_str_t STR_STARTTIME = { "StartTime", 9}; static const pj_str_t STR_ENDTIME = { "EndTime", 7}; static const pj_str_t STR_ACCOUNT = { "Account", 7}; static const pj_str_t STR_TYPE = { "Type", 4}; static const pj_str_t STR_VIEWFLAG = {"ViewFlag", 8}; typedef struct st_recorde_node { //创建双向链表 struct st_recorde_node *prev; struct st_recorde_node *next; char acName[MAX_DISP_NAME_LEN]; char acNumber[MAX_NUMBER_LEN]; unsigned short usAntNo; time_t stStartTime; time_t stEndTime; CALL_TYPE enType; unsigned short usViewFlag; } ST_RECORD_NODE; static ST_RECORD_NODE gastRecordData[MAX_CALLLOG_NUM + MAX_LINE_NUMBER]; ST_RECORD_NODE gstRecordsHead = {0}; void CL_Record2XML(pj_pool_t *pool, pj_xml_node *parent) { ST_RECORD_NODE *p, stTemp; pj_xml_node *node; pj_xml_attr *attr; pj_str_t value; if (!pool || !parent) { LOG(LOG_LEVEL_ERROR, (THIS_FILE, "Invalid parent node")); return; } p = &gstRecordsHead; if (p == p->next) return; do { p = p->next; memset(&stTemp, 0, sizeof(ST_RECORD_NODE)); memcpy(&stTemp, p, sizeof(ST_RECORD_NODE)); node = pj_xml_node_new(pool, &STR_RECORD); /*Attr 属性*/ value.ptr = stTemp.acName; value.slen = strlen(value.ptr); attr = pj_xml_attr_new(pool, &STR_NAME, &value); pj_xml_add_attr(node, attr); value.ptr = stTemp.acNumber; value.slen = strlen(value.ptr); attr = pj_xml_attr_new(pool, &STR_NUMBER, &value); pj_xml_add_attr(node, attr); if (MAX_ACCOUNT_NUMBER > stTemp.usAntNo) { sprintf(value.ptr, "%hu", stTemp.usAntNo + 1); } else { sprintf(value.ptr, "%hu", 0); } value.slen = strlen(value.ptr); attr = pj_xml_attr_new(pool, &STR_ACCOUNT, &value); pj_xml_add_attr(node, attr); sprintf(value.ptr, "%ld", stTemp.stStartTime); value.slen = strlen(value.ptr); attr = pj_xml_attr_new(pool, &STR_STARTTIME, &value); pj_xml_add_attr(node, attr); sprintf(value.ptr, "%ld", stTemp.stEndTime); value.slen = strlen(value.ptr); attr = pj_xml_attr_new(pool, &STR_ENDTIME, &value); pj_xml_add_attr(node, attr); sprintf(value.ptr, "%d", stTemp.enType); value.slen = strlen(value.ptr); attr = pj_xml_attr_new(pool, &STR_TYPE, &value); pj_xml_add_attr(node, attr); sprintf(value.ptr, "%d", stTemp.usViewFlag); value.slen = strlen(value.ptr); attr = pj_xml_attr_new(pool, &STR_VIEWFLAG, &value); pj_xml_add_attr(node, attr); pj_xml_add_node(parent, node); }while (p->next != &gstRecordsHead); } int CL_SaveToXML() { pj_status_t status; pj_oshandle_t xml_file = NULL; pj_xml_node *recorddata, *Log; pj_pool_t *pool = NULL; char buff[BUFLEN_1M] = {0}; //创建内存池 pool = pjsua_pool_create("XMLHISTORY", BUFLEN_1M, BUFLEN_1M); //打开文件 status = pj_file_open(pool, CL_RECORD_FILE, PJ_O_WRONLY, &xml_file); if (status != PJ_SUCCESS) { LOG(LOG_LEVEL_ERROR, (THIS_FILE, "Error creating "LOCAL_XML_DIRECTORY" file")); return FALSE; } /* 建立主结点 */ recorddata = pj_xml_node_new(pool, &STR_RECORDDATA); //添加1个子节点 Log = pj_xml_node_new(pool, &STR_LOG); pj_xml_add_node(recorddata, Log); /* 添加呼叫记录到Log节点树下*/ CL_Record2XML(pool, Log); pj_xml_print(recorddata, buff, BUFLEN_1M, PJ_FALSE); pj_ssize_t size = strlen(buff); if (BUFLEN_1M > size) { pj_file_write(xml_file, buff, &size); } else { LOG(LOG_LEVEL_ERROR, (THIS_FILE, "File "LOCAL_XML_DIRECTORY" is too large!")); } pj_file_close(xml_file); pj_pool_release(pool); return TRUE; } void CL_XML2Record(pj_xml_node *parent) { int strlen; pj_xml_attr *attr; char acStr[12] = {0}; ST_RECORD_NODE *pstHead, *p, *pstNew, stTempNode; pj_xml_node *node; if (!parent) { LOG(LOG_LEVEL_ERROR, (THIS_FILE, "Invalid parent node")); return; } node = pj_xml_find_node(parent, &STR_RECORD); while (NULL != node) { memset(&stTempNode, 0, sizeof(ST_RECORD_NODE)); attr = pj_xml_find_attr(node, &STR_NAME, NULL); if (attr) { strlen = (attr->value.slen > BUFLEN_32) ? BUFLEN_32 - 1 : attr->value.slen; memcpy(stTempNode.acName, attr->value.ptr, strlen); } attr = pj_xml_find_attr(node, &STR_NUMBER, NULL); if (attr) { strlen = (attr->value.slen > BUFLEN_32) ? BUFLEN_32 - 1 : attr->value.slen; memcpy(stTempNode.acNumber, attr->value.ptr, strlen); } attr = pj_xml_find_attr(node, &STR_ACCOUNT, NULL); if (attr) { strlen = (attr->value.slen > 8) ? 7 : attr->value.slen; memset(acStr, 0, sizeof(acStr)); memcpy(acStr, attr->value.ptr, strlen); stTempNode.usAntNo = (unsigned short)(atoi(acStr) - 1); } attr = pj_xml_find_attr(node, &STR_STARTTIME, NULL); if (attr) { strlen = (attr->value.slen > 12) ? 10 : attr->value.slen; memset(acStr, 0, sizeof(acStr)); memcpy(acStr, attr->value.ptr, strlen); stTempNode.stStartTime = atol(acStr); } attr = pj_xml_find_attr(node, &STR_ENDTIME, NULL); if (attr) { strlen = (attr->value.slen > 12) ? 10 : attr->value.slen; memset(acStr, 0, sizeof(acStr)); memcpy(acStr, attr->value.ptr, strlen); stTempNode.stEndTime = atol(acStr); } attr = pj_xml_find_attr(node, &STR_TYPE, NULL); if (attr) { strlen = (attr->value.slen > 8) ? 7 : attr->value.slen; memset(acStr, 0, sizeof(acStr)); memcpy(acStr, attr->value.ptr, strlen); stTempNode.enType = atoi(acStr); } attr = pj_xml_find_attr(node, &STR_VIEWFLAG, NULL); if (attr) { strlen = (attr->value.slen > 8) ? 7 : attr->value.slen; memset(acStr, 0, sizeof(acStr)); memcpy(acStr, attr->value.ptr, strlen); stTempNode.usViewFlag = atoi(acStr); } //按类型判断添加进链表 pstNew = CL_RecordMalloc(); if (NULL == pstNew) { LOG(LOG_LEVEL_WARNING, (THIS_FILE, "List Is Full!")); return; } pstHead = &gstRecordsHead; p = pstHead; while (p->next != pstHead) { p = p->next; } memcpy(pstNew, &stTempNode, sizeof(ST_RECORD_NODE)); //如果该类型达到最大数量就跳过不添加进去 if (CALLLOG_NUM > CL_CountFromType(pstNew->enType)) { p->next = pstNew; pstNew->prev = p; pstNew->next = pstHead; pstHead->prev = pstNew; } node = pj_xml_find_next_node(parent, node, &STR_RECORD); } } int CL_StringToList(char *msg, size_t len) { pj_xml_node *recorddata, *node; pj_pool_t *pool = NULL; if (!msg || !len) { return FALSE; } pool = pjsua_pool_create("StrToList", BUFLEN_2K, BUFLEN_2K); if (!pool) { return FALSE; } /* Parse XML */ recorddata = pj_xml_parse(pool, msg, len); if (!recorddata) { LOG(LOG_LEVEL_ERROR, (THIS_FILE, "recorddata ERROR!\n")); return FALSE; } /* Root document must be "ContactData" */ if (pj_stricmp(&recorddata->name, &STR_RECORDDATA) != 0) { LOG(LOG_LEVEL_ERROR, (THIS_FILE, "recorddata Name ERROR!\n")); return FALSE; } /*Log结点*/ node = pj_xml_find_node(recorddata, &STR_LOG); if (node) { CL_XML2Record(node); } pj_pool_release(pool); return TRUE; //return PB_SaveToXML(); } int CL_LoadXMLFile2List(char *file) { pj_status_t status; pj_oshandle_t xml_file = NULL; pj_off_t xml_file_len; pj_pool_t *pool = NULL; if (!file) { LOG(LOG_LEVEL_ERROR, (THIS_FILE, "Invalid File")); return FALSE; } pool = pjsua_pool_create("XMLHISTORY", BUFLEN_2K, BUFLEN_2K); status = pj_file_open(pool, file, PJ_O_RDONLY, &xml_file); if (status != PJ_SUCCESS) { LOG(LOG_LEVEL_ERROR, (THIS_FILE, "Error Open PhoneBook XML file", status)); return FALSE; } pj_file_setpos(xml_file, 0, PJ_SEEK_END); pj_file_getpos(xml_file, &xml_file_len); pj_file_setpos(xml_file, 0, PJ_SEEK_SET); pj_str_t msg; msg.ptr = (char *)pj_pool_alloc(pool, xml_file_len); msg.slen = xml_file_len; status = pj_file_read(xml_file, msg.ptr, &msg.slen); if (status != PJ_SUCCESS) { return FALSE; } pj_file_close(xml_file); status = CL_StringToList(msg.ptr, msg.slen); pj_pool_release(pool); return status; }