
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;
}