Commit 69ee81f39f940c6f12def7ba798b63dceab25352

Authored by Hu Chunming
1 parent 16819232

提交websocket client完整版功能代码

src/ai_platform/MultiSourceProcess.cpp
@@ -22,7 +22,7 @@ @@ -22,7 +22,7 @@
22 22
23 #include "../util/vpc_util.h" 23 #include "../util/vpc_util.h"
24 24
25 -#include "../decoder/gb28181/sip/SipServer.h" 25 +#include "../decoder/gb28181/websocket/WebsocketClient.h"
26 26
27 // #define VEHICLE_MULTI_BOXES 27 // #define VEHICLE_MULTI_BOXES
28 28
@@ -90,17 +90,17 @@ int CMultiSourceProcess::InitAlgorthim(tsl_aiplatform_param vptParam){ @@ -90,17 +90,17 @@ int CMultiSourceProcess::InitAlgorthim(tsl_aiplatform_param vptParam){
90 set_default_logger(LogLevel(vptParam.log_level), "multi_source_process", vptParam.log_path, vptParam.log_mem, vptParam.log_mem); 90 set_default_logger(LogLevel(vptParam.log_level), "multi_source_process", vptParam.log_path, vptParam.log_mem, vptParam.log_mem);
91 LOG_INFO("编译时间:{} {}", __DATE__, __TIME__); 91 LOG_INFO("编译时间:{} {}", __DATE__, __TIME__);
92 92
93 -// #ifdef USE_VILLAGE  
94 -// if (!CheckTime()) { //时间限制  
95 -// LOG_ERROR("sy_licence_check failed.");  
96 -// return AUTHOR_ERROR;  
97 -// }  
98 -// #else  
99 -// if (!CheckLabel(vptParam.gpuid)) { //机器授权  
100 -// LOG_ERROR("CheckLabel failed.");  
101 -// return AUTHOR_ERROR;  
102 -// }  
103 -// #endif 93 +#ifdef USE_VILLAGE
  94 + if (!CheckTime()) { //时间限制
  95 + LOG_ERROR("sy_licence_check failed.");
  96 + return AUTHOR_ERROR;
  97 + }
  98 +#else
  99 + if (!CheckLabel(vptParam.gpuid)) { //机器授权
  100 + LOG_ERROR("CheckLabel failed.");
  101 + return AUTHOR_ERROR;
  102 + }
  103 +#endif
104 104
105 SourceSingleton::getInstance(); 105 SourceSingleton::getInstance();
106 106
@@ -216,7 +216,15 @@ int CMultiSourceProcess::InitAlgorthim(tsl_aiplatform_param vptParam){ @@ -216,7 +216,15 @@ int CMultiSourceProcess::InitAlgorthim(tsl_aiplatform_param vptParam){
216 } 216 }
217 #endif 217 #endif
218 218
  219 + // 初始化ws
  220 + WebsocketClient* pServer = WebsocketClient::getInstance();
  221 + if(pServer->init() != 0) {
  222 + LOG_ERROR("websocket client 初始化失败 !");
  223 + return -1;
  224 + }
  225 +
219 m_task_param_manager = task_param_manager::getInstance(); 226 m_task_param_manager = task_param_manager::getInstance();
  227 +
220 m_snapshot_reprocessing = new snapshot_reprocessing(m_devId); 228 m_snapshot_reprocessing = new snapshot_reprocessing(m_devId);
221 m_save_snapshot_reprocessing = new save_snapshot_reprocessing(m_devId); 229 m_save_snapshot_reprocessing = new save_snapshot_reprocessing(m_devId);
222 230
@@ -227,10 +235,6 @@ int CMultiSourceProcess::InitAlgorthim(tsl_aiplatform_param vptParam){ @@ -227,10 +235,6 @@ int CMultiSourceProcess::InitAlgorthim(tsl_aiplatform_param vptParam){
227 VPCUtil* pVpcUtil = VPCUtil::getInstance(); 235 VPCUtil* pVpcUtil = VPCUtil::getInstance();
228 pVpcUtil->init(m_devId); 236 pVpcUtil->init(m_devId);
229 237
230 - // 初始化SIP服务器  
231 - SipServer* pSipServer = SipServer::getInstance();  
232 - pSipServer->Init(nullptr);  
233 -  
234 m_pAlgorthimThread = new thread([](void* arg) { 238 m_pAlgorthimThread = new thread([](void* arg) {
235 CMultiSourceProcess* process = (CMultiSourceProcess*)arg ; 239 CMultiSourceProcess* process = (CMultiSourceProcess*)arg ;
236 process->algorthim_process_thread(); 240 process->algorthim_process_thread();
@@ -694,21 +698,21 @@ int CMultiSourceProcess::algorthim_process_thread(){ @@ -694,21 +698,21 @@ int CMultiSourceProcess::algorthim_process_thread(){
694 ACL_CALL(aclrtCreateContext(&ctx, m_devId), ACL_SUCCESS, 1); 698 ACL_CALL(aclrtCreateContext(&ctx, m_devId), ACL_SUCCESS, 1);
695 699
696 while (true){ 700 while (true){
697 -// #ifdef USE_VILLAGE  
698 -// if (!CheckTime()) { //时间限制  
699 -// LOG_FATAL("authority failed!");  
700 -// break;  
701 -// }  
702 -// #else  
703 -// if (check_label == -1) { //机器授权  
704 -// LOG_FATAL("authority failed!");  
705 -// break;  
706 -// }  
707 -// if (!UpdateLabel()) {  
708 -// LOG_FATAL("authority failed!");  
709 -// break;  
710 -// }  
711 -// #endif 701 +#ifdef USE_VILLAGE
  702 + if (!CheckTime()) { //时间限制
  703 + LOG_FATAL("authority failed!");
  704 + break;
  705 + }
  706 +#else
  707 + if (check_label == -1) { //机器授权
  708 + LOG_FATAL("authority failed!");
  709 + break;
  710 + }
  711 + if (!UpdateLabel()) {
  712 + LOG_FATAL("authority failed!");
  713 + break;
  714 + }
  715 +#endif
712 if(m_bfinish){ 716 if(m_bfinish){
713 break; 717 break;
714 } 718 }
@@ -731,7 +735,7 @@ int CMultiSourceProcess::algorthim_process_thread(){ @@ -731,7 +735,7 @@ int CMultiSourceProcess::algorthim_process_thread(){
731 if (algor_map != nullptr) { 735 if (algor_map != nullptr) {
732 int input_image_width = gpuMem->getWidth(); 736 int input_image_width = gpuMem->getWidth();
733 int input_image_height = gpuMem->getHeight(); 737 int input_image_height = gpuMem->getHeight();
734 - LOG_INFO("task_id: {} width: {} height:{}", task_id, input_image_width, input_image_height); 738 + // LOG_DEBUG("task_id: {} width: {} height:{}", task_id, input_image_width, input_image_height);
735 739
736 /* 如果开启了行人 机动车非法闯入功能 生成闯入区域mask */ 740 /* 如果开启了行人 机动车非法闯入功能 生成闯入区域mask */
737 if (algor_map->find(algorithm_type_t::PEDESTRIAN_TRESPASS) != algor_map->end()) { 741 if (algor_map->find(algorithm_type_t::PEDESTRIAN_TRESPASS) != algor_map->end()) {
@@ -771,11 +775,36 @@ int CMultiSourceProcess::algorthim_process_thread(){ @@ -771,11 +775,36 @@ int CMultiSourceProcess::algorthim_process_thread(){
771 algorthim_vpt(vec_gpuMem); 775 algorthim_vpt(vec_gpuMem);
772 auto vptprocess2 = std::chrono::system_clock::now(); 776 auto vptprocess2 = std::chrono::system_clock::now();
773 auto vptprocess_time = std::chrono::duration_cast<std::chrono::milliseconds>(vptprocess2 - vptprocess1).count(); 777 auto vptprocess_time = std::chrono::duration_cast<std::chrono::milliseconds>(vptprocess2 - vptprocess1).count();
774 - LOG_INFO("Process per frame cost time: {} ms fps: {}", vptprocess_time/vec_gpuMem.size(), 1000/(vptprocess_time/vec_gpuMem.size())); 778 + // LOG_INFO("Process per frame cost time: {} ms fps: {}", vptprocess_time/vec_gpuMem.size(), 1000/(vptprocess_time/vec_gpuMem.size()));
775 779
776 #ifdef WITH_FACE_DET_SS 780 #ifdef WITH_FACE_DET_SS
777 algorthim_face_detect(vec_gpuMem); 781 algorthim_face_detect(vec_gpuMem);
778 #endif 782 #endif
  783 +
  784 +
  785 + // static int index = 0;
  786 + // index++;
  787 +
  788 + // DeviceMemory* mem = vec_gpuMem[0];
  789 + // if(index % 100 == 0){
  790 + // string task_id = mem->getId();
  791 +
  792 + // string video_file_name = "/home/cmhu/vpt_ascend_arm/bin/res/video_recode/";
  793 + // video_file_name += task_id + "_" + std::to_string(mem->getFrameNb()) + ".mp4";
  794 +
  795 + // RecoderInfo recoderInfo;
  796 + // recoderInfo.task_id = task_id;
  797 + // recoderInfo.object_id = std::to_string(index);
  798 + // recoderInfo.recoderPath = video_file_name;
  799 + // recoderInfo.frame_nb = mem->getFrameNb();
  800 + // recoderInfo.mq_info = task_id + "_" + std::to_string(mem->getFrameNb());
  801 +
  802 + // m_recoderinfo_queue_mtx.lock();
  803 + // m_recoderinfo_queue.push_back(recoderInfo);
  804 + // m_recoderinfo_queue_mtx.unlock();
  805 + // }
  806 +
  807 +
779 // auto record_t2 = std::chrono::system_clock::now(); 808 // auto record_t2 = std::chrono::system_clock::now();
780 // auto record_time = std::chrono::duration_cast<std::chrono::milliseconds>(record_t2 - record_t1).count(); 809 // auto record_time = std::chrono::duration_cast<std::chrono::milliseconds>(record_t2 - record_t1).count();
781 // LOG_INFO("Record per frame cost time: {} ms fps: {}", record_time/vec_gpuMem.size(), 1000/(record_time/vec_gpuMem.size())); 810 // LOG_INFO("Record per frame cost time: {} ms fps: {}", record_time/vec_gpuMem.size(), 1000/(record_time/vec_gpuMem.size()));
@@ -2179,7 +2208,7 @@ bool CMultiSourceProcess::CheckTime() { @@ -2179,7 +2208,7 @@ bool CMultiSourceProcess::CheckTime() {
2179 nYear = info->tm_year + 1900; 2208 nYear = info->tm_year + 1900;
2180 nMonth = info->tm_mon + 1; 2209 nMonth = info->tm_mon + 1;
2181 nDay = info->tm_mday; 2210 nDay = info->tm_mday;
2182 - if ((nYear == 2023 && nMonth <= 12) || (nYear == 2024 && nMonth <= 2)) 2211 + if ((nYear == 2023 && nMonth <= 12) || (nYear == 2024 && nMonth <= 7))
2183 { 2212 {
2184 return true; 2213 return true;
2185 } 2214 }
src/ai_platform/header.h
@@ -589,6 +589,7 @@ typedef struct rabbitmq_conn_params_t @@ -589,6 +589,7 @@ typedef struct rabbitmq_conn_params_t
589 #define __TSL_AIPLATFORM_PARAM__ 589 #define __TSL_AIPLATFORM_PARAM__
590 typedef struct tsl_aiplatform_param { 590 typedef struct tsl_aiplatform_param {
591 int gpuid; //指定显卡id 591 int gpuid; //指定显卡id
  592 + int sip_server_port; // sip服务端端口
592 char *trt_serialize_file; //缓存文件保存路径 593 char *trt_serialize_file; //缓存文件保存路径
593 char *models_dir; // 模型文件目录 594 char *models_dir; // 模型文件目录
594 595
src/decoder/dvpp/DvppDecoder.cpp
@@ -484,7 +484,11 @@ void DvppDecoder::read_thread() { @@ -484,7 +484,11 @@ void DvppDecoder::read_thread() {
484 484
485 do { 485 do {
486 CHECK_AND_BREAK(aclrtSetDevice(m_dvpp_deviceId), "aclrtSetDevice failed"); 486 CHECK_AND_BREAK(aclrtSetDevice(m_dvpp_deviceId), "aclrtSetDevice failed");
487 - CHECK_AND_BREAK(aclrtCreateContext(&ctx, m_dvpp_deviceId), "aclrtCreateContext failed"); 487 + int ret = aclrtSetCurrentContext(m_context);
  488 + if(ret != ACL_ERROR_NONE){
  489 + LOG_ERROR("[{}]- aclrtSetCurrentContext failed", m_dec_name);
  490 + break;
  491 + }
488 492
489 vdecChannelDesc = aclvdecCreateChannelDesc(); 493 vdecChannelDesc = aclvdecCreateChannelDesc();
490 if (vdecChannelDesc == nullptr) { 494 if (vdecChannelDesc == nullptr) {
@@ -528,6 +532,8 @@ void DvppDecoder::read_thread() { @@ -528,6 +532,8 @@ void DvppDecoder::read_thread() {
528 } 532 }
529 } 533 }
530 534
  535 + // LOG_DEBUG("[{}]- read in", m_dec_name);
  536 +
531 int result = av_read_frame(fmt_ctx, pkt); 537 int result = av_read_frame(fmt_ctx, pkt);
532 if (result == AVERROR_EOF || result < 0){ 538 if (result == AVERROR_EOF || result < 0){
533 av_packet_unref(pkt); 539 av_packet_unref(pkt);
@@ -535,6 +541,8 @@ void DvppDecoder::read_thread() { @@ -535,6 +541,8 @@ void DvppDecoder::read_thread() {
535 break; 541 break;
536 } 542 }
537 543
  544 + // LOG_DEBUG("[{}]- read out", m_dec_name);
  545 +
538 if (m_bReal && m_DvppCacheCounter.load() > 20){ 546 if (m_bReal && m_DvppCacheCounter.load() > 20){
539 // 解码器解码不过来。实时流在此处的处理会导致花屏,这是由于解码器性能问题导致,无法避免 547 // 解码器解码不过来。实时流在此处的处理会导致花屏,这是由于解码器性能问题导致,无法避免
540 // 实时流在这里处理是为了避免长时间不读取数据导致数据中断 548 // 实时流在这里处理是为了避免长时间不读取数据导致数据中断
@@ -549,6 +557,8 @@ void DvppDecoder::read_thread() { @@ -549,6 +557,8 @@ void DvppDecoder::read_thread() {
549 557
550 if (video_index == pkt->stream_index){ 558 if (video_index == pkt->stream_index){
551 559
  560 + LOG_DEBUG("[{}]- av_bsf_send_packet", m_dec_name);
  561 +
552 ret = av_bsf_send_packet(h264bsfc, pkt); 562 ret = av_bsf_send_packet(h264bsfc, pkt);
553 if(ret < 0) { 563 if(ret < 0) {
554 LOG_ERROR("[{}]- av_bsf_send_packet error!", m_dec_name); 564 LOG_ERROR("[{}]- av_bsf_send_packet error!", m_dec_name);
@@ -565,7 +575,7 @@ void DvppDecoder::read_thread() { @@ -565,7 +575,7 @@ void DvppDecoder::read_thread() {
565 575
566 frame_nb++; 576 frame_nb++;
567 #ifdef USE_VILLAGE 577 #ifdef USE_VILLAGE
568 - m_recoderManager.cache_pkt(pkt, frame_nb); 578 + m_recoderManager.cache_pkt(pkt, frame_nb, m_dec_name);
569 #endif 579 #endif
570 nSended = sendPkt(vdecChannelDesc, pkt, frame_nb); 580 nSended = sendPkt(vdecChannelDesc, pkt, frame_nb);
571 581
@@ -595,25 +605,31 @@ void DvppDecoder::read_thread() { @@ -595,25 +605,31 @@ void DvppDecoder::read_thread() {
595 605
596 } while (0); 606 } while (0);
597 607
  608 + LOG_DEBUG("[{}]- 1", m_dec_name);
  609 +
598 if (vdecChannelDesc) { 610 if (vdecChannelDesc) {
599 CHECK_NOT_RETURN(aclvdecDestroyChannel(vdecChannelDesc), "aclvdecDestroyChannel failed"); 611 CHECK_NOT_RETURN(aclvdecDestroyChannel(vdecChannelDesc), "aclvdecDestroyChannel failed");
600 CHECK_NOT_RETURN(aclvdecDestroyChannelDesc(vdecChannelDesc), "aclvdecDestroyChannelDesc failed"); 612 CHECK_NOT_RETURN(aclvdecDestroyChannelDesc(vdecChannelDesc), "aclvdecDestroyChannelDesc failed");
601 vdecChannelDesc = nullptr; 613 vdecChannelDesc = nullptr;
602 } 614 }
603 615
  616 + LOG_DEBUG("[{}]- 2", m_dec_name);
  617 +
604 m_bRunning=false; 618 m_bRunning=false;
605 619
606 m_bExitReportThd = true; 620 m_bExitReportThd = true;
607 CHECK_NOT_RETURN(pthread_join(report_thread, nullptr), "report_thread join failed"); 621 CHECK_NOT_RETURN(pthread_join(report_thread, nullptr), "report_thread join failed");
608 622
  623 + LOG_DEBUG("[{}]- 3", m_dec_name);
  624 +
609 m_bExitDisplayThd = true; 625 m_bExitDisplayThd = true;
610 display_thread.join(); 626 display_thread.join();
611 627
612 - if (ctx){  
613 - CHECK_NOT_RETURN(aclrtDestroyContext(ctx), "aclrtDestroyContext failed");  
614 - } 628 + LOG_DEBUG("[{}]- 4", m_dec_name);
615 629
616 m_recoderManager.close(); 630 m_recoderManager.close();
  631 +
  632 + LOG_DEBUG("[{}]- 5", m_dec_name);
617 633
618 release_ffmpeg(); 634 release_ffmpeg();
619 release_dvpp(); 635 release_dvpp();
src/decoder/dvpp/DvppStreamDecoder.cpp
@@ -401,7 +401,7 @@ int DvppStreamDecoder::SendData(int videoType, char* data, int len, int isKey, u @@ -401,7 +401,7 @@ int DvppStreamDecoder::SendData(int videoType, char* data, int len, int isKey, u
401 return -3; 401 return -3;
402 } 402 }
403 403
404 - int ret = aclrtSetCurrentContext(m_context); 404 + int ret = aclrtSetCurrentContext(m_context);
405 if(ret != ACL_ERROR_NONE){ 405 if(ret != ACL_ERROR_NONE){
406 LOG_ERROR("[{}]- aclrtSetCurrentContext failed", m_dec_name); 406 LOG_ERROR("[{}]- aclrtSetCurrentContext failed", m_dec_name);
407 return -2; 407 return -2;
@@ -480,7 +480,7 @@ int DvppStreamDecoder::SendData(int videoType, char* data, int len, int isKey, u @@ -480,7 +480,7 @@ int DvppStreamDecoder::SendData(int videoType, char* data, int len, int isKey, u
480 m_frame_nb++; 480 m_frame_nb++;
481 481
482 #ifdef USE_VILLAGE 482 #ifdef USE_VILLAGE
483 - m_recoderManager.cache_pkt(pkt, m_frame_nb); 483 + m_recoderManager.cache_pkt(pkt, m_frame_nb, m_dec_name);
484 #endif 484 #endif
485 485
486 // dvpp 解码 486 // dvpp 解码
@@ -636,8 +636,16 @@ void DvppStreamDecoder::release_channeldesc() { @@ -636,8 +636,16 @@ void DvppStreamDecoder::release_channeldesc() {
636 void DvppStreamDecoder::Close() { 636 void DvppStreamDecoder::Close() {
637 m_bExit = true; 637 m_bExit = true;
638 638
639 - release_channeldesc();  
640 - release_dvpp(); 639 + if (m_context) {
  640 + int ret = aclrtSetCurrentContext(m_context);
  641 + if(ret != ACL_ERROR_NONE){
  642 + LOG_ERROR("[{}]- aclrtSetCurrentContext failed", m_dec_name);
  643 + return;
  644 + }
  645 +
  646 + release_channeldesc();
  647 + release_dvpp();
  648 + }
641 649
642 if(h264bsfc){ 650 if(h264bsfc){
643 av_bsf_free(&h264bsfc); 651 av_bsf_free(&h264bsfc);
@@ -648,6 +656,7 @@ void DvppStreamDecoder::Close() { @@ -648,6 +656,7 @@ void DvppStreamDecoder::Close() {
648 656
649 if(decode_finished_cbk) { 657 if(decode_finished_cbk) {
650 decode_finished_cbk(m_finishedDecArg); 658 decode_finished_cbk(m_finishedDecArg);
  659 + decode_finished_cbk = nullptr;
651 } 660 }
652 } 661 }
653 662
src/decoder/dvpp/FFRecoderTaskManager.cpp
@@ -44,29 +44,6 @@ FFRecoderTaskManager::~FFRecoderTaskManager(){ @@ -44,29 +44,6 @@ FFRecoderTaskManager::~FFRecoderTaskManager(){
44 LOG_DEBUG("~FFRecoderTaskManager()"); 44 LOG_DEBUG("~FFRecoderTaskManager()");
45 } 45 }
46 46
47 -bool FFRecoderTaskManager::init(AVStream* stream, AVCodecContext* avctx){  
48 - if(stream == nullptr || avctx == nullptr) {  
49 - return false;  
50 - }  
51 -  
52 - m_time_base = stream->time_base;  
53 - m_avctx = avctx;  
54 - m_inStream = stream;  
55 -  
56 - m_recoder_thread = new std::thread(  
57 - [](void* arg) {  
58 - FFRecoderTaskManager* _this=(FFRecoderTaskManager*)arg;  
59 - if(_this != nullptr) {  
60 - _this->recode_thread();  
61 - }else{  
62 - LOG_ERROR("recode 线程启动失败 !");  
63 - }  
64 - return (void*)0;  
65 - }, this);  
66 -  
67 - return true;  
68 -}  
69 -  
70 bool FFRecoderTaskManager::init2(int w, int h, int fps, int bit_rate) { 47 bool FFRecoderTaskManager::init2(int w, int h, int fps, int bit_rate) {
71 m_width = w; 48 m_width = w;
72 m_height = h; 49 m_height = h;
@@ -108,7 +85,7 @@ static AVPacket* packet_clone(AVPacket* pkt) { @@ -108,7 +85,7 @@ static AVPacket* packet_clone(AVPacket* pkt) {
108 return new_pkt; 85 return new_pkt;
109 } 86 }
110 87
111 -void FFRecoderTaskManager::cache_pkt(AVPacket* pkt, long long frame_nb){ 88 +void FFRecoderTaskManager::cache_pkt(AVPacket* pkt, long long frame_nb, string dec_name){
112 if(m_bExit) { 89 if(m_bExit) {
113 // 任务退出了就不再缓存数据了 90 // 任务退出了就不再缓存数据了
114 return; 91 return;
@@ -126,10 +103,17 @@ void FFRecoderTaskManager::cache_pkt(AVPacket* pkt, long long frame_nb){ @@ -126,10 +103,17 @@ void FFRecoderTaskManager::cache_pkt(AVPacket* pkt, long long frame_nb){
126 if(is_key_frame(pkt)){ 103 if(is_key_frame(pkt)){
127 // 越来越大的值 104 // 越来越大的值
128 newDataPkt->isKeyFrame = true; 105 newDataPkt->isKeyFrame = true;
129 - LOG_INFO("key frame_nb: {}", frame_nb); 106 + LOG_INFO("[{}] - key frame_nb: {}", dec_name, frame_nb);
130 } else { 107 } else {
131 newDataPkt->isKeyFrame = false; 108 newDataPkt->isKeyFrame = false;
132 } 109 }
  110 +
  111 + AVPacket* npkt = newDataPkt->pkt;
  112 + if(npkt == nullptr) {
  113 + return ;
  114 + } else if (npkt->data == nullptr || npkt->size <= 0){
  115 + return ;
  116 + }
133 117
134 std::lock_guard<std::mutex> l_info(m_pkt_list_short_mtx); 118 std::lock_guard<std::mutex> l_info(m_pkt_list_short_mtx);
135 m_pkt_list_short.push_back(newDataPkt); 119 m_pkt_list_short.push_back(newDataPkt);
@@ -154,7 +138,6 @@ void FFRecoderTaskManager::save_intask_recoderinfo(RecoderInfo info) { @@ -154,7 +138,6 @@ void FFRecoderTaskManager::save_intask_recoderinfo(RecoderInfo info) {
154 } 138 }
155 139
156 list<DataPacket*>::iterator FFRecoderTaskManager::getStartIterator(unsigned long long frame_nb){ 140 list<DataPacket*>::iterator FFRecoderTaskManager::getStartIterator(unsigned long long frame_nb){
157 - std::lock_guard<std::mutex> l(m_pkt_list_mtx);  
158 141
159 auto it_first = m_pkt_list.begin(); 142 auto it_first = m_pkt_list.begin();
160 143
@@ -185,101 +168,6 @@ void FFRecoderTaskManager::create_recode_task(RecoderInfo&amp; recoderInfo) { @@ -185,101 +168,6 @@ void FFRecoderTaskManager::create_recode_task(RecoderInfo&amp; recoderInfo) {
185 save_intask_recoderinfo(recoderInfo); 168 save_intask_recoderinfo(recoderInfo);
186 } 169 }
187 170
188 -void FFRecoderTaskManager::recode_thread() {  
189 - LOG_INFO("recode_thread start...");  
190 - while(true) {  
191 - if(m_bExit) {  
192 - break;  
193 - }  
194 -  
195 - m_recoderinfo_list_mtx.lock();  
196 - if(m_recoderinfo_list.size() <= 0){  
197 - m_recoderinfo_list_mtx.unlock();  
198 - std::this_thread::sleep_for(std::chrono::milliseconds(3));  
199 - continue;  
200 - }  
201 -  
202 - auto it_param = m_recoderinfo_list.begin();  
203 - RecoderInfo recoderinfo = *it_param;  
204 - m_recoderinfo_list_mtx.unlock();  
205 -  
206 - do  
207 - {  
208 - auto it_data = getStartIterator(recoderinfo.frame_nb);  
209 - if(it_data == m_pkt_list.end()) {  
210 - std::this_thread::sleep_for(std::chrono::milliseconds(3));  
211 - break;  
212 - }  
213 -  
214 - LOG_INFO("start frame_nb: {}", (*it_data)->frame_nb);  
215 -  
216 - m_pkt_list_mtx.lock();  
217 - auto it = m_pkt_list.begin();  
218 - while (it != it_data) {  
219 - DataPacket* dataPkt = m_pkt_list.front();  
220 - delete dataPkt;  
221 - dataPkt = nullptr;  
222 - m_pkt_list.pop_front();  
223 - it = m_pkt_list.begin();  
224 - }  
225 - m_pkt_list_mtx.unlock();  
226 -  
227 - string file_name = recoderinfo.recoderPath;  
228 -  
229 - FFRecoder ffrecoder;  
230 - bool bInit = ffrecoder.init(m_inStream, m_avctx, file_name.c_str());  
231 - if (!bInit) {  
232 - LOG_ERROR("ffrecoder init error : {} {} {}", recoderinfo.task_id, recoderinfo.object_id, recoderinfo.frame_nb);  
233 - ffrecoder.uninit();  
234 - break;  
235 - }  
236 - LOG_DEBUG("record start, pkt_list size: {} task_id: {} object_id:{} frame_nb: {}", m_pkt_list.size(), recoderinfo.task_id, recoderinfo.object_id, recoderinfo.frame_nb);  
237 -  
238 - int count = 0;  
239 - auto it_save = it_data;  
240 - unsigned long long start_frame_nb = (*it_data)->frame_nb;  
241 - unsigned long long end_frame_nb = (*it_data)->frame_nb;  
242 - for (; it_save != m_pkt_list.end() && count < 500; ++it_save) {  
243 - DataPacket* dataPkt = *it_save;  
244 - if(dataPkt->frame_nb > recoderinfo.frame_nb) {  
245 - break;  
246 - }  
247 - AVPacket* pkt = dataPkt->pkt;  
248 - if(pkt == nullptr) {  
249 - LOG_ERROR("{} pkt is nullptr", recoderinfo.task_id);  
250 - continue;  
251 - } else if (pkt->data == nullptr || pkt->size <= 0){  
252 - LOG_ERROR("{} pkt data is nullptr", recoderinfo.task_id);  
253 - continue;  
254 - }  
255 -  
256 - ffrecoder.write_pkt(pkt);  
257 - count++;  
258 - end_frame_nb = (*it_save)->frame_nb;  
259 - }  
260 -  
261 - ffrecoder.flush_pkt();  
262 - ffrecoder.uninit();  
263 -  
264 - // 发送mq消息  
265 - if(mq_publish_func && recoderinfo.mq_info.length() > 0) {  
266 - mq_publish_func(recoderinfo.mq_info.c_str());  
267 - // LOG_INFO("record save: {}", recoderinfo.mq_info.c_str());  
268 - }  
269 -  
270 - LOG_INFO("record end, total save: {} start_frame_nb: {} end_frame_nb: {} file_path: {}", count, start_frame_nb, end_frame_nb, file_name);  
271 - } while (0);  
272 -  
273 - // m_recoderinfo_list 为空会触发 m_pkt_list size 大于1000时的删除操作,  
274 - // 因此应当在本次m_pkt_list操作都完成之后再pop,避免这边在用m_pkt_list, 另一边在删除,从而导致崩溃  
275 - m_recoderinfo_list_mtx.lock();  
276 - m_recoderinfo_list.pop_front();  
277 - m_recoderinfo_list_mtx.unlock();  
278 - }  
279 -  
280 - LOG_INFO("recode_thread end.");  
281 -}  
282 -  
283 void FFRecoderTaskManager::pkt_cache_thread() { 171 void FFRecoderTaskManager::pkt_cache_thread() {
284 LOG_INFO("pkt_cache_thread start..."); 172 LOG_INFO("pkt_cache_thread start...");
285 173
@@ -311,7 +199,6 @@ void FFRecoderTaskManager::pkt_cache_thread() { @@ -311,7 +199,6 @@ void FFRecoderTaskManager::pkt_cache_thread() {
311 } 199 }
312 m_pkt_list_mtx.unlock(); 200 m_pkt_list_mtx.unlock();
313 m_pkt_list_short_mtx.unlock(); 201 m_pkt_list_short_mtx.unlock();
314 -  
315 202
316 std::lock_guard<std::mutex> l_info(m_recoderinfo_list_mtx); 203 std::lock_guard<std::mutex> l_info(m_recoderinfo_list_mtx);
317 if(m_recoderinfo_list.size() <= 0){ 204 if(m_recoderinfo_list.size() <= 0){
@@ -366,15 +253,25 @@ void FFRecoderTaskManager::recode_thread2() { @@ -366,15 +253,25 @@ void FFRecoderTaskManager::recode_thread2() {
366 253
367 do 254 do
368 { 255 {
  256 + std::lock_guard<std::mutex> l_long(m_pkt_list_mtx);
  257 +
369 auto it_data = getStartIterator(recoderinfo.frame_nb); 258 auto it_data = getStartIterator(recoderinfo.frame_nb);
370 if(it_data == m_pkt_list.end()) { 259 if(it_data == m_pkt_list.end()) {
  260 + LOG_WARN("待保存信息已无相关数据包");
371 std::this_thread::sleep_for(std::chrono::milliseconds(3)); 261 std::this_thread::sleep_for(std::chrono::milliseconds(3));
372 break; 262 break;
373 } 263 }
374 264
375 - LOG_INFO("start frame_nb: {}", (*it_data)->frame_nb); 265 + auto it = m_pkt_list.begin();
  266 + while (it != it_data) {
  267 + DataPacket* dataPkt = m_pkt_list.front();
  268 + delete dataPkt;
  269 + dataPkt = nullptr;
  270 + m_pkt_list.pop_front();
  271 + it = m_pkt_list.begin();
  272 + }
376 273
377 - std::lock_guard<std::mutex> l_long(m_pkt_list_mtx); 274 + LOG_INFO("start frame_nb: {}", (*it_data)->frame_nb);
378 275
379 string file_name = recoderinfo.recoderPath; 276 string file_name = recoderinfo.recoderPath;
380 277
src/decoder/dvpp/FFRecoderTaskManager.h
1 -#include "FFRecoder.h"  
2 #include "FFRecoder2.h" 1 #include "FFRecoder2.h"
3 2
4 #include "../../ai_platform/common_header.h" 3 #include "../../ai_platform/common_header.h"
@@ -26,9 +25,8 @@ public: @@ -26,9 +25,8 @@ public:
26 FFRecoderTaskManager(); 25 FFRecoderTaskManager();
27 virtual ~FFRecoderTaskManager(); 26 virtual ~FFRecoderTaskManager();
28 27
29 - void cache_pkt(AVPacket* pkt, long long frame_nb); 28 + void cache_pkt(AVPacket* pkt, long long frame_nb, string dec_name);
30 29
31 - bool init(AVStream* stream, AVCodecContext* avctx);  
32 bool init2(int w, int h, int fps, int bit_rate); 30 bool init2(int w, int h, int fps, int bit_rate);
33 void create_recode_task(RecoderInfo& recoderInfo); 31 void create_recode_task(RecoderInfo& recoderInfo);
34 32
@@ -37,7 +35,6 @@ public: @@ -37,7 +35,6 @@ public:
37 void set_mq_callback(mq_callback_t cb); 35 void set_mq_callback(mq_callback_t cb);
38 36
39 public: 37 public:
40 - void recode_thread();  
41 void recode_thread2(); 38 void recode_thread2();
42 void pkt_cache_thread(); 39 void pkt_cache_thread();
43 40
src/decoder/dvpp/depend_headers.h
@@ -46,6 +46,7 @@ struct DataPacket { @@ -46,6 +46,7 @@ struct DataPacket {
46 46
47 ~DataPacket(){ 47 ~DataPacket(){
48 if(pkt != nullptr) { 48 if(pkt != nullptr) {
  49 + // LOG_INFO("free frame_nb:{}", frame_nb);
49 av_packet_free(&pkt); 50 av_packet_free(&pkt);
50 pkt = nullptr; 51 pkt = nullptr;
51 } 52 }
src/decoder/gb28181/DvppGB28181Decoder.cpp
@@ -56,7 +56,8 @@ DvppGB28181Decoder::~DvppGB28181Decoder() @@ -56,7 +56,8 @@ DvppGB28181Decoder::~DvppGB28181Decoder()
56 } 56 }
57 57
58 void DvppGB28181Decoder::close(){ 58 void DvppGB28181Decoder::close(){
59 - if (m_status == ECLOSED || m_status == ECLOSING) return ; 59 +
  60 + if (m_status == ECLOSED) return;
60 61
61 m_status = ECLOSING; 62 m_status = ECLOSING;
62 63
@@ -76,6 +77,7 @@ void DvppGB28181Decoder::close(){ @@ -76,6 +77,7 @@ void DvppGB28181Decoder::close(){
76 77
77 if (m_post_decode_thread != 0) { 78 if (m_post_decode_thread != 0) {
78 pthread_join(m_post_decode_thread,0); 79 pthread_join(m_post_decode_thread,0);
  80 + m_post_decode_thread = 0;
79 } 81 }
80 82
81 streamDecoder.Close(); 83 streamDecoder.Close();
@@ -304,6 +306,8 @@ void DvppGB28181Decoder::stream_end_callback() @@ -304,6 +306,8 @@ void DvppGB28181Decoder::stream_end_callback()
304 { 306 {
305 LOG_INFO("[{}] - send_video_eof", m_dec_name); 307 LOG_INFO("[{}] - send_video_eof", m_dec_name);
306 308
  309 + m_status == ECLOSING;
  310 +
307 decode_finished_cbk(m_finishedDecArg); 311 decode_finished_cbk(m_finishedDecArg);
308 312
309 return; 313 return;
src/decoder/gb28181/common_header.h
@@ -4,5 +4,6 @@ @@ -4,5 +4,6 @@
4 4
5 #include "../interface/logger.hpp" 5 #include "../interface/logger.hpp"
6 #include "../interface/utiltools.hpp" 6 #include "../interface/utiltools.hpp"
  7 +#include "../../util/StringTools.hpp"
7 8
8 #endif 9 #endif
9 \ No newline at end of file 10 \ No newline at end of file
src/decoder/gb28181/main.cpp.28181 deleted
1 -//  
2 -// Created bxc on 2022/11/25.  
3 -//  
4 -  
5 -#include "./sip/SipServer.h"  
6 -#include "./rtp/RTPReceiver.h"  
7 -#include"./rtp/RTPTcpReceiver.h"  
8 -#include"./rtp/RTPUdpReceiver.h"  
9 -  
10 -#include <thread>  
11 -#include <chrono>  
12 -#include <iostream>  
13 -  
14 -  
15 -#ifdef __linux__  
16 -#include "arpa/inet.h"  
17 -#endif  
18 -  
19 -#include "common_header.h"  
20 -  
21 -  
22 -#define MIN_RTP_PORT 10000  
23 -#define MAX_RTP_PORT 60000  
24 -  
25 -  
26 -using namespace std;  
27 -  
28 -  
29 -static void RTP_Stream_CallBack(void* userdata, int videoType, char* data, int len, int isKey, uint64_t pts, uint64_t localPts)  
30 -{  
31 - LOG_INFO("len: {}", len);  
32 - // FFGB28181Decoder* decoder = (FFGB28181Decoder*)userdata;  
33 - // decoder->stream_callback(videoType, data, len, isKey, pts, localPts);  
34 -}  
35 -  
36 -static void RTP_Stream_End_CallBack(void* userdata)  
37 -{  
38 - LOG_INFO("finished.");  
39 - // FFGB28181Decoder* decoder = (FFGB28181Decoder*)userdata;  
40 - // decoder->stream_end_callback();  
41 -}  
42 -  
43 -bool RequestStream(const char* deviceId, int rtp_port);  
44 -  
45 -// ȡ MIN_RTP_PORT(10000)~MAX_RTP_PORT(60000)֮�������˿�(ż���������������˿ڿ���)  
46 -int allocRtpPort() {  
47 -  
48 - int s_rtpPort = MIN_RTP_PORT;  
49 -  
50 - srand((unsigned int)time(NULL));  
51 - s_rtpPort = MIN_RTP_PORT + (rand() % MIN_RTP_PORT);  
52 -  
53 - if (s_rtpPort % 2)  
54 - ++s_rtpPort;  
55 -  
56 - int count = 0;  
57 -  
58 - while (true)  
59 - {  
60 - if (s_rtpPort >= MAX_RTP_PORT) {  
61 - s_rtpPort = MIN_RTP_PORT;  
62 - count ++;  
63 - if (count > 1) {  
64 - printf("10000 到 60000 没有可用的port");  
65 - }  
66 - }  
67 -  
68 - int i = 0;  
69 - for (; i < 2; i++) {  
70 - sockaddr_in sRecvAddr;  
71 - int s = socket(AF_INET, SOCK_DGRAM, 0);  
72 -  
73 - sRecvAddr.sin_family = AF_INET;  
74 - sRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);  
75 - sRecvAddr.sin_port = htons(s_rtpPort + i);  
76 -  
77 - int nResult = bind(s, (sockaddr *)&sRecvAddr, sizeof(sRecvAddr));  
78 - if (nResult != 0) {  
79 - break;  
80 - }  
81 -  
82 - nResult = close(s);  
83 - if (nResult != 0) {  
84 - printf("closesocket failed : {}", nResult);  
85 - break;  
86 - }  
87 - }  
88 -  
89 - if (i == 2)  
90 - break;  
91 -  
92 - s_rtpPort += 2;  
93 - }  
94 -  
95 - return s_rtpPort;  
96 -}  
97 -  
98 -bool start_rtp(string deviceId, int m_port) {  
99 - RTPReceiver* m_rtpPtr = nullptr;  
100 - if(false){  
101 - m_rtpPtr = new RTPTcpReceiver();  
102 - }else{  
103 - m_rtpPtr = new RTPUdpReceiver();  
104 - }  
105 - if(nullptr == m_rtpPtr){  
106 - return false;  
107 - }  
108 -  
109 - m_rtpPtr->SetRequestStreamCallback(RequestStream);  
110 -  
111 -  
112 -  
113 - m_rtpPtr->SetOutputCallback(RTP_Stream_CallBack, nullptr);  
114 - m_rtpPtr->SetVodEndCallback(RTP_Stream_End_CallBack, nullptr);  
115 -  
116 -  
117 - bool bRet = m_rtpPtr->Open(deviceId);  
118 - if(bRet){  
119 - // pthread_create(&m_post_decode_thread,0,  
120 - // [](void* arg)  
121 - // {  
122 - // FFGB28181Decoder* a=(FFGB28181Decoder*)arg;  
123 - // a->post_decode_thread();  
124 - // return (void*)0;  
125 - // }  
126 - // ,this);  
127 - LOG_INFO("rtp open successed.");  
128 - }  
129 - return bRet;  
130 -}  
131 -  
132 -  
133 -bool RequestStream(const char* deviceId, int rtp_port) {  
134 - SipServer* pServer = SipServer::getInstance();  
135 - int ret = pServer->RequestInvite_UDP(deviceId, rtp_port);  
136 - if (ret > 0)  
137 - {  
138 - return true;  
139 - }  
140 -  
141 - return false;  
142 -}  
143 -  
144 -int main(int argc, char *argv[]) {  
145 -  
146 - if (argc <= 1)  
147 - {  
148 - printf("请输入待获取的摄像头的视频通道编码ID。");  
149 - return -1;  
150 - }  
151 -  
152 - SipServer* pServer = SipServer::getInstance();  
153 - pServer->Init(nullptr);  
154 -  
155 - // const char* sipid = "34020000001310000001";  
156 - const char* sipid = argv[1];  
157 - char oper = 'g';  
158 - while (oper != 'q') {  
159 - oper = getchar();  
160 - switch (oper)  
161 - {  
162 - case 'g':  
163 - break;  
164 - case 'i':  
165 - {  
166 - int rtp_port = allocRtpPort();  
167 - start_rtp(sipid, rtp_port);  
168 -  
169 - pServer->RequestInvite_UDP(sipid, rtp_port);  
170 - }  
171 - break;  
172 - case 'b':  
173 - break;  
174 - default:  
175 - break;  
176 - }  
177 - }  
178 -  
179 - return 0;  
180 -}  
181 \ No newline at end of file 0 \ No newline at end of file
src/decoder/gb28181/rtp/RTPReceiver.cpp
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 #include <thread> 3 #include <thread>
4 4
5 #include "../common_header.h" 5 #include "../common_header.h"
6 -#include "../sip/SipServer.h" 6 +#include "../websocket/WebsocketClient.h"
7 7
8 #ifdef __linux__ 8 #ifdef __linux__
9 #include "arpa/inet.h" 9 #include "arpa/inet.h"
@@ -52,6 +52,11 @@ RTPReceiver::~RTPReceiver(){ @@ -52,6 +52,11 @@ RTPReceiver::~RTPReceiver(){
52 if(recvTmpBuf != nullptr){ 52 if(recvTmpBuf != nullptr){
53 delete[] recvTmpBuf; 53 delete[] recvTmpBuf;
54 } 54 }
  55 +
  56 + WebsocketClient* pClient = WebsocketClient::getInstance();
  57 + if (pClient){
  58 + pClient->DeleteReceiverPair(m_SipChannelId, m_rtp_port);
  59 + }
55 } 60 }
56 61
57 void RTPReceiver::SetOutputCallback(CallBack_Stream cb, void* param) 62 void RTPReceiver::SetOutputCallback(CallBack_Stream cb, void* param)
@@ -79,7 +84,7 @@ int RTPReceiver::InitPS(){ @@ -79,7 +84,7 @@ int RTPReceiver::InitPS(){
79 return -1; 84 return -1;
80 } 85 }
81 86
82 - LOG_INFO("[{}] InitPS finished", m_SipChannelId); 87 + LOG_INFO("[{}] InitPS successed", m_SipChannelId);
83 88
84 return 0; 89 return 0;
85 } 90 }
@@ -310,7 +315,7 @@ int RTPReceiver::ParsePacket(RTPPacket* packet){ @@ -310,7 +315,7 @@ int RTPReceiver::ParsePacket(RTPPacket* packet){
310 315
311 int RTPReceiver::allocRtpPort() { 316 int RTPReceiver::allocRtpPort() {
312 317
313 - SipServer* pServer = SipServer::getInstance(); 318 + WebsocketClient* pServer = WebsocketClient::getInstance();
314 int MIN_RTP_PORT = pServer->GetMinRtpPort() ; 319 int MIN_RTP_PORT = pServer->GetMinRtpPort() ;
315 int MAX_RTP_PORT = pServer->GetMaxRtpPort(); 320 int MAX_RTP_PORT = pServer->GetMaxRtpPort();
316 321
@@ -330,7 +335,7 @@ int RTPReceiver::allocRtpPort() { @@ -330,7 +335,7 @@ int RTPReceiver::allocRtpPort() {
330 s_rtpPort = MIN_RTP_PORT; 335 s_rtpPort = MIN_RTP_PORT;
331 count ++; 336 count ++;
332 if (count > 1) { 337 if (count > 1) {
333 - LOG_ERROR("[{}] - 10000 到 60000 没有可用的port", m_SipChannelId); 338 + LOG_ERROR("[{}] - 范围内没有可用的port", m_SipChannelId);
334 } 339 }
335 } 340 }
336 341
@@ -362,4 +367,8 @@ int RTPReceiver::allocRtpPort() { @@ -362,4 +367,8 @@ int RTPReceiver::allocRtpPort() {
362 } 367 }
363 368
364 return s_rtpPort; 369 return s_rtpPort;
  370 +}
  371 +
  372 +void RTPReceiver::RequestStreamFailed() {
  373 + m_bRtpExit = true;
365 } 374 }
366 \ No newline at end of file 375 \ No newline at end of file
src/decoder/gb28181/rtp/RTPReceiver.h
@@ -90,6 +90,7 @@ public: @@ -90,6 +90,7 @@ public:
90 virtual bool Open(string channel_id) = 0; 90 virtual bool Open(string channel_id) = 0;
91 virtual bool IsOpened() = 0; 91 virtual bool IsOpened() = 0;
92 virtual void Close() = 0; 92 virtual void Close() = 0;
  93 + virtual bool RequestStream() = 0;
93 94
94 void SetVodEndCallback(CallBack_VodFileEnd cb, void* param); 95 void SetVodEndCallback(CallBack_VodFileEnd cb, void* param);
95 96
@@ -101,6 +102,8 @@ public: @@ -101,6 +102,8 @@ public:
101 102
102 int allocRtpPort(); 103 int allocRtpPort();
103 104
  105 + void RequestStreamFailed();
  106 +
104 public: 107 public:
105 void OnPsDemux(unsigned char streamId, BYTE *data, int len, bool key, uint64_t pts, uint64_t localPts); 108 void OnPsDemux(unsigned char streamId, BYTE *data, int len, bool key, uint64_t pts, uint64_t localPts);
106 int OnPsProcess(); 109 int OnPsProcess();
@@ -130,7 +133,8 @@ public: @@ -130,7 +133,8 @@ public:
130 int m_rtp_port{-1}; 133 int m_rtp_port{-1};
131 134
132 CMpeg2Demux m_psParser; 135 CMpeg2Demux m_psParser;
133 - std::atomic_bool m_bPsExit; // 标识PS解包线程关闭 136 + std::atomic_bool m_bPsExit; // 标识PS解包线程关闭
  137 + std::atomic_bool m_bRtpExit; // RTP收包线程结束开关
134 138
135 uint32_t lastPts{0}; 139 uint32_t lastPts{0};
136 uint64_t last_recv_ts{0}; 140 uint64_t last_recv_ts{0};
@@ -138,7 +142,7 @@ public: @@ -138,7 +142,7 @@ public:
138 int mark{0}; 142 int mark{0};
139 BYTE* recvTmpBuf{nullptr}; 143 BYTE* recvTmpBuf{nullptr};
140 144
141 - std::thread* m_psThreadPtr; // PS解包线程 145 + std::thread* m_psThreadPtr{nullptr}; // PS解包线程
142 146
143 CallBack_VodFileEnd m_hVodEndFunc; // 录像流结束回调 147 CallBack_VodFileEnd m_hVodEndFunc; // 录像流结束回调
144 CallBack_Request_Stream m_callback_request_stream; //请求流回调 148 CallBack_Request_Stream m_callback_request_stream; //请求流回调
src/decoder/gb28181/rtp/RTPTcpReceiver.cpp
1 #include"RTPTcpReceiver.h" 1 #include"RTPTcpReceiver.h"
2 2
3 #include "../common_header.h" 3 #include "../common_header.h"
4 -#include "../sip/SipServer.h" 4 +#include "../websocket/WebsocketClient.h"
5 5
6 6
7 // class TcpRTPSession : public RTPSession 7 // class TcpRTPSession : public RTPSession
@@ -96,14 +96,14 @@ static int listen_finish_thread_(void* param) @@ -96,14 +96,14 @@ static int listen_finish_thread_(void* param)
96 } 96 }
97 97
98 RTPTcpReceiver::RTPTcpReceiver() 98 RTPTcpReceiver::RTPTcpReceiver()
99 -: m_bRtpExit(false)  
100 -, m_bOpened(false) 99 +: m_bOpened(false)
101 , m_idleCount(-1) 100 , m_idleCount(-1)
102 , m_noDataCount(-1) 101 , m_noDataCount(-1)
103 , m_nListener(-1) 102 , m_nListener(-1)
104 , m_bAccepted(false) 103 , m_bAccepted(false)
105 , m_bClosing(false) 104 , m_bClosing(false)
106 { 105 {
  106 + m_bRtpExit = false;
107 m_rtpSessionPtr = new RTPSession(); 107 m_rtpSessionPtr = new RTPSession();
108 m_pSessparams = new RTPSessionParams(); 108 m_pSessparams = new RTPSessionParams();
109 m_pTrans = new MyTCPTransmitter(); 109 m_pTrans = new MyTCPTransmitter();
@@ -132,13 +132,11 @@ RTPTcpReceiver::~RTPTcpReceiver(){ @@ -132,13 +132,11 @@ RTPTcpReceiver::~RTPTcpReceiver(){
132 bool RTPTcpReceiver::Open(string channel_id){ 132 bool RTPTcpReceiver::Open(string channel_id){
133 m_SipChannelId = channel_id; 133 m_SipChannelId = channel_id;
134 134
135 - int rtpPort = allocRtpPort();  
136 - if (rtpPort < 0) { 135 + m_rtp_port = allocRtpPort();
  136 + if (m_rtp_port < 0) {
137 return false; 137 return false;
138 } 138 }
139 139
140 - m_rtp_port = rtpPort;  
141 -  
142 if(0 != initSession(m_rtp_port)){ 140 if(0 != initSession(m_rtp_port)){
143 return false; 141 return false;
144 } 142 }
@@ -158,6 +156,11 @@ bool RTPTcpReceiver::IsOpened(){ @@ -158,6 +156,11 @@ bool RTPTcpReceiver::IsOpened(){
158 void RTPTcpReceiver::Close(){ 156 void RTPTcpReceiver::Close(){
159 m_bRtpExit = true; 157 m_bRtpExit = true;
160 158
  159 + WebsocketClient* pServer = WebsocketClient::getInstance();
  160 + if (pServer){
  161 + pServer->ByeInvite(m_SipChannelId, m_rtp_port);
  162 + }
  163 +
161 if(m_listenFinishThread.joinable()){ 164 if(m_listenFinishThread.joinable()){
162 m_listenFinishThread.join(); 165 m_listenFinishThread.join();
163 } 166 }
@@ -370,11 +373,12 @@ bool RTPTcpReceiver::ReConnect(){ @@ -370,11 +373,12 @@ bool RTPTcpReceiver::ReConnect(){
370 } 373 }
371 374
372 bool RTPTcpReceiver::RequestStream(){ 375 bool RTPTcpReceiver::RequestStream(){
373 - SipServer* pServer = SipServer::getInstance();  
374 - int ret = -1; 376 + WebsocketClient* pServer = WebsocketClient::getInstance();
375 if (pServer){ 377 if (pServer){
376 - ret = pServer->RequestInvite_TCP_a(m_SipChannelId.c_str(), m_rtp_port); 378 + if (pServer->InviteTcp(m_SipChannelId, m_rtp_port, this) < 0) {
  379 + return false;
  380 + }
377 } 381 }
378 382
379 - return (ret > 0) ; 383 + return true ;
380 } 384 }
381 \ No newline at end of file 385 \ No newline at end of file
src/decoder/gb28181/rtp/RTPTcpReceiver.h
@@ -26,17 +26,6 @@ @@ -26,17 +26,6 @@
26 #include "RTPReceiver.h" 26 #include "RTPReceiver.h"
27 27
28 28
29 -#define OUTTIME_RTCP 30*1000  
30 -#define PAYLOAD 99  
31 -#define PAYLOAD_PS 96  
32 -#define PAYLOAD_H264 98  
33 -#define PAYLOAD_MP4 97  
34 -  
35 -#define UDP_SIZE 1400  
36 -#define MIN_PORT 10000  
37 -#define MAX_PORT 60000  
38 -#define RTP_MAX_PACKET_LEN 1450  
39 -  
40 using namespace jrtplib; 29 using namespace jrtplib;
41 using namespace std; 30 using namespace std;
42 31
@@ -51,15 +40,15 @@ public: @@ -51,15 +40,15 @@ public:
51 RTPTcpReceiver(); 40 RTPTcpReceiver();
52 ~RTPTcpReceiver(); 41 ~RTPTcpReceiver();
53 42
54 - bool Open(string channel_id);  
55 - bool IsOpened();  
56 - void Close(); 43 + virtual bool Open(string channel_id);
  44 + virtual bool IsOpened() ;
  45 + virtual void Close() ;
  46 + virtual bool RequestStream();
57 47
58 public: 48 public:
59 int OnRtpRecv(); 49 int OnRtpRecv();
60 bool ReConnect(); 50 bool ReConnect();
61 int ListenFinish(); 51 int ListenFinish();
62 - bool RequestStream();  
63 bool isClosing(); 52 bool isClosing();
64 53
65 private: 54 private:
@@ -67,9 +56,6 @@ private: @@ -67,9 +56,6 @@ private:
67 void close_task(); 56 void close_task();
68 57
69 private: 58 private:
70 -  
71 - std::atomic_bool m_bRtpExit; // 标识RTP收包线程闭  
72 -  
73 std::atomic_bool m_bOpened; 59 std::atomic_bool m_bOpened;
74 std::atomic_bool m_bAccepted; 60 std::atomic_bool m_bAccepted;
75 std::atomic_bool m_bClosing; 61 std::atomic_bool m_bClosing;
src/decoder/gb28181/rtp/RTPUdpReceiver.cpp
@@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
7 #include <chrono> 7 #include <chrono>
8 8
9 #include "../common_header.h" 9 #include "../common_header.h"
10 -#include "../sip/SipServer.h" 10 +#include "../websocket/WebsocketClient.h"
11 11
12 12
13 using namespace std; 13 using namespace std;
@@ -55,12 +55,22 @@ static int rtp_revc_thread_(void* param) @@ -55,12 +55,22 @@ static int rtp_revc_thread_(void* param)
55 return self->OnRtpRecv(); 55 return self->OnRtpRecv();
56 } 56 }
57 57
  58 +static int connecting_thread_(void* param)
  59 +{
  60 + if (!param) {
  61 + return -1;
  62 + }
  63 +
  64 + RTPUdpReceiver* self = (RTPUdpReceiver*)param;
  65 + return self->IsConnecting();
  66 +}
  67 +
58 RTPUdpReceiver::RTPUdpReceiver() 68 RTPUdpReceiver::RTPUdpReceiver()
59 -: m_bRtpExit(false)  
60 -, m_bOpened(false) 69 +:m_bOpened(false)
61 , m_idleCount(-1) 70 , m_idleCount(-1)
62 ,m_noDataCount(-1) 71 ,m_noDataCount(-1)
63 { 72 {
  73 + m_bRtpExit = false;
64 m_sessparamsPtr = new RTPSessionParams(); 74 m_sessparamsPtr = new RTPSessionParams();
65 m_transparamsPtr = new RTPUDPv4TransmissionParams(); 75 m_transparamsPtr = new RTPUDPv4TransmissionParams();
66 m_rtpSessionPtr = new UdpRTPSession(); 76 m_rtpSessionPtr = new UdpRTPSession();
@@ -68,8 +78,7 @@ RTPUdpReceiver::RTPUdpReceiver() @@ -68,8 +78,7 @@ RTPUdpReceiver::RTPUdpReceiver()
68 78
69 RTPUdpReceiver::~RTPUdpReceiver() 79 RTPUdpReceiver::~RTPUdpReceiver()
70 { 80 {
71 - if (IsOpened())  
72 - Close(); 81 + m_bRtpExit = true;
73 82
74 if(nullptr != m_sessparamsPtr){ 83 if(nullptr != m_sessparamsPtr){
75 delete m_sessparamsPtr; 84 delete m_sessparamsPtr;
@@ -81,6 +90,12 @@ RTPUdpReceiver::~RTPUdpReceiver() @@ -81,6 +90,12 @@ RTPUdpReceiver::~RTPUdpReceiver()
81 m_transparamsPtr = nullptr; 90 m_transparamsPtr = nullptr;
82 } 91 }
83 92
  93 + if (nullptr != m_connThreadPtr && m_connThreadPtr->joinable()) {
  94 + m_connThreadPtr->join();
  95 + delete m_connThreadPtr;
  96 + m_connThreadPtr = nullptr;
  97 + }
  98 +
84 if(nullptr != m_rtpSessionPtr){ 99 if(nullptr != m_rtpSessionPtr){
85 delete m_rtpSessionPtr; 100 delete m_rtpSessionPtr;
86 m_rtpSessionPtr = nullptr; 101 m_rtpSessionPtr = nullptr;
@@ -91,11 +106,10 @@ bool RTPUdpReceiver::Open(string channel_id) @@ -91,11 +106,10 @@ bool RTPUdpReceiver::Open(string channel_id)
91 { 106 {
92 m_SipChannelId = channel_id; 107 m_SipChannelId = channel_id;
93 108
94 - int rtpPort = allocRtpPort();  
95 - if (rtpPort < 0) { 109 + m_rtp_port = allocRtpPort();
  110 + if (m_rtp_port < 0) {
96 return false; 111 return false;
97 } 112 }
98 - m_rtp_port = rtpPort;  
99 113
100 m_sessparamsPtr->SetUsePollThread(true); 114 m_sessparamsPtr->SetUsePollThread(true);
101 m_sessparamsPtr->SetMinimumRTCPTransmissionInterval(10); 115 m_sessparamsPtr->SetMinimumRTCPTransmissionInterval(10);
@@ -123,29 +137,27 @@ bool RTPUdpReceiver::Open(string channel_id) @@ -123,29 +137,27 @@ bool RTPUdpReceiver::Open(string channel_id)
123 return false; 137 return false;
124 } 138 }
125 139
  140 + // InitPS()成功就得起该线程,因为ClosePsThread是在这里完成的
  141 + m_connThreadPtr = new std::thread(connecting_thread_, this);
  142 + if (nullptr == m_connThreadPtr) {
  143 + LOG_ERROR("[{}] Create m_connThreadPtr error", m_SipChannelId);
  144 + return false;
  145 + }
  146 +
126 bool bReq = RequestStream(); 147 bool bReq = RequestStream();
127 if (!bReq) { 148 if (!bReq) {
128 LOG_INFO("[{}] RequestStream failed !", m_SipChannelId); 149 LOG_INFO("[{}] RequestStream failed !", m_SipChannelId);
129 Close(); 150 Close();
130 return false; 151 return false;
131 } 152 }
132 - 153 +
133 m_bOpened = true; 154 m_bOpened = true;
  155 + m_bNoData = false;
134 LOG_INFO("[{}] Open ok", m_SipChannelId); 156 LOG_INFO("[{}] Open ok", m_SipChannelId);
135 157
136 return true; 158 return true;
137 } 159 }
138 160
139 -bool RTPUdpReceiver::RequestStream() {  
140 - SipServer* pServer = SipServer::getInstance();  
141 - int ret = -1;  
142 - if (pServer){  
143 - ret = pServer->RequestInvite_UDP(m_SipChannelId.c_str(), m_rtp_port);  
144 - }  
145 -  
146 - return (ret > 0) ;  
147 -}  
148 -  
149 bool RTPUdpReceiver::IsOpened() 161 bool RTPUdpReceiver::IsOpened()
150 { 162 {
151 return m_bOpened; 163 return m_bOpened;
@@ -154,21 +166,6 @@ bool RTPUdpReceiver::IsOpened() @@ -154,21 +166,6 @@ bool RTPUdpReceiver::IsOpened()
154 void RTPUdpReceiver::Close() 166 void RTPUdpReceiver::Close()
155 { 167 {
156 m_bRtpExit = true; 168 m_bRtpExit = true;
157 -  
158 - // rtp接收线程退出  
159 - if (nullptr != m_rtpThreadPtr && m_rtpThreadPtr->joinable())  
160 - {  
161 - m_rtpThreadPtr->join();  
162 - delete m_rtpThreadPtr;  
163 - m_rtpThreadPtr = nullptr;  
164 - }  
165 - m_rtpSessionPtr->Destroy();  
166 -  
167 - ClosePsThread();  
168 -  
169 - m_bOpened = false;  
170 -  
171 - LOG_INFO("[{}] closed.", m_SipChannelId);  
172 } 169 }
173 170
174 // 收RTP包线程 171 // 收RTP包线程
@@ -197,6 +194,7 @@ int RTPUdpReceiver::OnRtpRecv() @@ -197,6 +194,7 @@ int RTPUdpReceiver::OnRtpRecv()
197 RTPPacket* packet; 194 RTPPacket* packet;
198 while ((packet = m_rtpSessionPtr->GetNextPacket()) != NULL) 195 while ((packet = m_rtpSessionPtr->GetNextPacket()) != NULL)
199 { 196 {
  197 + m_bNoData = false;
200 // LOG_INFO("OnRtpRecv GetNextPacket --{}", m_SipChannelId); 198 // LOG_INFO("OnRtpRecv GetNextPacket --{}", m_SipChannelId);
201 int ret = ParsePacket(packet); 199 int ret = ParsePacket(packet);
202 m_rtpSessionPtr->DeletePacket(packet); 200 m_rtpSessionPtr->DeletePacket(packet);
@@ -342,4 +340,87 @@ int RTPUdpReceiver::OnRtpRecv() @@ -342,4 +340,87 @@ int RTPUdpReceiver::OnRtpRecv()
342 return 0; 340 return 0;
343 } 341 }
344 342
  343 +bool RTPUdpReceiver::RequestStream() {
  344 + WebsocketClient* pClient = WebsocketClient::getInstance();
  345 + if (pClient){
  346 + if (pClient->InviteUdp(m_SipChannelId, m_rtp_port, this) < 0) {
  347 + return false;
  348 + }
  349 + }
345 350
  351 + return true;
  352 +}
  353 +
  354 +int RTPUdpReceiver::IsConnecting() {
  355 + LOG_INFO("[{}] IsConnecting started.", m_SipChannelId);
  356 +
  357 + int count = 0;
  358 + while (!m_bRtpExit)
  359 + {
  360 + if (m_bNoData) {
  361 + bool bReq = RequestStream();
  362 + if (!bReq) {
  363 + LOG_INFO("[{}] RequestStream failed !", m_SipChannelId);
  364 + }
  365 +
  366 + wait_times(30); // 等待3s
  367 +
  368 + count++;
  369 +
  370 + if (count > 10) {
  371 + // 30s 依然没数据过来,则关闭
  372 + m_bRtpExit = true;
  373 + break;
  374 + }
  375 + } else {
  376 + m_bNoData = true;
  377 +
  378 + wait_times(100); // 等待10s, 10s之内正常有数据的情况 m_bNoData 已经被置为false
  379 + }
  380 + }
  381 +
  382 + LOG_DEBUG("[{}] while", m_SipChannelId);
  383 +
  384 + // 结束整个任务
  385 + WebsocketClient* pClient = WebsocketClient::getInstance();
  386 + if (pClient){
  387 + pClient->ByeInvite(m_SipChannelId, m_rtp_port);
  388 + }
  389 +
  390 + LOG_DEBUG("[{}] ByeInvite", m_SipChannelId);
  391 +
  392 + // rtp接收线程退出
  393 + if (nullptr != m_rtpThreadPtr && m_rtpThreadPtr->joinable())
  394 + {
  395 + m_rtpThreadPtr->join();
  396 + delete m_rtpThreadPtr;
  397 + m_rtpThreadPtr = nullptr;
  398 + }
  399 +
  400 + LOG_DEBUG("[{}] m_rtpThreadPtr", m_SipChannelId);
  401 +
  402 + m_rtpSessionPtr->Destroy();
  403 +
  404 + LOG_DEBUG("[{}] m_rtpSessionPtr", m_SipChannelId);
  405 +
  406 + ClosePsThread();
  407 +
  408 + m_bOpened = false;
  409 +
  410 + LOG_INFO("[{}] IsConnecting exited.", m_SipChannelId);
  411 +
  412 + return 0;
  413 +}
  414 +
  415 +// 对退出命令敏感的延时
  416 +bool RTPUdpReceiver::wait_times(int times) {
  417 + int count_sleep = times;
  418 + while (!m_bRtpExit) {
  419 + count_sleep-- ;
  420 + if (count_sleep <= 0) {
  421 + count_sleep = times;
  422 + break;
  423 + }
  424 + std::this_thread::sleep_for(std::chrono::milliseconds(100));
  425 + }
  426 +}
346 \ No newline at end of file 427 \ No newline at end of file
src/decoder/gb28181/rtp/RTPUdpReceiver.h
@@ -14,17 +14,6 @@ @@ -14,17 +14,6 @@
14 #include "RTPReceiver.h" 14 #include "RTPReceiver.h"
15 15
16 16
17 -#define OUTTIME_RTCP 30*1000  
18 -#define PAYLOAD 99  
19 -#define PAYLOAD_PS 96  
20 -#define PAYLOAD_H264 98  
21 -#define PAYLOAD_MP4 97  
22 -  
23 -#define UDP_SIZE 1400  
24 -#define MIN_PORT 10000  
25 -#define MAX_PORT 60000  
26 -#define RTP_MAX_PACKET_LEN 1450  
27 -  
28 using namespace jrtplib; 17 using namespace jrtplib;
29 using namespace std; 18 using namespace std;
30 19
@@ -40,28 +29,33 @@ public: @@ -40,28 +29,33 @@ public:
40 virtual bool Open(string channel_id); 29 virtual bool Open(string channel_id);
41 virtual bool IsOpened() ; 30 virtual bool IsOpened() ;
42 virtual void Close() ; 31 virtual void Close() ;
43 -  
44 - bool RequestStream(); 32 + virtual bool RequestStream();
45 33
46 public: 34 public:
47 int OnRtpRecv(); 35 int OnRtpRecv();
  36 + int IsConnecting();
48 37
49 private: 38 private:
50 - std::thread* m_rtpThreadPtr; // RTP接收线程 39 + bool wait_times(int times);
51 40
52 - RTPSession* m_rtpSessionPtr; // RTP会话  
53 - RTPSession m_rtpSession;  
54 - std::atomic_bool m_bRtpExit; // 标识RTP收包线程闭 41 +private:
  42 + std::thread* m_rtpThreadPtr{nullptr}; // RTP接收线程
  43 + std::thread* m_connThreadPtr{nullptr}; // 判断流是否还在的线程
  44 +
  45 + RTPSession* m_rtpSessionPtr{nullptr}; // RTP会话
  46 + RTPSession m_rtpSession;
55 47
56 std::atomic_bool m_bOpened; 48 std::atomic_bool m_bOpened;
57 49
58 int64_t m_idleCount; 50 int64_t m_idleCount;
59 int64_t m_noDataCount;//线程计数,用于打开流成功但是实际没流过来 51 int64_t m_noDataCount;//线程计数,用于打开流成功但是实际没流过来
60 52
61 - RTPSessionParams* m_sessparamsPtr;  
62 - RTPUDPv4TransmissionParams* m_transparamsPtr; 53 + RTPSessionParams* m_sessparamsPtr{nullptr};
  54 + RTPUDPv4TransmissionParams* m_transparamsPtr{nullptr};
63 55
64 string m_sip_channel_id; 56 string m_sip_channel_id;
  57 +
  58 + std::atomic_bool m_bNoData{false};
65 }; 59 };
66 60
67 #endif // _RTP_UDP_RECEIVER_H_ 61 #endif // _RTP_UDP_RECEIVER_H_
src/decoder/gb28181/sip/Message/CatalogParser.cpp deleted
1 -#include "CatalogParser.h"  
2 -#include <sstream>  
3 -#include <list>  
4 -  
5 -#include "../../common_header.h"  
6 -  
7 -static const char* g_event_desc[] =  
8 -{  
9 - "ON",  
10 - "OFF",  
11 - "VLOST",  
12 - "DEFECT",  
13 - "ADD",  
14 - "DEL",  
15 - "UPDATE"  
16 -};  
17 -  
18 -  
19 -bool CCatalogParser::Encode( std::string &message )  
20 -{  
21 - std::ostringstream content;  
22 - content<<"<?xml version=\"1.0\"?>\r\n";  
23 - content<<"<Notify>\r\n";  
24 - content<<"<CmdType>Catalog</CmdType>\r\n";  
25 - content<<"<SN>"<< m_sn <<"</SN>\r\n";  
26 - content<<"<DeviceID>"<< m_deviceid <<"</DeviceID>\r\n";  
27 - content<<"<Status>OK</Status>\r\n";  
28 - content<<"<SumNum>"<< m_sum <<"</SumNum>\r\n";  
29 - content<<"<DeviceList Num=\"" << m_devices.size() << "\">\r\n";  
30 -  
31 - for( auto it = m_devices.begin(); it != m_devices.end(); ++it )  
32 - {  
33 - // 校验目录项的必选参数  
34 - const DeviceInfo &catalog = (*it);  
35 - content<<"<Item>\r\n";  
36 - content<<"<DeviceID>"<<catalog.id<<"</DeviceID>\r\n";  
37 - content<<"<Event>"<< g_event_desc[catalog.event] <<"</Event>\r\n";  
38 -  
39 - if( catalog.event == EVENT_ADD || catalog.event == EVENT_UPDATE )  
40 - {  
41 - content<<"<Name>"<< catalog.name <<"</Name>\r\n";  
42 - content<<"<Manufacturer>"<< catalog.manufacturer <<"</Manufacturer>\r\n";  
43 - content<<"<Model>"<< catalog.model <<"</Model>\r\n";  
44 - content<<"<Owner>"<< catalog.owner <<"</Owner>\r\n";  
45 -  
46 - if( !catalog.civil.empty() )  
47 - {  
48 - content<<"<CivilCode>"<<catalog.civil<<"</CivilCode>\r\n";  
49 - }  
50 - else  
51 - {  
52 - content<<"<CivilCode>"<<catalog.parentid<<"</CivilCode>\r\n";  
53 - }  
54 -  
55 - if( !catalog.block.empty() )  
56 - {  
57 - content<<"<Block>"<< catalog.block <<"</Block>\r\n";  
58 - }  
59 -  
60 - content<<"<Address>"<< catalog.address <<"</Address>\r\n";  
61 - content<<"<Parental>"<< catalog.parental <<"</Parental>\r\n";  
62 - content<<"<ParentID>"<< catalog.parentid <<"</ParentID>\r\n";  
63 -  
64 - if( !catalog.safetyway.empty() )  
65 - {  
66 - content<<"<SafetyWay>"<< catalog.safetyway <<"</SafetyWay>\r\n";  
67 - }  
68 -  
69 - content<<"<RegisterWay>"<< catalog.registerway <<"</RegisterWay>\r\n";  
70 -  
71 - if( !catalog.certnum.empty() )  
72 - {  
73 - content<<"<CertNum>"<< catalog.certnum <<"</CertNum>\r\n";  
74 - }  
75 -  
76 - if( !catalog.certifiable.empty() )  
77 - {  
78 - content<<"<Certifiable>"<< catalog.certifiable <<"</Certifiable>\r\n";  
79 - }  
80 -  
81 - if( !catalog.errcode.empty() )  
82 - {  
83 - content<<"<ErrCode>"<< catalog.errcode <<"</ErrCode>\r\n";  
84 - }  
85 -  
86 - if( !catalog.endtime.empty() )  
87 - {  
88 - content<<"<EndTime>"<< catalog.endtime <<"</EndTime>\r\n";  
89 - }  
90 -  
91 - content<<"<Secrecy>"<< catalog.secrecy <<"</Secrecy>\r\n";  
92 -  
93 - if( !catalog.ip.empty() )  
94 - {  
95 - content<<"<IPAddress>"<< catalog.ip <<"</IPAddress>\r\n";  
96 - }  
97 -  
98 - if( !catalog.port.empty() )  
99 - {  
100 - content<<"<Port>"<< catalog.port <<"</Port>\r\n";  
101 - }  
102 -  
103 - if( !catalog.password.empty() )  
104 - {  
105 - content<<"<Password>"<< catalog.password <<"</Password>\r\n";  
106 - }  
107 -  
108 - content<<"<Status>"<<catalog.status<<"</Status>\r\n";  
109 -  
110 - if( !catalog.longitude.empty() )  
111 - {  
112 - content<<"<Longitude>"<<catalog.longitude<<"</Longitude>\r\n";  
113 - }  
114 -  
115 - if( !catalog.latitude.empty() )  
116 - {  
117 - content<<"<Latitude>"<<catalog.latitude<<"</Latitude>\r\n";  
118 - }  
119 -  
120 - content<<"<Info>\r\n";  
121 - if( !catalog.ptz.empty() )  
122 - {  
123 - content<<"<PTZType>"<<catalog.ptz<<"</PTZType>\r\n";  
124 - }  
125 -  
126 - if( !catalog.position.empty() )  
127 - {  
128 - content<<"<PositionType>"<<catalog.position<<"</PositionType>\r\n";  
129 - }  
130 -  
131 - if( !catalog.room.empty() )  
132 - {  
133 - content<<"<RoomType>"<<catalog.room<<"</RoomType>\r\n";  
134 - }  
135 -  
136 - if( !catalog.use.empty() )  
137 - {  
138 - content<<"<UseType>"<<catalog.use<<"</UseType>\r\n";  
139 - }  
140 -  
141 - if( !catalog.supplylight.empty() )  
142 - {  
143 - content<<"<SupplyLightType>"<<catalog.supplylight<<"</SupplyLightType>\r\n";  
144 - }  
145 -  
146 - if( !catalog.direction.empty() )  
147 - {  
148 - content<<"<DirectionType>"<<catalog.direction<<"</DirectionType>\r\n";  
149 - }  
150 -  
151 - if( !catalog.resolution.empty() )  
152 - {  
153 - content<<"<Resolution>"<<catalog.resolution<<"</Resolution>\r\n";  
154 - }  
155 -  
156 - if( !catalog.businessgroup.empty() )  
157 - {  
158 - content<<"<BusinessGroupID>"<<catalog.businessgroup<<"</BusinessGroupID>\r\n";  
159 - }  
160 -  
161 - content<<"</Info>\r\n";  
162 - }  
163 -  
164 - content<<"</Item>\r\n";  
165 - }  
166 - content<<"</DeviceList>\r\n";  
167 - content<<"</Notify>\r\n\r\n";  
168 -  
169 - message = content.str();  
170 - return true;  
171 -}  
172 -  
173 -std::vector< DeviceInfo > CCatalogParser::Decode( const std::vector< tinyxml2::XMLNode* > &nodes)  
174 -{  
175 - std::vector< DeviceInfo > cat_list;  
176 - // 必须参数校验  
177 - tinyxml2::XMLNode *pSumNum = NULL;  
178 - size_t size = nodes.size();  
179 - for( size_t i = 0; i < size; ++i )  
180 - {  
181 - tinyxml2::XMLNode *pNode = nodes[i];  
182 - if( pNode == NULL )  
183 - {  
184 - LOG_DEBUG( "参数错误" );  
185 - continue;  
186 - }  
187 -  
188 - const char* type = pNode->Value();  
189 - if( type == NULL )  
190 - {  
191 - LOG_DEBUG( "参数名字为空" );  
192 - continue;  
193 - }  
194 -  
195 - if( CGBMessage::CompareNoCase( type, "SumNum" ) )  
196 - {  
197 - pSumNum = pNode;  
198 - }  
199 - }  
200 -  
201 - // 必选参数必须填  
202 - if( pSumNum == NULL )  
203 - {  
204 - LOG_ERROR( "参数SumNum没有被设置" );  
205 - return cat_list;  
206 - }  
207 -  
208 - // 参数解析  
209 - std::list< tinyxml2::XMLNode* > items;  
210 - for( size_t i = 0; i < size; ++i )  
211 - {  
212 - tinyxml2::XMLNode *pNode = nodes[i];  
213 - if( pNode == NULL )  
214 - {  
215 - LOG_DEBUG( "参数错误" );  
216 - continue;  
217 - }  
218 -  
219 - const char* type = pNode->Value();  
220 - if( type == NULL )  
221 - {  
222 - LOG_DEBUG( "参数名字为空" );  
223 - continue;  
224 - }  
225 -  
226 - if( CGBMessage::CompareNoCase( type, "Status" ) )  
227 - {  
228 - tinyxml2::XMLNode *pChild = pNode->FirstChild();  
229 - if( pChild == NULL )  
230 - {  
231 - LOG_DEBUG( "参数值没有设置" );  
232 - continue;  
233 - }  
234 -  
235 - const char *value = pChild->Value();  
236 - if( value == NULL )  
237 - {  
238 - LOG_DEBUG( "参数值为空" );  
239 - continue;  
240 - }  
241 - else  
242 - {  
243 - m_status = value;  
244 - }  
245 - }  
246 - else if( CGBMessage::CompareNoCase( type, "SumNum" ) )  
247 - {  
248 - tinyxml2::XMLNode *pChild = pNode->FirstChild();  
249 - if( pChild == NULL )  
250 - {  
251 - LOG_DEBUG( "参数值没有设置" );  
252 - continue;  
253 - }  
254 -  
255 - const char *value = pChild->Value();  
256 - if( value == NULL )  
257 - {  
258 - LOG_DEBUG( "参数值为空" );  
259 - continue;  
260 - }  
261 - else  
262 - {  
263 - m_sum = atoi( value );  
264 - }  
265 - }  
266 - else if( CGBMessage::CompareNoCase( type, "DeviceList" ) )  
267 - {  
268 - for(tinyxml2::XMLNode *pItem = pNode->FirstChild(); pItem != NULL; pItem = pItem->NextSibling() )  
269 - {  
270 - const char *type = pItem->Value();  
271 - if( type == NULL )  
272 - {  
273 - LOG_DEBUG( "参数名字为空" );  
274 - continue;  
275 - }  
276 -  
277 - if( CGBMessage::CompareNoCase( type, "Item" ) )  
278 - {  
279 - items.push_back( pItem );  
280 - }  
281 - else  
282 - {  
283 - LOG_DEBUG( "国标未定义的参数:{}" , type );  
284 - continue;  
285 - }  
286 - }  
287 - }  
288 - else  
289 - {  
290 - LOG_DEBUG( "国标未定义的参数:{}" , type );  
291 - continue;  
292 - }  
293 - }  
294 -  
295 - // 目录项  
296 - std::list< tinyxml2::XMLNode* >::iterator it = items.begin();  
297 - std::list< tinyxml2::XMLNode* >::iterator end = items.end();  
298 - for( /*it*/; it != end; ++it )  
299 - {  
300 - DeviceInfo catalog;  
301 - for(tinyxml2::XMLNode *pItem = (*it)->FirstChild(); pItem != NULL; pItem = pItem->NextSibling() )  
302 - {  
303 - const char *type = pItem->Value();  
304 - if( type == NULL )  
305 - {  
306 - LOG_DEBUG( "参数名字为空" );  
307 - continue;  
308 - }  
309 -  
310 - tinyxml2::XMLNode *pValue = pItem->FirstChild();  
311 - if( pValue == NULL )  
312 - {  
313 - LOG_DEBUG( "参数值没有设置" );  
314 - continue;  
315 - }  
316 -  
317 - const char *value = pValue->Value();  
318 - if( value == NULL )  
319 - {  
320 - LOG_DEBUG( "参数值为空" );  
321 - continue;  
322 - }  
323 -  
324 - if( CGBMessage::CompareNoCase( type, "DeviceID" ) )  
325 - {  
326 - catalog.id = value;  
327 - }  
328 - else if( CGBMessage::CompareNoCase( type, "Event" ) )  
329 - {  
330 - if( CGBMessage::CompareNoCase( value, "ON" ) )  
331 - {  
332 - catalog.event = EVENT_ON;  
333 - }  
334 - else if( CGBMessage::CompareNoCase( value, "OFF" ) )  
335 - {  
336 - catalog.event = EVENT_OFF;  
337 - }  
338 - else if( CGBMessage::CompareNoCase( value, "VLOST" ) )  
339 - {  
340 - catalog.event = EVENT_VLOST;  
341 - }  
342 - else if( CGBMessage::CompareNoCase( value, "DEFECT" ) )  
343 - {  
344 - catalog.event = EVENT_DEFECT;  
345 - }  
346 - else if( CGBMessage::CompareNoCase( value, "ADD" ) )  
347 - {  
348 - catalog.event = EVENT_ADD;  
349 - }  
350 - else if( CGBMessage::CompareNoCase( value, "DEL" ) )  
351 - {  
352 - catalog.event = EVENT_DEL;  
353 - }  
354 - else if( CGBMessage::CompareNoCase( value, "UPDATE" ) )  
355 - {  
356 - catalog.event = EVENT_UPDATE;  
357 - }  
358 - else  
359 - {  
360 - LOG_ERROR( "Event参数值\'{}\'无效", value );  
361 - return cat_list;  
362 - }  
363 - }  
364 - else if( CGBMessage::CompareNoCase( type, "Name" ) )  
365 - {  
366 - catalog.name = value;  
367 - }  
368 - else if( CGBMessage::CompareNoCase( type, "Manufacturer" ) )  
369 - {  
370 - catalog.manufacturer = value;  
371 - }  
372 - else if( CGBMessage::CompareNoCase( type, "Model" ) )  
373 - {  
374 - catalog.model = value;  
375 - }  
376 - else if( CGBMessage::CompareNoCase( type, "Owner" ) )  
377 - {  
378 - catalog.owner = value;  
379 - }  
380 - else if( CGBMessage::CompareNoCase( type, "CivilCode" ) )  
381 - {  
382 - catalog.civil = value;  
383 - }  
384 - else if( CGBMessage::CompareNoCase( type, "Block" ) )  
385 - {  
386 - catalog.block = value;  
387 - }  
388 - else if( CGBMessage::CompareNoCase( type, "Address" ) )  
389 - {  
390 - catalog.address = value;  
391 - }  
392 - else if( CGBMessage::CompareNoCase( type, "Parental" ) )  
393 - {  
394 - catalog.parental = value;  
395 - }  
396 - else if( CGBMessage::CompareNoCase( type, "ParentID" ) )  
397 - {  
398 - catalog.parentid = value;  
399 - }  
400 - else if( CGBMessage::CompareNoCase( type, "SafetyWay" ) )  
401 - {  
402 - catalog.safetyway = value;  
403 - }  
404 - else if( CGBMessage::CompareNoCase( type, "RegisterWay" ) )  
405 - {  
406 - catalog.registerway = value;  
407 - }  
408 - else if( CGBMessage::CompareNoCase( type, "CertNum" ) )  
409 - {  
410 - catalog.certnum = value;  
411 - }  
412 - else if( CGBMessage::CompareNoCase( type, "Certifiable" ) )  
413 - {  
414 - catalog.certifiable = value;  
415 - }  
416 - else if( CGBMessage::CompareNoCase( type, "ErrCode" ) )  
417 - {  
418 - catalog.errcode = value;  
419 - }  
420 - else if( CGBMessage::CompareNoCase( type, "EndTime" ) )  
421 - {  
422 - catalog.endtime = value;  
423 - }  
424 - else if( CGBMessage::CompareNoCase( type, "Secrecy" ) )  
425 - {  
426 - catalog.secrecy = value;  
427 - }  
428 - else if( CGBMessage::CompareNoCase( type, "IPAddress" ) )  
429 - {  
430 - catalog.ip = value;  
431 - }  
432 - else if( CGBMessage::CompareNoCase( type, "Port" ) )  
433 - {  
434 - catalog.port = value;  
435 - }  
436 - else if( CGBMessage::CompareNoCase( type, "Password" ) )  
437 - {  
438 - catalog.password = value;  
439 - }  
440 - else if( CGBMessage::CompareNoCase( type, "Status" ) )  
441 - {  
442 - catalog.status = value;  
443 - }  
444 - else if( CGBMessage::CompareNoCase( type, "Longitude" ) )  
445 - {  
446 - catalog.longitude = value;  
447 - }  
448 - else if( CGBMessage::CompareNoCase( type, "Latitude" ) )  
449 - {  
450 - catalog.latitude = value;  
451 - }  
452 - else if( CGBMessage::CompareNoCase( type, "PTZType" ) )  
453 - {  
454 - catalog.ptz = value;  
455 - }  
456 - else if( CGBMessage::CompareNoCase( type, "PositionType" ) )  
457 - {  
458 - catalog.position = value;  
459 - }  
460 - else if( CGBMessage::CompareNoCase( type, "RoomType" ) )  
461 - {  
462 - catalog.room = value;  
463 - }  
464 - else if( CGBMessage::CompareNoCase( type, "UseType" ) )  
465 - {  
466 - catalog.use = value;  
467 - }  
468 - else if( CGBMessage::CompareNoCase( type, "SupplyLightType" ) )  
469 - {  
470 - catalog.supplylight = value;  
471 - }  
472 - else if( CGBMessage::CompareNoCase( type, "DirectionType" ) )  
473 - {  
474 - catalog.direction = value;  
475 - }  
476 - else if( CGBMessage::CompareNoCase( type, "Resolution" ) )  
477 - {  
478 - catalog.resolution = value;  
479 - }  
480 - else if( CGBMessage::CompareNoCase( type, "BusinessGroupID" ) )  
481 - {  
482 - catalog.businessgroup = value;  
483 - }  
484 - else if( CGBMessage::CompareNoCase( type, "Info" ) )  
485 - {  
486 - for(tinyxml2::XMLNode *pInfo = pItem->FirstChild(); pInfo != NULL; pInfo = pInfo->NextSibling() )  
487 - {  
488 - pValue = pInfo->FirstChild();  
489 - if( pValue == NULL )  
490 - {  
491 - LOG_DEBUG( "参数值没有设置" );  
492 - continue;  
493 - }  
494 -  
495 - const char *type = pInfo->Value();  
496 - if( type == NULL )  
497 - {  
498 - LOG_DEBUG( "参数名字为空" );  
499 - continue;  
500 - }  
501 -  
502 - const char *value = pValue->Value();  
503 - if( value == NULL )  
504 - {  
505 - LOG_DEBUG( "参数值为空" );  
506 - continue;  
507 - }  
508 -  
509 - if( CGBMessage::CompareNoCase( type, "PTZType" ) )  
510 - {  
511 - catalog.ptz = value;  
512 - }  
513 - else if( CGBMessage::CompareNoCase( type, "PositionType" ) )  
514 - {  
515 - catalog.position = value;  
516 - }  
517 - else if( CGBMessage::CompareNoCase( type, "RoomType" ) )  
518 - {  
519 - catalog.room = value;  
520 - }  
521 - else if( CGBMessage::CompareNoCase( type, "UseType" ) )  
522 - {  
523 - catalog.use = value;  
524 - }  
525 - else if( CGBMessage::CompareNoCase( type, "SupplyLightType" ) )  
526 - {  
527 - catalog.supplylight = value;  
528 - }  
529 - else if( CGBMessage::CompareNoCase( type, "DirectionType" ) )  
530 - {  
531 - catalog.direction = value;  
532 - }  
533 - else if( CGBMessage::CompareNoCase( type, "Resolution" ) )  
534 - {  
535 - catalog.resolution = value;  
536 - }  
537 - else if( CGBMessage::CompareNoCase( type, "BusinessGroupID" ) )  
538 - {  
539 - catalog.businessgroup = value;  
540 - }  
541 - else  
542 - {  
543 - LOG_DEBUG( "国标未定义的参数:{}" , type );  
544 - }  
545 - }  
546 - }  
547 - else  
548 - {  
549 - LOG_DEBUG( "国标未定义的参数:{}" , type );  
550 - }  
551 - }  
552 -  
553 - // add to devices  
554 - m_devices.push_back( catalog );  
555 - }  
556 -  
557 - return m_devices;  
558 -}  
559 -  
560 -std::vector< DeviceInfo > CCatalogParser::DecodeCatlog(const char* body)  
561 -{  
562 - std::vector< DeviceInfo > cat_list;  
563 - if (body == NULL)  
564 - {  
565 - return cat_list;  
566 - }  
567 -  
568 - tinyxml2::XMLDocument doc;  
569 - doc.Parse(body);  
570 - tinyxml2::XMLElement* pRoot = doc.RootElement();  
571 - if (pRoot == NULL)  
572 - {  
573 - return cat_list;  
574 - }  
575 -  
576 - tinyxml2::XMLNode* pCmd = 0;  
577 - tinyxml2::XMLNode* pSN = 0;  
578 - tinyxml2::XMLNode* pDeviceID = 0;  
579 - std::vector< tinyxml2::XMLNode* > nodes;  
580 - for (tinyxml2::XMLNode* pNode = pRoot->FirstChild(); pNode != 0; pNode = pNode->NextSibling())  
581 - {  
582 - std::string value = pNode->Value();  
583 - if (value == "CmdType")  
584 - {  
585 - pCmd = pNode->FirstChild();  
586 - }  
587 - else if (value == "SN")  
588 - {  
589 - pSN = pNode->FirstChild();  
590 - }  
591 - else if (value == "DeviceID")  
592 - {  
593 - pDeviceID = pNode->FirstChild();  
594 - }  
595 - else  
596 - {  
597 - nodes.push_back(pNode);  
598 - }  
599 - }  
600 -  
601 - if (pCmd == NULL || pSN == NULL || pDeviceID == NULL)  
602 - {  
603 - return cat_list;  
604 - }  
605 -  
606 - std::string sn = pSN->Value();  
607 - if (sn.empty()) {  
608 - return cat_list;  
609 - }  
610 -  
611 - std::string deviceid = pDeviceID->Value();  
612 - if (deviceid.empty()) {  
613 - return cat_list;  
614 - }  
615 -  
616 - std::string msgType = pRoot->Value();  
617 - std::string cmdType = pCmd->Value();  
618 - if (msgType == "Response" && cmdType == "Catalog")  
619 - {  
620 - cat_list = Decode(nodes);  
621 - if (cat_list.empty())  
622 - {  
623 - LOG_WARN("消息体未解析出设备!");  
624 - } else {  
625 - // 设置  
626 - for (size_t i = 0; i < cat_list.size(); i++) {  
627 - cat_list[i].parentid = deviceid;  
628 - }  
629 - }  
630 - }  
631 -  
632 - return cat_list;  
633 -}  
634 -  
635 -string CCatalogParser::getItemValue(tinyxml2::XMLNode *pItem) {  
636 -  
637 - tinyxml2::XMLNode *pValue = pItem->FirstChild();  
638 - if( pValue == NULL ) {  
639 - LOG_DEBUG( "参数值没有设置" );  
640 - return "";  
641 - }  
642 -  
643 - const char *value = pValue->Value();  
644 - if( value == NULL ) {  
645 - LOG_DEBUG( "参数值为空" );  
646 - return "";  
647 - }  
648 -  
649 - return value;  
650 -}  
651 -  
652 -ServerInfo CCatalogParser::DecodeServerConfig(const char* body)  
653 -{  
654 - ServerInfo info;  
655 - if (body == NULL) {  
656 - return info;  
657 - }  
658 -  
659 - tinyxml2::XMLDocument doc;  
660 - doc.Parse(body);  
661 - tinyxml2::XMLElement* pRoot = doc.RootElement();  
662 - if (pRoot == NULL) {  
663 - return info;  
664 - }  
665 -  
666 - for (tinyxml2::XMLNode* pNode = pRoot->FirstChild(); pNode != 0; pNode = pNode->NextSibling())  
667 - {  
668 - std::string type = pNode->Value();  
669 - if (CGBMessage::CompareNoCase( type, "Ua" ))  
670 - {  
671 - info.setUa(getItemValue(pNode));  
672 - }  
673 - else if (CGBMessage::CompareNoCase( type, "Nonce" ))  
674 - {  
675 - info.setNonce(getItemValue(pNode));  
676 - }  
677 - else if (CGBMessage::CompareNoCase( type, "Ip" ))  
678 - {  
679 - info.setIp(getItemValue(pNode));  
680 - }  
681 - else if (CGBMessage::CompareNoCase( type, "Port" ))  
682 - {  
683 - string str = getItemValue(pNode);  
684 - int i = atoi(str.c_str());  
685 - info.setPort(i);  
686 - }  
687 - else if (CGBMessage::CompareNoCase( type, "SipId" ))  
688 - {  
689 - info.setSipId(getItemValue(pNode));  
690 - }  
691 - else if (CGBMessage::CompareNoCase( type, "SipRealm" )) {  
692 - info.setSipRealm(getItemValue(pNode));  
693 - }  
694 - else if (CGBMessage::CompareNoCase( type, "Password" )) {  
695 - info.setSipPass(getItemValue(pNode));  
696 - }  
697 - else if (CGBMessage::CompareNoCase( type, "Timeout" )) {  
698 - string str = getItemValue(pNode);  
699 - int i = atoi(str.c_str());  
700 - info.setTimeout(i);  
701 - } else if (CGBMessage::CompareNoCase( type, "Expiry" )) {  
702 - string str = getItemValue(pNode);  
703 - int i = atoi(str.c_str());  
704 - info.setExpiry(i);  
705 - } else if (CGBMessage::CompareNoCase( type, "MinRtpPort" )) {  
706 - string str = getItemValue(pNode);  
707 - int i = atoi(str.c_str());  
708 - info.setMinRtpPort(i);  
709 - } else if (CGBMessage::CompareNoCase( type, "MaxRtpPort" )) {  
710 - string str = getItemValue(pNode);  
711 - int i = atoi(str.c_str());  
712 - info.setMaxRtpPort(i);  
713 - }  
714 - }  
715 -  
716 - return info;  
717 -}  
718 \ No newline at end of file 0 \ No newline at end of file
src/decoder/gb28181/sip/Message/CatalogParser.h deleted
1 -#ifndef MSG_NOTIFY_MSG_HPP_  
2 -#define MSG_NOTIFY_MSG_HPP_  
3 -  
4 -#include "GBMessage.h"  
5 -#include <vector>  
6 -  
7 -#include "../sip_header.h"  
8 -  
9 -class CCatalogParser : public CGBMessage  
10 -{  
11 -public:  
12 - CCatalogParser()  
13 - {  
14 - }  
15 -  
16 -public:  
17 - bool Encode( std::string &message );  
18 -  
19 - std::vector<DeviceInfo> DecodeCatlog(const char* body);  
20 -  
21 - ServerInfo DecodeServerConfig(const char* body);  
22 -  
23 - static std::string GetStrName(EEventType eType)  
24 - {  
25 - switch (eType)  
26 - {  
27 - case EVENT_ON:  
28 - return "ON";  
29 - case EVENT_OFF:  
30 - return "OFF";  
31 - case EVENT_VLOST:  
32 - return "VLOST";  
33 - case EVENT_DEFECT:  
34 - return "DEFECT";  
35 - case EVENT_ADD:  
36 - return "ADD";  
37 - case EVENT_DEL:  
38 - return "DEL";  
39 - case EVENT_UPDATE:  
40 - return "UPDATE";  
41 - default: //EVENT_UNKNOW  
42 - return "UNKNOW";  
43 - }  
44 -  
45 - return "UNKNOW";  
46 - }  
47 -  
48 - EEventType GetEnumName(const std::string &sType)  
49 - {  
50 - if (sType == "ON")  
51 - return EVENT_ON;  
52 - if (sType == "OFF")  
53 - return EVENT_OFF;  
54 - if (sType == "VLOSE")  
55 - return EVENT_VLOST;  
56 - if (sType == "DEFECT")  
57 - return EVENT_DEFECT;  
58 - if (sType == "ADD")  
59 - return EVENT_ADD;  
60 - if (sType == "DEL")  
61 - return EVENT_DEL;  
62 - if (sType == "UPDATE")  
63 - return EVENT_UPDATE;  
64 -  
65 - return EVENT_UNKNOW;  
66 -  
67 - }  
68 -  
69 -  
70 -public:  
71 -  
72 - inline const std::string& GetSN() const  
73 - {  
74 - return m_sn;  
75 - }  
76 -  
77 - inline const std::string& GetDeviceID() const  
78 - {  
79 - return m_deviceid;  
80 - }  
81 -  
82 - inline void SetDeviceID( const std::string &deviceid )  
83 - {  
84 - m_deviceid = deviceid;  
85 - }  
86 -  
87 - inline void SetSN( const std::string &sn )  
88 - {  
89 - m_sn = sn;  
90 - }  
91 -  
92 - inline const std::string& GetStatus() const  
93 - {  
94 - return m_status;  
95 - }  
96 -  
97 - inline void SetStatus( const std::string &status )  
98 - {  
99 - m_status = status;  
100 - }  
101 -  
102 - inline int GetSum() const  
103 - {  
104 - return m_sum;  
105 - }  
106 -  
107 - inline void SetSum( int sum )  
108 - {  
109 - m_sum = sum;  
110 - }  
111 -  
112 - inline const std::vector< DeviceInfo >& GetDevices() const  
113 - {  
114 - return m_devices;  
115 - }  
116 -  
117 - inline void AddEvent(const std::string &id, EEventType eventType)  
118 - {  
119 - DeviceInfo catalog;  
120 - catalog.id = id;  
121 - catalog.event = eventType;  
122 - m_devices.push_back( catalog );  
123 - }  
124 -  
125 - inline void AddOnEvent( const std::string &id )  
126 - {  
127 - DeviceInfo catalog;  
128 - catalog.id = id;  
129 - catalog.event = EVENT_ON;  
130 - m_devices.push_back( catalog );  
131 - }  
132 -  
133 - inline void AddOffEvent( const std::string &id )  
134 - {  
135 - DeviceInfo catalog;  
136 - catalog.id = id;  
137 - catalog.event = EVENT_OFF;  
138 - m_devices.push_back( catalog );  
139 - }  
140 -  
141 - inline void AddVLostEvent( const std::string &id )  
142 - {  
143 - DeviceInfo catalog;  
144 - catalog.id = id;  
145 - catalog.event = EVENT_VLOST;  
146 - m_devices.push_back( catalog );  
147 - }  
148 -  
149 - inline void AddDefectEvent( const std::string &id )  
150 - {  
151 - DeviceInfo catalog;  
152 - catalog.id = id;  
153 - catalog.event = EVENT_DEFECT;  
154 - m_devices.push_back( catalog );  
155 - }  
156 -  
157 - inline void AddDelEvent( const std::string &id )  
158 - {  
159 - DeviceInfo catalog;  
160 - catalog.id = id;  
161 - catalog.event = EVENT_DEL;  
162 - m_devices.push_back( catalog );  
163 - }  
164 -  
165 - inline void AddAddEvent( const DeviceInfo &catalog )  
166 - {  
167 - if( catalog.event == EVENT_ADD )  
168 - {  
169 - m_devices.push_back( catalog );  
170 - }  
171 - }  
172 -  
173 - inline void AddUpdateEvent( const DeviceInfo &catalog )  
174 - {  
175 - if( catalog.event == EVENT_UPDATE )  
176 - {  
177 - m_devices.push_back( catalog );  
178 - }  
179 - }  
180 -  
181 -private:  
182 - std::vector< DeviceInfo > Decode(const std::vector< tinyxml2::XMLNode* >& nodes);  
183 - string getItemValue(tinyxml2::XMLNode *pItem);  
184 -  
185 -private:  
186 - std::string m_sn;  
187 - std::string m_deviceid;  
188 - std::string m_status;  
189 - int m_sum;  
190 - std::vector< DeviceInfo > m_devices;  
191 -};  
192 -  
193 -#endif // MSG_NOTIFY_MSG_HPP_  
194 \ No newline at end of file 0 \ No newline at end of file
src/decoder/gb28181/sip/Message/GBMessage.cpp deleted
1 -#include "GBMessage.h"  
2 -//#include "ILocker.h"  
3 -#include <atomic>  
4 -static std::atomic<unsigned int> g_msgsn(0);  
5 -//static CLocker g_msg_lock;  
6 -  
7 -bool CGBMessage::CompareNoCase( const char *type, const char *label )  
8 -{  
9 - // 参数校验  
10 - if( type == NULL || label == NULL )  
11 - {  
12 - return false;  
13 - }  
14 -  
15 - // 比较是否相等  
16 - char ch1 = type[0];  
17 - char ch2 = label[0];  
18 - size_t i = 0;  
19 - while( ch1 != 0 && ch2 != 0 )  
20 - {  
21 - if( ch1 >= 'a' && ch1 <= 'z' )  
22 - {  
23 - ch1 -= 'a';  
24 - ch1 += 'A';  
25 - }  
26 -  
27 - if( ch2 >= 'a' && ch2 <= 'z' )  
28 - {  
29 - ch2 -= 'a';  
30 - ch2 += 'A';  
31 - }  
32 -  
33 - if( ch1 != ch2 )  
34 - {  
35 - return false;  
36 - }  
37 - else  
38 - {  
39 - ++i;  
40 - ch1 = type[i];  
41 - ch2 = label[i];  
42 - }  
43 - }  
44 -  
45 - return( ch1 == 0 && ch2 == 0 );  
46 -}  
47 -  
48 -  
49 -bool CGBMessage::CompareNoCase( const std::string &str, const char *label )  
50 -{  
51 - // 参数校验  
52 - const char* type = str.c_str();  
53 - if( type == NULL || label == NULL )  
54 - {  
55 - return false;  
56 - }  
57 -  
58 - // 比较是否相等  
59 - char ch1 = type[0];  
60 - char ch2 = label[0];  
61 - size_t i = 0;  
62 - while( ch1 != 0 && ch2 != 0 )  
63 - {  
64 - if( ch1 >= 'a' && ch1 <= 'z' )  
65 - {  
66 - ch1 -= 'a';  
67 - ch1 += 'A';  
68 - }  
69 -  
70 - if( ch2 >= 'a' && ch2 <= 'z' )  
71 - {  
72 - ch2 -= 'a';  
73 - ch2 += 'A';  
74 - }  
75 -  
76 - if( ch1 != ch2 )  
77 - {  
78 - return false;  
79 - }  
80 - else  
81 - {  
82 - ++i;  
83 - ch1 = type[i];  
84 - ch2 = label[i];  
85 - }  
86 - }  
87 -  
88 - return( ch1 == 0 && ch2 == 0 );  
89 -}  
90 -  
91 -unsigned int CGBMessage::GetNextSN()  
92 -{  
93 - //CNPAutoLock locker( g_msg_lock );  
94 - g_msgsn++;  
95 - return g_msgsn;  
96 -}  
97 -  
98 -bool CGBMessage::DecodeSubject()  
99 -{  
100 - std::vector< std::string > vec;  
101 - size_t b = 0;  
102 - size_t e = 0;  
103 - while( b != std::string::npos )  
104 - {  
105 - e = m_subject.find_first_of( ',', b );  
106 - vec.push_back( m_subject.substr( b, e ) );  
107 - if( e != std::string::npos )  
108 - {  
109 - b = e + 1;  
110 - }  
111 - else  
112 - {  
113 - break;  
114 - }  
115 - }  
116 -  
117 - if( vec.size() != 2 )  
118 - {  
119 - return false;  
120 - }  
121 -  
122 - //  
123 - std::string send = vec[0];  
124 - std::string recv = vec[1];  
125 -  
126 - // 发送者ID和序列号  
127 - vec.clear();  
128 - b = 0;  
129 - while( b != std::string::npos )  
130 - {  
131 - e = send.find_first_of( ':', b );  
132 - vec.push_back( send.substr( b, e ) );  
133 - if( e != std::string::npos )  
134 - {  
135 - b = e + 1;  
136 - }  
137 - else  
138 - {  
139 - break;  
140 - }  
141 - }  
142 -  
143 - if( vec.size() != 2 )  
144 - {  
145 - return false;  
146 - }  
147 - else  
148 - {  
149 - m_sender.id = vec[0];  
150 - m_sender.seq = vec[1];  
151 - }  
152 -  
153 - // 接收者ID和序列号  
154 - vec.clear();  
155 - b = 0;  
156 - while( b != std::string::npos )  
157 - {  
158 - e = recv.find_first_of( ':', b );  
159 - vec.push_back( recv.substr( b, e ) );  
160 - if( e != std::string::npos )  
161 - {  
162 - b = e + 1;  
163 - }  
164 - else  
165 - {  
166 - break;  
167 - }  
168 - }  
169 -  
170 - if( vec.size() != 2 )  
171 - {  
172 - return false;  
173 - }  
174 - else  
175 - {  
176 - m_recver.id = vec[0];  
177 - m_recver.seq = vec[1];  
178 - }  
179 -  
180 - return true;  
181 -}  
182 -  
src/decoder/gb28181/sip/Message/GBMessage.h deleted
1 -#ifndef GBMESSAGE_HPP_  
2 -#define GBMESSAGE_HPP_  
3 -  
4 -#include <sstream>  
5 -#include <iostream>  
6 -#include <string>  
7 -#include <vector>  
8 -#include "../tinyxml2/tinyxml2.h"  
9 -  
10 -  
11 -#if defined(CATCH_RESIP_EXCEPTION)  
12 -#undef __DUM_TRY  
13 -#undef __DUM_CATCH  
14 -#define __DUM_TRY try {  
15 -#define __DUM_CATCH \  
16 -} catch(resip::DumException* be) { \  
17 - resip::Data ex; \  
18 - ex = "RESIP ³öÏÖÒì³££ºname = "; \  
19 - ex += be->name(); \  
20 - ex += "£¬what = "; \  
21 - ex += be->what(); \  
22 - throw new std::exception(ex.c_str()); \  
23 -}  
24 -#else  
25 -#undef __DUM_TRY  
26 -#undef __DUM_CATCH  
27 -#define __DUM_TRY  
28 -#define __DUM_CATCH  
29 -#endif  
30 -  
31 -  
32 -class CGBMessage  
33 -{  
34 -public:  
35 - enum EGBResultType  
36 - {  
37 - RESULT_OK = 0,  
38 - RESULT_ERROR,  
39 - };  
40 -  
41 - struct SDate  
42 - {  
43 - int year;  
44 - int month;  
45 - int day;  
46 - int hour;  
47 - int minute;  
48 - int second;  
49 - int millisecond;  
50 - };  
51 -  
52 - struct SSubject  
53 - {  
54 - std::string id;  
55 - std::string seq;  
56 - };  
57 -  
58 - struct SUserIdentity  
59 - {  
60 - std::string user;  
61 - std::string deviceid;  
62 - std::string organization;  
63 - std::string policetype;  
64 - std::string duty;  
65 - };  
66 -  
67 -public:  
68 - CGBMessage() : m_adjusttime( false ), m_port( 0 ), m_cseq( 0 ), m_forwards( 0 ), m_expires( 0 ), m_statusCode( 0 )  
69 - {  
70 - }  
71 -  
72 - virtual ~CGBMessage()  
73 - {  
74 - }  
75 -  
76 -private:  
77 - CGBMessage( const CGBMessage &rhs );  
78 - CGBMessage& operator=( const CGBMessage &rhs );  
79 -  
80 -public:  
81 - inline bool Ok() const  
82 - {  
83 - return( m_statusCode == 200 );  
84 - }  
85 -  
86 - inline bool AdjustTime() const  
87 - {  
88 - return m_adjusttime;  
89 - }  
90 -  
91 - inline const std::string& GetSubjectSendID() const  
92 - {  
93 - return m_sender.id;  
94 - }  
95 -  
96 - inline const std::string& GetSubjectSendSeq() const  
97 - {  
98 - return m_sender.seq;  
99 - }  
100 -  
101 - inline const std::string& GetSubjectRecvID() const  
102 - {  
103 - return m_recver.id;  
104 - }  
105 -  
106 - inline const std::string& GetSubjectRecvSeq() const  
107 - {  
108 - return m_recver.seq;  
109 - }  
110 -  
111 - inline const std::string& GetUser() const  
112 - {  
113 - return m_request;  
114 - }  
115 -  
116 - inline const std::string& GetSubject() const  
117 - {  
118 - return m_subject;  
119 - }  
120 -  
121 - inline const std::string& GetFrom() const  
122 - {  
123 - return m_from;  
124 - }  
125 -  
126 - inline const std::string& GetFromTag() const  
127 - {  
128 - return m_tagfrom;  
129 - }  
130 -  
131 - inline const std::string& GetTo() const  
132 - {  
133 - return m_to;  
134 - }  
135 -  
136 - inline const std::string& GetToTag() const  
137 - {  
138 - return m_tagto;  
139 - }  
140 -  
141 - inline unsigned long GetCSeq() const  
142 - {  
143 - return m_cseq;  
144 - }  
145 -  
146 - inline int GetStatusCode() const  
147 - {  
148 - return m_statusCode;  
149 - }  
150 -  
151 - inline int GetMaxFrowards() const  
152 - {  
153 - return m_forwards;  
154 - }  
155 -  
156 - inline int GetExpires() const  
157 - {  
158 - return m_expires;  
159 - }  
160 -  
161 - inline const std::string& GetIP() const  
162 - {  
163 - return m_ip;  
164 - }  
165 -  
166 - inline int GetPort() const  
167 - {  
168 - return m_port;  
169 - }  
170 -  
171 - inline const std::string& GetCallID() const  
172 - {  
173 - return m_callid;  
174 - }  
175 -  
176 - inline const SDate& GetDate() const  
177 - {  
178 - return m_date;  
179 - }  
180 -  
181 - inline const SUserIdentity& GetUserIdentity() const  
182 - {  
183 - return m_useridentity;  
184 - }  
185 -  
186 - inline const std::vector< std::string >& GetContacts() const  
187 - {  
188 - return m_contacts;  
189 - }  
190 -  
191 - inline const std::vector< std::string >& GetVias() const  
192 - {  
193 - return m_vias;  
194 - }  
195 -  
196 - inline void SetSubjectSendID( const std::string &id )  
197 - {  
198 - m_sender.id = id;  
199 - }  
200 -  
201 - inline void SetSubjectSendSeq( const std::string &seq )  
202 - {  
203 - m_sender.seq = seq;  
204 - }  
205 -  
206 - inline void SetSubjectRecvID( const std::string &id )  
207 - {  
208 - m_recver.id = id;  
209 - }  
210 -  
211 - inline void SetSubjectRecvSeq( const std::string &seq )  
212 - {  
213 - m_recver.seq = seq;  
214 - }  
215 -  
216 - inline void SetUser( const char *user )  
217 - {  
218 - if( user != NULL )  
219 - {  
220 - m_request = user;  
221 - }  
222 - }  
223 -  
224 - inline void SetUser( const std::string &user )  
225 - {  
226 - m_request = user;  
227 - }  
228 -  
229 - inline void SetSubject( const char *uri )  
230 - {  
231 - if( uri != NULL )  
232 - {  
233 - m_subject = uri;  
234 - DecodeSubject();  
235 - }  
236 - }  
237 -  
238 - inline void SetSubject( const std::string &uri )  
239 - {  
240 - m_subject = uri;  
241 - DecodeSubject();  
242 - }  
243 -  
244 - inline void SetFrom( const char *code )  
245 - {  
246 - if( code != NULL )  
247 - {  
248 - m_from = code;  
249 - }  
250 - }  
251 -  
252 - inline void SetFrom( const std::string &code )  
253 - {  
254 - m_from = code;  
255 - }  
256 -  
257 - inline void SetFromTag( const char *tag )  
258 - {  
259 - if( tag != NULL )  
260 - {  
261 - m_tagfrom = tag;  
262 - }  
263 - }  
264 -  
265 - inline void SetFromTag( const std::string &code )  
266 - {  
267 - m_tagfrom = code;  
268 - }  
269 -  
270 - inline void SetTo( const char *code )  
271 - {  
272 - if( code != NULL )  
273 - {  
274 - m_to = code;  
275 - }  
276 - }  
277 -  
278 - inline void SetTo( const std::string &code )  
279 - {  
280 - m_to = code;  
281 - }  
282 -  
283 - inline void SetToTag( const char *tag )  
284 - {  
285 - if( tag != NULL )  
286 - {  
287 - m_tagto = tag;  
288 - }  
289 - }  
290 -  
291 - inline void SetToTag( const std::string &tag )  
292 - {  
293 - m_tagto = tag;  
294 - }  
295 -  
296 - inline void SetCSeq( unsigned long cseq )  
297 - {  
298 - m_cseq = cseq;  
299 - }  
300 -  
301 - inline void SetExpires( int expires )  
302 - {  
303 - m_expires = expires;  
304 - }  
305 -  
306 - inline void SetStatusCode( int code )  
307 - {  
308 - m_statusCode = code;  
309 - }  
310 -  
311 - inline void SetMaxFrowards( int forwards )  
312 - {  
313 - m_forwards = forwards;  
314 - }  
315 -  
316 - inline void SetCallID( const char *callid )  
317 - {  
318 - if( callid != NULL )  
319 - {  
320 - m_callid = callid;  
321 - }  
322 - }  
323 -  
324 - inline void SetCallID( const std::string &callid )  
325 - {  
326 - m_callid = callid;  
327 - }  
328 -  
329 - inline void SetIP( const std::string &ip )  
330 - {  
331 - m_ip = ip;  
332 - }  
333 -  
334 - inline void SetIP( const char *ip )  
335 - {  
336 - if( ip != NULL )  
337 - {  
338 - m_ip = ip;  
339 - }  
340 - }  
341 -  
342 - inline void SetPort( int port )  
343 - {  
344 - m_port = port;  
345 - }  
346 -  
347 - inline void SetDate( int year, int month, int day, int hour, int minute, int second, int millisecond )  
348 - {  
349 - m_adjusttime = true;  
350 - m_date.year = year;  
351 - m_date.month = month;  
352 - m_date.day = day;  
353 - m_date.hour = hour;  
354 - m_date.minute = minute;  
355 - m_date.second = second;  
356 - m_date.millisecond = millisecond;  
357 - }  
358 -  
359 - inline void AddContacts( const char *contacts )  
360 - {  
361 - if( contacts != NULL )  
362 - {  
363 - m_contacts.push_back( contacts );  
364 - }  
365 - }  
366 -  
367 - inline void AddContacts( const std::string &contacts )  
368 - {  
369 - m_contacts.push_back( contacts );  
370 - }  
371 -  
372 - inline void AddVias( const char *host, long port )  
373 - {  
374 - if( host != NULL )  
375 - {  
376 - char buf[16] = { 0 };  
377 - sprintf( buf, "%d", port );  
378 - std::string via = host;  
379 - via += ":";  
380 - via += buf;  
381 - m_vias.push_back( via );  
382 - }  
383 - }  
384 -  
385 - inline void AddVias( const std::string &host, long port )  
386 - {  
387 - char buf[16] = { 0 };  
388 - sprintf( buf, "%d", port );  
389 - std::string via = host;  
390 - via += ":";  
391 - via += buf;  
392 - m_vias.push_back( via );  
393 - }  
394 -  
395 - inline void SetUserIdentity( const std::string &user, const std::string& deviceid, const std::string& organization, const std::string& policetype, const std::string& duty )  
396 - {  
397 - m_useridentity.user = user;  
398 - m_useridentity.deviceid = deviceid;  
399 - m_useridentity.organization = organization;  
400 - m_useridentity.policetype = policetype;  
401 - m_useridentity.duty = duty;  
402 - }  
403 -  
404 -public:  
405 -  
406 - virtual bool Response( int status )  
407 - {  
408 - return false;  
409 - }  
410 -  
411 -public:  
412 - static bool CompareNoCase( const char *type, const char *label );  
413 - static bool CompareNoCase( const std::string &type, const char *label );  
414 - static unsigned int GetNextSN();  
415 - bool DecodeSubject();  
416 -  
417 -protected:  
418 - SSubject m_sender; // subject  
419 - SSubject m_recver; // subject  
420 - std::string m_request;  
421 - std::string m_subject;  
422 - std::string m_callid;  
423 - std::string m_from;  
424 - std::string m_tagfrom;  
425 - std::string m_to;  
426 - std::string m_tagto;  
427 - SDate m_date;  
428 - std::vector< std::string > m_contacts;  
429 - std::vector< std::string > m_vias;  
430 - std::string m_ip;  
431 - bool m_adjusttime; // message has date header  
432 - int m_port;  
433 - unsigned long m_cseq;  
434 - int m_forwards;  
435 - int m_expires;  
436 - int m_statusCode;  
437 - SUserIdentity m_useridentity;  
438 -};  
439 -  
440 -//////////////////////////////////////////////////////////////////////////  
441 -#endif // GBMESSAGE_HPP_  
src/decoder/gb28181/sip/SipServer.cpp deleted
1 -//  
2 -// Created bxc on 2022/11/25.  
3 -//  
4 -  
5 -#include "SipServer.h"  
6 -  
7 -#ifndef WIN32  
8 -// Linux系统  
9 -#include <arpa/inet.h>  
10 -#else  
11 -#include <WinSock2.h>  
12 -#pragma comment(lib, "ws2_32.lib")  
13 -#endif // !WIN32  
14 -  
15 -#include <cstring>  
16 -#include "../common_header.h"  
17 -#include "./Utils/HTTPDigest.h"  
18 -  
19 -#include <sstream>  
20 -#include <algorithm>  
21 -#include <fstream>  
22 -  
23 -using namespace std;  
24 -  
25 -static void event_loop_thread(void* arg) {  
26 - SipServer* _this = (SipServer*)arg;  
27 - if (_this != nullptr) {  
28 - _this->event_loop();  
29 - }  
30 - else {  
31 - LOG_ERROR("event_loop线程启动失败 !");  
32 - }  
33 -}  
34 -  
35 -static void timing_getcatlog_thread(void* arg) {  
36 - SipServer* _this = (SipServer*)arg;  
37 - if (_this != nullptr) {  
38 - _this->timing_getcatlog();  
39 - }  
40 - else {  
41 - LOG_ERROR("timing_getcatlog 线程启动失败 !");  
42 - }  
43 -}  
44 -  
45 -static void dt_printSipMsg(osip_message_t* msg) {  
46 - osip_message_t* clone_event = NULL;  
47 - size_t length = 0;  
48 - char* message = NULL;  
49 - osip_message_clone(msg, &clone_event);  
50 - osip_message_to_str(clone_event, &message, &length);  
51 - LOG_INFO("{}", message);  
52 -}  
53 -  
54 -static bool isntspace(const char &ch) {  
55 - return !isspace(ch);  
56 -}  
57 -  
58 -static std::string trim(const std::string &s) {  
59 - std::string::const_iterator iter1 = find_if(s.begin(), s.end(), isntspace);  
60 - std::string::const_iterator iter2 = find_if(s.rbegin(), s.rend(), isntspace).base();  
61 -  
62 - return iter1 < iter2 ? string(iter1, iter2) : std::string("");  
63 -}  
64 -  
65 -SipServer::SipServer():  
66 - mQuit(false),  
67 - mSipCtx(nullptr){  
68 -#ifdef WIN32  
69 - WSADATA wsaData;  
70 - if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)  
71 - {  
72 - LOG_ERROR("WSAStartup Error");  
73 - return;  
74 - }  
75 -#endif // WIN32  
76 -  
77 -}  
78 -SipServer::~SipServer() {  
79 - LOG_INFO("~SipServer");  
80 -  
81 - if (m_event_loop_thread)  
82 - {  
83 - mQuit = true;  
84 - m_event_loop_thread->join();  
85 -  
86 - delete m_event_loop_thread;  
87 - m_event_loop_thread = nullptr;  
88 - }  
89 -  
90 - this->clearClientMap();  
91 -#ifdef WIN32  
92 - WSACleanup();  
93 -#endif // WIN32  
94 -}  
95 -  
96 -bool SipServer::Init(ServerInfo* pInfo) {  
97 -  
98 - if (pInfo == nullptr) {  
99 - std::ifstream cfgFile("./sip_server_cfg.xml");  
100 - if(cfgFile.is_open()) {  
101 - string strConfig;  
102 - string str;  
103 - int char_count = 0;  
104 - while(cfgFile >> str)  
105 - {  
106 - strConfig += str;  
107 - }  
108 - CCatalogParser catPaser;  
109 - mInfo = catPaser.DecodeServerConfig(strConfig.c_str());  
110 - } else {  
111 - LOG_ERROR("read sip server config file failed!");  
112 - return false;  
113 - }  
114 - cfgFile.close();  
115 - } else {  
116 - mInfo = *pInfo;  
117 - }  
118 -  
119 - LOG_INFO("{}:{}", mInfo.getIp(), mInfo.getPort());  
120 -  
121 - m_event_loop_thread = new std::thread(event_loop_thread, this);  
122 -  
123 - return true;  
124 -}  
125 -  
126 -int SipServer::GetMinRtpPort(){  
127 - return mInfo.getMinRtpPort();  
128 -}  
129 -  
130 -int SipServer::GetMaxRtpPort(){  
131 - return mInfo.getMaxRtpPort();  
132 -}  
133 -  
134 -int SipServer::sip_event_handle(eXosip_event_t *evtp) {  
135 -  
136 - switch(evtp->type) {  
137 - case EXOSIP_CALL_MESSAGE_NEW://14  
138 - // LOG_INFO("EXOSIP_CALL_MESSAGE_NEW type={}", evtp->type);  
139 - this->dump_request(evtp);  
140 - this->dump_response(evtp);  
141 - break;  
142 -  
143 - case EXOSIP_CALL_CLOSED://21  
144 - LOG_INFO("EXOSIP_CALL_CLOSED type={}",evtp->type);  
145 - this->dump_request(evtp);  
146 - this->dump_response(evtp);  
147 - break;  
148 -  
149 - case EXOSIP_CALL_RELEASED://22  
150 - LOG_INFO("EXOSIP_CALL_RELEASED type={}", evtp->type);  
151 - this->dump_request(evtp);  
152 - this->dump_response(evtp);  
153 -  
154 - // this->clearClientMap();  
155 - break;  
156 - case EXOSIP_MESSAGE_NEW://23  
157 - // LOG_INFO("EXOSIP_MESSAGE_NEW type={}",evtp->type);  
158 -  
159 - if (MSG_IS_REGISTER(evtp->request)) {  
160 - this->response_register(evtp);  
161 - }  
162 - else if (MSG_IS_MESSAGE(evtp->request)) {  
163 - this->response_message(evtp);  
164 - }  
165 - else if(MSG_IS_BYE(evtp->request)){  
166 - LOG_ERROR("BYE");  
167 - }  
168 - else{  
169 - LOG_ERROR("unknown2");  
170 - }  
171 - break;  
172 - case EXOSIP_MESSAGE_ANSWERED:  
173 - this->dump_request(evtp);  
174 - break;  
175 - case EXOSIP_MESSAGE_REQUESTFAILURE:  
176 - LOG_INFO("EXOSIP_MESSAGE_REQUESTFAILURE type={}: Receive feedback on sending failure after actively sending a message", evtp->type);  
177 - this->dump_request(evtp);  
178 - this->dump_response(evtp);  
179 - break;  
180 - case EXOSIP_CALL_INVITE:  
181 - LOG_INFO("EXOSIP_CALL_INVITE type={}: The server receives the Invite request actively sent by the client", evtp->type);  
182 - break;  
183 - case EXOSIP_CALL_PROCEEDING://5  
184 - LOG_INFO("EXOSIP_CALL_PROCEEDING type={}: When the server receives the Invite (SDP) confirmation reply from the client", evtp->type);  
185 - this->dump_request(evtp);  
186 - this->dump_response(evtp);  
187 - break;  
188 - case EXOSIP_CALL_ANSWERED:// 7  
189 - LOG_INFO("EXOSIP_CALL_ANSWERED type={}: The server receives an invite (SDP) confirmation reply from the client", evtp->type);  
190 - this->dump_request(evtp);  
191 - this->dump_response(evtp);  
192 -  
193 - this->response_invite_ack(evtp);  
194 - break;  
195 - case EXOSIP_CALL_SERVERFAILURE:  
196 - LOG_INFO("EXOSIP_CALL_SERVERFAILURE type={}", evtp->type);  
197 - break;  
198 - case EXOSIP_IN_SUBSCRIPTION_NEW:  
199 - LOG_INFO("EXOSIP_IN_SUBSCRIPTION_NEW type={}", evtp->type);  
200 - break;  
201 - default:  
202 - LOG_INFO("type={} unknown", evtp->type);  
203 - break;  
204 - }  
205 -  
206 - return 0;  
207 -}  
208 -  
209 -int SipServer::init_sip_server() {  
210 - mSipCtx = eXosip_malloc();  
211 - if (!mSipCtx) {  
212 - LOG_ERROR("eXosip_malloc error");  
213 - return -1;  
214 - }  
215 - if (eXosip_init(mSipCtx)) {  
216 - LOG_ERROR("eXosip_init error");  
217 - return -1;  
218 - }  
219 - if (eXosip_listen_addr(mSipCtx, IPPROTO_UDP, nullptr, mInfo.getPort(), AF_INET, 0)) {  
220 - LOG_ERROR("eXosip_listen_addr error");  
221 - return -1;  
222 - }  
223 - eXosip_set_user_agent(mSipCtx, mInfo.getUa().c_str());  
224 - if (eXosip_add_authentication_info(mSipCtx, mInfo.getSipId().c_str(), mInfo.getSipId().c_str(), mInfo.getSipPass().c_str(), NULL, mInfo.getSipRealm().c_str())) {  
225 - LOG_ERROR("eXosip_add_authentication_info error");  
226 - return -1;  
227 - }  
228 -  
229 - return 0;  
230 -}  
231 -  
232 -void SipServer::event_loop() {  
233 -  
234 - if(this->init_sip_server() !=0 ){  
235 - return;  
236 - }  
237 -  
238 - thread* timing_getcatlog_threadptr = new std::thread(timing_getcatlog_thread, this);  
239 -  
240 - while(!mQuit) {  
241 - eXosip_event_t *evtp = eXosip_event_wait(mSipCtx, 0, 20);  
242 - if (!evtp){  
243 - eXosip_automatic_action(mSipCtx);  
244 - osip_usleep(100000);  
245 - continue;  
246 - }  
247 - eXosip_automatic_action(mSipCtx);  
248 - this->sip_event_handle(evtp);  
249 - eXosip_event_free(evtp);  
250 - }  
251 -  
252 - mQuit = true;  
253 - if (timing_getcatlog_threadptr) {  
254 - timing_getcatlog_threadptr->join();  
255 - delete timing_getcatlog_threadptr;  
256 - timing_getcatlog_threadptr = nullptr;  
257 - }  
258 -}  
259 -  
260 -void SipServer::Close() {  
261 - mQuit = true;  
262 -  
263 - if (m_event_loop_thread) {  
264 - m_event_loop_thread->join();  
265 - delete m_event_loop_thread;  
266 - m_event_loop_thread = nullptr;  
267 - }  
268 -  
269 -}  
270 -  
271 -void SipServer::timing_getcatlog() {  
272 - while(!mQuit) {  
273 - // 5分钟更新一次  
274 - std::this_thread::sleep_for(std::chrono::minutes(5));  
275 - cacheCatalog();  
276 - }  
277 -}  
278 -  
279 -void SipServer::response_message_answer(eXosip_event_t *evtp,int code){  
280 -  
281 - int returnCode = 0 ;  
282 - osip_message_t * pRegister = nullptr;  
283 - returnCode = eXosip_message_build_answer (mSipCtx,evtp->tid,code,&pRegister);  
284 - bool bRegister = false;  
285 - if(pRegister){  
286 - bRegister = true;  
287 - }  
288 - if (returnCode == 0 && bRegister)  
289 - {  
290 - eXosip_lock(mSipCtx);  
291 - eXosip_message_send_answer (mSipCtx,evtp->tid,code,pRegister);  
292 - eXosip_unlock(mSipCtx);  
293 - }  
294 - else{  
295 - LOG_ERROR("code={},returnCode={},bRegister={}",code,returnCode,bRegister);  
296 - }  
297 -  
298 -}  
299 -void SipServer::response_register(eXosip_event_t *evtp) {  
300 -  
301 - osip_authorization_t * auth = nullptr;  
302 - osip_message_get_authorization(evtp->request, 0, &auth);  
303 -  
304 - if(auth && auth->username){  
305 -  
306 - char *method = NULL, // REGISTER  
307 - *algorithm = NULL, // MD5  
308 - *username = NULL,// 340200000013200000024  
309 - *realm = NULL, // sip服务器传给客户端,客户端携带并提交上来的sip服务域  
310 - *nonce = NULL, //sip服务器传给客户端,客户端携带并提交上来的nonce  
311 - *nonce_count = NULL,  
312 - *uri = NULL; // sip:34020000002000000001@3402000000  
313 -  
314 - osip_contact_t *contact = nullptr;  
315 - osip_message_get_contact (evtp->request, 0, &contact);  
316 -  
317 - method = evtp->request->sip_method;  
318 - char calc_response[HASHHEXLEN];  
319 - HASHHEX HA1, HA2 = "", Response;  
320 -  
321 -#define SIP_STRDUP(field) if (auth->field) (field) = osip_strdup_without_quote(auth->field)  
322 -  
323 - SIP_STRDUP(algorithm);  
324 - SIP_STRDUP(username);  
325 - SIP_STRDUP(realm);  
326 - SIP_STRDUP(nonce);  
327 - SIP_STRDUP(nonce_count);  
328 - SIP_STRDUP(uri);  
329 -  
330 - DigestCalcHA1(algorithm, username, realm, mInfo.getSipPass().c_str(), nonce, nonce_count, HA1);  
331 - DigestCalcResponse(HA1, nonce, nonce_count, auth->cnonce, auth->message_qop, 0, method, uri, HA2, Response);  
332 -  
333 - HASHHEX temp_HA1;  
334 - HASHHEX temp_response;  
335 - DigestCalcHA1("REGISTER", username, mInfo.getSipRealm().c_str(), mInfo.getSipPass().c_str(), mInfo.getNonce().c_str(), NULL, temp_HA1);  
336 - DigestCalcResponse(temp_HA1, mInfo.getNonce().c_str(), NULL, NULL, NULL, 0, method, uri, NULL, temp_response);  
337 - memcpy(calc_response, temp_response, HASHHEXLEN);  
338 -  
339 -  
340 -  
341 - if (!memcmp(calc_response, Response, HASHHEXLEN)) {  
342 - this->response_message_answer(evtp,200);  
343 -  
344 - Client* client = new Client(strdup(contact->url->host),  
345 - atoi(contact->url->port),  
346 - strdup(username));  
347 -  
348 - LOG_INFO("Camera registration succee,ip={},port={},device={}",client->getIp(),client->getPort(),client->getDevice());  
349 -  
350 - std::lock_guard<std::mutex> l(m_client_map_mtx);  
351 -  
352 - auto it_client = mClientMap.find(client->getDevice());  
353 - if (it_client != mClientMap.end()) {  
354 - Client* c = it_client->second;  
355 - delete c;  
356 - c = nullptr;  
357 - mClientMap.erase(it_client);  
358 - }  
359 -  
360 - mClientMap.insert(std::make_pair(client->getDevice(),client));  
361 -  
362 - // NVR注册成功,立即请求设备目录  
363 - RequestCatalog(client);  
364 -  
365 - } else {  
366 - this->response_message_answer(evtp,401);  
367 - LOG_INFO("Camera registration error, p={},port={},device={}", strdup(contact->url->host), atoi(contact->url->port), strdup(username));  
368 - }  
369 -  
370 - osip_free(algorithm);  
371 - osip_free(username);  
372 - osip_free(realm);  
373 - osip_free(nonce);  
374 - osip_free(nonce_count);  
375 - osip_free(uri);  
376 - } else {  
377 - response_register_401unauthorized(evtp);  
378 - }  
379 -  
380 -}  
381 -  
382 -void SipServer::response_register_401unauthorized(eXosip_event_t *evtp) {  
383 -  
384 - char *dest = nullptr;  
385 - osip_message_t * reg = nullptr;  
386 - osip_www_authenticate_t * header = nullptr;  
387 -  
388 - osip_www_authenticate_init(&header);  
389 - osip_www_authenticate_set_auth_type (header, osip_strdup("Digest"));  
390 - osip_www_authenticate_set_realm(header,osip_enquote(mInfo.getSipRealm().c_str()));  
391 - osip_www_authenticate_set_nonce(header,osip_enquote(mInfo.getNonce().c_str()));  
392 - osip_www_authenticate_to_str(header, &dest);  
393 - int ret = eXosip_message_build_answer (mSipCtx, evtp->tid, 401, &reg);  
394 - if ( ret == 0 && reg != nullptr ) {  
395 - osip_message_set_www_authenticate(reg, dest);  
396 - osip_message_set_content_type(reg, "Application/MANSCDP+xml");  
397 - eXosip_lock(mSipCtx);  
398 - eXosip_message_send_answer (mSipCtx, evtp->tid,401, reg);  
399 - eXosip_unlock(mSipCtx);  
400 - LOG_INFO("response_register_401unauthorized success");  
401 - }else {  
402 - LOG_INFO("response_register_401unauthorized error");  
403 - }  
404 -  
405 - osip_www_authenticate_free(header);  
406 - osip_free(dest);  
407 -  
408 -}  
409 -  
410 -void printDevice(std::vector<DeviceInfo> vec_device) {  
411 - LOG_INFO("-----start print----");  
412 - for (size_t i = 0; i < vec_device.size(); i++) {  
413 - LOG_INFO("{} {}", vec_device[i].id, vec_device[i].parentid);  
414 - }  
415 - LOG_INFO("-----end print----");  
416 -}  
417 -  
418 -void SipServer::response_message(eXosip_event_t *evtp) {  
419 -  
420 - osip_body_t* body = nullptr;  
421 - char CmdType[64] = {0};  
422 - char DeviceID[64] = {0};  
423 - osip_message_get_body(evtp->request, 0, &body);  
424 - if(body){  
425 - parse_xml(body->body, "<CmdType>", false, "</CmdType>", false, CmdType);  
426 - parse_xml(body->body, "<DeviceID>", false, "</DeviceID>", false, DeviceID);  
427 - }  
428 -  
429 - if(!strcmp(CmdType, "Catalog")) {  
430 - this->response_message_answer(evtp,200);  
431 - // 需要根据对方的Catelog请求,做一些相应的应答请求  
432 - CCatalogParser catPaser;  
433 - std::vector<DeviceInfo> vec_device = catPaser.DecodeCatlog(body->body);  
434 - printDevice(vec_device);  
435 -  
436 - std::lock_guard<std::mutex> l(m_device_map_mtx);  
437 - for (size_t i = 0; i < vec_device.size(); i++) {  
438 - DeviceInfo info = vec_device[i];  
439 - m_device_map[info.id] = info;  
440 - }  
441 - }  
442 - else if(!strcmp(CmdType, "Keepalive")){  
443 - this->response_message_answer(evtp,200);  
444 - // LOG_INFO("CmdType={},DeviceID={}", CmdType, DeviceID);  
445 - std::lock_guard<std::mutex> l_c(m_client_map_mtx);  
446 - Client* client = mClientMap[DeviceID];  
447 - if (client != nullptr) {  
448 - client->updateHeartBeat(UtilTools::get_cur_time_ms());  
449 - }  
450 - }else{  
451 - this->response_message_answer(evtp,200);  
452 - }  
453 -}  
454 -  
455 -bool SipServer::check_device_status(string id) {  
456 - std::lock_guard<std::mutex> l(m_device_map_mtx);  
457 - auto it_info = m_device_map.find(id);  
458 - if (it_info == m_device_map.end()) {  
459 - return false;  
460 - }  
461 -  
462 - string status = trim(it_info->second.status);  
463 - // status = std::tolower(status.c_str());  
464 - transform(status.begin(), status.end(), status.begin(),::tolower);  
465 - if (status == "on"){  
466 - return true;  
467 - }  
468 -  
469 - return false;  
470 -}  
471 -  
472 -Client* SipServer::get_parent_by_id(string id) {  
473 - std::lock_guard<std::mutex> l(m_device_map_mtx);  
474 - auto it_info = m_device_map.find(id);  
475 - if (it_info == m_device_map.end()) {  
476 - return nullptr;  
477 - }  
478 - string parent_id = it_info->second.parentid;  
479 -  
480 - std::lock_guard<std::mutex> l_c(m_client_map_mtx);  
481 - auto it_client = mClientMap.find(parent_id);  
482 - if (it_client == mClientMap.end()) {  
483 - return nullptr;  
484 - }  
485 -  
486 - return mClientMap[parent_id];  
487 -}  
488 -  
489 -void SipServer::response_invite_ack(eXosip_event_t *evtp){  
490 -  
491 - osip_message_t* msg = nullptr;  
492 - int ret = eXosip_call_build_ack(mSipCtx, evtp->did, &msg);  
493 - if (!ret && msg) {  
494 - eXosip_call_send_ack(mSipCtx, evtp->did, msg);  
495 - } else {  
496 - LOG_ERROR("eXosip_call_send_ack error={}", ret);  
497 - }  
498 -  
499 -}  
500 -int SipServer::request_bye(eXosip_event_t* evtp) {  
501 -  
502 - eXosip_lock(mSipCtx);  
503 - int ret = eXosip_call_terminate(mSipCtx, evtp->cid, evtp->did);  
504 - eXosip_unlock(mSipCtx);  
505 -  
506 - return ret;  
507 -}  
508 -  
509 -int SipServer::RequestInvite_UDP(const char* dst_channel, int rtpPort) {  
510 -  
511 - // 检查设备是否在线  
512 - if (!check_device_status(dst_channel)) {  
513 - return -2;  
514 - }  
515 -  
516 - Client* client = get_parent_by_id(dst_channel);  
517 - if (client == nullptr) {  
518 - return -1;  
519 - }  
520 -  
521 - LOG_INFO("INVITE UDP");  
522 -  
523 - char session_exp[1024] = { 0 };  
524 - osip_message_t* msg = nullptr;  
525 - char from[1024] = { 0 };  
526 - char to[1024] = { 0 };  
527 - char sdp[2048] = { 0 };  
528 - char head[1024] = { 0 };  
529 -  
530 - sprintf(from, "sip:%s@%s:%d", mInfo.getSipId().c_str(), mInfo.getIp().c_str(), mInfo.getPort());  
531 - sprintf(to, "sip:%s@%s:%d", dst_channel, client->getIp().c_str(), client->getPort());  
532 - snprintf(sdp, 2048,  
533 - "v=0\r\n"  
534 - "o=%s 0 0 IN IP4 %s\r\n"  
535 - "s=Play\r\n"  
536 - "c=IN IP4 %s\r\n"  
537 - "t=0 0\r\n"  
538 - "m=video %d RTP/AVP 96 98 97\r\n"  
539 - "a=recvonly\r\n"  
540 - "a=rtpmap:96 PS/90000\r\n"  
541 - "a=rtpmap:98 H264/90000\r\n"  
542 - "a=rtpmap:97 MPEG4/90000\r\n"  
543 - "a=setup:passive\r\n"  
544 - "a=connection:new\r\n"  
545 - "y=0100000001\r\n"  
546 - "f=\r\n", mInfo.getSipId().c_str(), mInfo.getIp().c_str(), mInfo.getIp().c_str(), rtpPort);  
547 -  
548 - int ret = eXosip_call_build_initial_invite(mSipCtx, &msg, to, from, nullptr, nullptr);  
549 - if (ret) {  
550 - LOG_ERROR("eXosip_call_build_initial_invite error: {} {} ret:{}", from, to, ret);  
551 - return -1;  
552 - }  
553 -  
554 - osip_message_set_body(msg, sdp, strlen(sdp));  
555 - osip_message_set_content_type(msg, "application/sdp");  
556 - snprintf(session_exp, sizeof(session_exp) - 1, "%i;refresher=uac", mInfo.getTimeout());  
557 - osip_message_set_header(msg, "Session-Expires", session_exp);  
558 - osip_message_set_supported(msg, "timer");  
559 -  
560 - int call_id = eXosip_call_send_initial_invite(mSipCtx, msg);  
561 - if (call_id > 0) {  
562 - LOG_INFO("eXosip_call_send_initial_invite success: call_id={}", call_id);  
563 - }  
564 - else {  
565 - LOG_ERROR("eXosip_call_send_initial_invite error: call_id={}", call_id);  
566 - }  
567 - return call_id;  
568 -}  
569 -  
570 -int SipServer::RequestInvite_TCP_a(const char* dst_channel, int rtpPort) {  
571 - // 检查设备是否在线  
572 - if (!check_device_status(dst_channel)) {  
573 - return -2;  
574 - }  
575 -  
576 - Client* client = get_parent_by_id(dst_channel);  
577 - if (client == nullptr) {  
578 - return -1;  
579 - }  
580 -  
581 - LOG_INFO("INVITE TCP active");  
582 -  
583 - char session_exp[1024] = { 0 };  
584 - osip_message_t* msg = nullptr;  
585 - char from[1024] = { 0 };  
586 - char to[1024] = { 0 };  
587 - char sdp[2048] = { 0 };  
588 - char head[1024] = { 0 };  
589 -  
590 - // const char* dst_channel = "34020000001320000001";  
591 -  
592 - sprintf(from, "sip:%s@%s:%d", mInfo.getSipId().c_str(), mInfo.getIp().c_str(), mInfo.getPort());  
593 - sprintf(to, "sip:%s@%s:%d", dst_channel, client->getIp().c_str(), client->getPort());  
594 - snprintf(sdp, 2048,  
595 - "v=0\r\n"  
596 - "o=%s 0 0 IN IP4 %s\r\n"  
597 - "s=Play\r\n"  
598 - "c=IN IP4 %s\r\n"  
599 - "t=0 0\r\n"  
600 - "m=video %d TCP/RTP/AVP 96 98 97\r\n"  
601 - "a=recvonly\r\n"  
602 - "a=rtpmap:96 PS/90000\r\n"  
603 - "a=rtpmap:98 H264/90000\r\n"  
604 - "a=rtpmap:97 MPEG4/90000\r\n"  
605 - "a=setup:active\r\n"  
606 - "a=connection:new\r\n"  
607 - "y=0100000001\r\n"  
608 - "f=\r\n", mInfo.getSipId().c_str(), mInfo.getIp().c_str(), mInfo.getIp().c_str(), rtpPort);  
609 -  
610 - int ret = eXosip_call_build_initial_invite(mSipCtx, &msg, to, from, nullptr, nullptr);  
611 - if (ret) {  
612 - LOG_ERROR("eXosip_call_build_initial_invite error: {} {} ret:{}", from, to, ret);  
613 - return -1;  
614 - }  
615 -  
616 - osip_message_set_body(msg, sdp, strlen(sdp));  
617 - osip_message_set_content_type(msg, "application/sdp");  
618 - snprintf(session_exp, sizeof(session_exp) - 1, "%i;refresher=uac", mInfo.getTimeout());  
619 - osip_message_set_header(msg, "Session-Expires", session_exp);  
620 - osip_message_set_supported(msg, "timer");  
621 -  
622 - int call_id = eXosip_call_send_initial_invite(mSipCtx, msg);  
623 - if (call_id > 0) {  
624 - LOG_INFO("eXosip_call_send_initial_invite success: call_id={}", call_id);  
625 - }  
626 - else {  
627 - LOG_ERROR("eXosip_call_send_initial_invite error: call_id={}", call_id);  
628 - }  
629 - return call_id;  
630 -}  
631 -  
632 -void SipServer::cacheCatalog() {  
633 -  
634 - std::lock_guard<std::mutex> l(m_client_map_mtx);  
635 -  
636 - if (mClientMap.size() <= 0){  
637 - cout << "no IPC" << endl;  
638 - return ;  
639 - }  
640 -  
641 - cout << "client size:" << mClientMap.size() << endl;  
642 - for (auto it = mClientMap.begin(); it != mClientMap.end(); it++) {  
643 - RequestCatalog(it->second);  
644 - }  
645 -}  
646 -  
647 -void SipServer::RequestCatalog(Client* client) {  
648 -  
649 - eXosip_lock(mSipCtx);  
650 -  
651 - osip_message_t* catlog_msg = NULL;  
652 - char to[100];/*sip:主叫用户名@被叫IP地址*/  
653 - char from[100];/*sip:被叫IP地址:被叫IP端口*/  
654 - char xml_body[4096];  
655 -  
656 - memset(to, 0, 100);  
657 - memset(from, 0, 100);  
658 - memset(xml_body, 0, 4096);  
659 -  
660 - sprintf(from, "sip:%s@%s:%d", mInfo.getSipId().c_str(), mInfo.getIp().c_str(), mInfo.getPort());  
661 - sprintf(to, "sip:%s@%s:%d", client->getDevice().c_str(), client->getIp().c_str(), client->getPort());  
662 - eXosip_message_build_request(mSipCtx, &catlog_msg, "MESSAGE", to, from, NULL);/*构建"MESSAGE"请求*/  
663 -  
664 - snprintf(xml_body, 4096,  
665 - "<?xml version=\"1.0\"?>"  
666 - "<Query>"  
667 - "<CmdType>Catalog</CmdType>"  
668 - "<SN>%d</SN>"  
669 - "<DeviceID>%s</DeviceID>"  
670 - "</Query>", rand() % (99999 - 10000 + 1) + 10000, client->getDevice().c_str());  
671 -  
672 - osip_message_set_body(catlog_msg, xml_body, strlen(xml_body));  
673 - osip_message_set_content_type(catlog_msg, "Application/MANSCDP+xml");  
674 - eXosip_message_send_request(mSipCtx, catlog_msg);  
675 -  
676 - eXosip_unlock(mSipCtx);  
677 -}  
678 -  
679 -int SipServer::clearClientMap(){  
680 - std::lock_guard<std::mutex> l(m_client_map_mtx);  
681 - for (auto iter=mClientMap.begin(); iter!=mClientMap.end(); iter++) {  
682 - delete iter->second;  
683 - iter->second = nullptr;  
684 - }  
685 - mClientMap.clear();  
686 -  
687 - return 0;  
688 -}  
689 -  
690 -void SipServer::deleteClientByDevice(string device) {  
691 - std::lock_guard<std::mutex> l(m_client_map_mtx);  
692 - auto it = mClientMap.find(device);  
693 - if (it == mClientMap.end()) {  
694 - return ;  
695 - }  
696 - delete it->second;  
697 - it->second = nullptr;  
698 - mClientMap.erase(it);  
699 -}  
700 -  
701 -int SipServer::parse_xml(const char *data, const char *s_mark, bool with_s_make, const char *e_mark, bool with_e_make, char *dest) {  
702 - const char* satrt = strstr( data, s_mark );  
703 -  
704 - if(satrt != NULL) {  
705 - const char* end = strstr(satrt, e_mark);  
706 -  
707 - if(end != NULL){  
708 - int s_pos = with_s_make ? 0 : strlen(s_mark);  
709 - int e_pos = with_e_make ? strlen(e_mark) : 0;  
710 -  
711 - strncpy( dest, satrt+s_pos, (end+e_pos) - (satrt+s_pos) );  
712 - }  
713 - return 0;  
714 - }  
715 - return -1;  
716 -  
717 -}  
718 -void SipServer::dump_request(eXosip_event_t *evtp) {  
719 - char *s;  
720 - size_t len;  
721 - osip_message_to_str(evtp->request, &s, &len);  
722 - LOG_INFO("\nprint request start\ntype={}\n{}\nprint request end\n",evtp->type,s);  
723 -}  
724 -void SipServer::dump_response(eXosip_event_t *evtp) {  
725 - char *s;  
726 - size_t len;  
727 - osip_message_to_str(evtp->response, &s, &len);  
728 - LOG_INFO("\nprint response start\ntype={}\n{}\nprint response end\n",evtp->type,s);  
729 -}  
730 \ No newline at end of file 0 \ No newline at end of file
src/decoder/gb28181/sip/SipServer.h deleted
1 -#ifndef __SIPSERVER_H__  
2 -#define __SIPSERVER_H__  
3 -  
4 -extern "C" {  
5 -#include <osip2/osip_mt.h>  
6 -#include <eXosip2/eXosip.h>  
7 -}  
8 -  
9 -#include <map>  
10 -#include <string>  
11 -#include <thread>  
12 -#include <chrono>  
13 -#include <mutex>  
14 -  
15 -#include "./Message/CatalogParser.h"  
16 -#include "sip_header.h"  
17 -  
18 -using namespace std;  
19 -  
20 -class Client {  
21 -public:  
22 - Client(string ip, int port, string device) :  
23 - mIp(ip),  
24 - mPort(port),  
25 - mRtpPort(0),  
26 - mDevice(device),  
27 - mIsReg(false){  
28 - }  
29 - ~Client() = default;  
30 -public:  
31 -  
32 - void setRtpPort(int rtpPort) {  
33 - mRtpPort = rtpPort;  
34 - }  
35 -  
36 - void setReg(bool isReg) {  
37 - mIsReg = isReg;  
38 - }  
39 - string getDevice() const{  
40 - return mDevice;  
41 - }  
42 - string getIp() const{  
43 - return mIp;  
44 - }  
45 - int getPort() const{  
46 - return mPort;  
47 - }  
48 -  
49 - unsigned long getHeartBeat() {  
50 - return mHeartBeatTime;  
51 - }  
52 -  
53 - void updateHeartBeat(unsigned long ts) {  
54 - mHeartBeatTime = ts;  
55 - }  
56 -  
57 -private:  
58 - string mIp; // client ip  
59 - int mPort; // client port  
60 - string mDevice;// 340200000013200000024  
61 - bool mIsReg;  
62 - int mRtpPort;  
63 - unsigned long mHeartBeatTime{0};  
64 -  
65 -};  
66 -  
67 -  
68 -class SipServer {  
69 -public:  
70 - static SipServer* getInstance(){  
71 - static SipServer* singleton = nullptr;  
72 - if (singleton == nullptr){  
73 - singleton = new SipServer();  
74 - }  
75 - return singleton;  
76 - }  
77 -  
78 -public:  
79 - SipServer();  
80 - ~SipServer();  
81 -  
82 - bool Init(ServerInfo* pInfo);  
83 -  
84 - int RequestInvite_UDP(const char* dst_channel, int rtpPort);  
85 -  
86 - int RequestInvite_TCP_a(const char* dst_channel, int rtpPort);  
87 -  
88 - void Close();  
89 -  
90 - int GetMinRtpPort();  
91 -  
92 - int GetMaxRtpPort();  
93 -  
94 -public:  
95 - void event_loop();  
96 - void timing_getcatlog();  
97 -  
98 -private:  
99 - int init_sip_server();  
100 - int sip_event_handle(eXosip_event_t *evtp);  
101 -  
102 - void RequestCatalog(Client* client);  
103 - void cacheCatalog();  
104 -  
105 - void response_message_answer(eXosip_event_t *evtp,int code);  
106 - void response_register(eXosip_event_t *evtp);  
107 - void response_register_401unauthorized(eXosip_event_t *evt);  
108 - void response_message(eXosip_event_t *evtp);  
109 - void response_invite_ack(eXosip_event_t *evtp);  
110 - int request_bye(eXosip_event_t* evtp);// 通知相机停止推流  
111 - int parse_xml(const char* data, const char* s_mark, bool with_s_make, const char* e_mark, bool with_e_make, char* dest);  
112 - void dump_request(eXosip_event_t *evtp);  
113 - void dump_response(eXosip_event_t *evtp);  
114 -  
115 - int clearClientMap();  
116 - void deleteClientByDevice(string device);  
117 -  
118 - Client* get_parent_by_id(string id);  
119 - bool check_device_status(string id);  
120 -  
121 -private:  
122 - bool mQuit{ false };  
123 - eXosip_t *mSipCtx;  
124 - ServerInfo mInfo;  
125 -  
126 - std::map<std::string, Client *> mClientMap;// <DeviceID,SipClient>  
127 - mutex m_client_map_mtx;  
128 - std::map<std::string, DeviceInfo> m_device_map;  
129 - mutex m_device_map_mtx;  
130 -  
131 - thread* m_event_loop_thread{nullptr};  
132 -};  
133 -  
134 -  
135 -#endif //__SIPSERVER_H__  
src/decoder/gb28181/sip/Utils/HTTPDigest.cpp deleted
1 -#include "MD5.h"  
2 -#include <string.h>  
3 -#include "HTTPDigest.h"  
4 -  
5 -#ifdef _WIN32  
6 -//#define strcasecmp _stricmp  
7 -//#define strncasecmp _strnicmp  
8 -#endif  
9 -#ifdef _MSC_VER  
10 -#define strcasecmp _stricmp  
11 -#define strncasecmp _strnicmp  
12 -#endif  
13 -  
14 -void my_CvtHex(  
15 - IN HASH Bin,  
16 - OUT HASHHEX Hex  
17 - )  
18 -{  
19 - unsigned short i;  
20 - unsigned char j;  
21 - for (i = 0; i < HASHLEN; i++) {  
22 - j = (Bin[i] >> 4) & 0xf;  
23 - if (j <= 9)  
24 - Hex[i*2] = (j + '0');  
25 - else  
26 - Hex[i*2] = (j + 'a' - 10);  
27 - j = Bin[i] & 0xf;  
28 - if (j <= 9)  
29 - Hex[i*2+1] = (j + '0');  
30 - else  
31 - Hex[i*2+1] = (j + 'a' - 10);  
32 - };  
33 - Hex[HASHHEXLEN] = '\0';  
34 -}  
35 -  
36 -/* calculate H(A1) as per spec */  
37 -void  
38 -DigestCalcHA1 (IN const char *pszAlg,  
39 - IN const char *pszUserName,  
40 - IN const char *pszRealm,  
41 - IN const char *pszPassword,  
42 - IN const char *pszNonce,  
43 - IN const char *pszCNonce,  
44 - OUT HASHHEX SessionKey)  
45 -{  
46 - MD5_CTX Md5Ctx;  
47 - HASH HA1;  
48 -  
49 - MD5Init (&Md5Ctx);  
50 - MD5Update (&Md5Ctx, (unsigned char *) pszUserName, (unsigned int) strlen (pszUserName));  
51 - MD5Update (&Md5Ctx, (unsigned char *) ":", 1);  
52 - MD5Update (&Md5Ctx, (unsigned char *) pszRealm, (unsigned int) strlen (pszRealm));  
53 - MD5Update (&Md5Ctx, (unsigned char *) ":", 1);  
54 - MD5Update (&Md5Ctx, (unsigned char *) pszPassword, (unsigned int) strlen (pszPassword));  
55 - MD5Final ((unsigned char *) HA1, &Md5Ctx);  
56 - if ((pszAlg != NULL) && strcasecmp (pszAlg, "md5-sess") == 0) {  
57 - MD5Init (&Md5Ctx);  
58 - MD5Update (&Md5Ctx, (unsigned char *) HA1, HASHLEN);  
59 - MD5Update (&Md5Ctx, (unsigned char *) ":", 1);  
60 - MD5Update (&Md5Ctx, (unsigned char *) pszNonce, (unsigned int) strlen (pszNonce));  
61 - MD5Update (&Md5Ctx, (unsigned char *) ":", 1);  
62 - MD5Update (&Md5Ctx, (unsigned char *) pszCNonce, (unsigned int) strlen (pszCNonce));  
63 - MD5Final ((unsigned char *) HA1, &Md5Ctx);  
64 - }  
65 - my_CvtHex (HA1, SessionKey);  
66 -}  
67 -  
68 -/* calculate request-digest/response-digest as per HTTP Digest spec */  
69 -void  
70 -DigestCalcResponse (IN HASHHEX HA1, /* H(A1) */  
71 - IN const char *pszNonce, /* nonce from server */  
72 - IN const char *pszNonceCount, /* 8 hex digits */  
73 - IN const char *pszCNonce, /* client nonce */  
74 - IN const char *pszQop, /* qop-value: "", "auth", "auth-int" */  
75 - IN int Aka, /* Calculating AKAv1-MD5 response */  
76 - IN const char *pszMethod, /* method from the request */  
77 - IN const char *pszDigestUri, /* requested URL */  
78 - IN HASHHEX HEntity, /* H(entity body) if qop="auth-int" */  
79 - OUT HASHHEX Response  
80 - /* request-digest or response-digest */ )  
81 -{  
82 - MD5_CTX Md5Ctx;  
83 - HASH HA2;  
84 - HASH RespHash;  
85 - HASHHEX HA2Hex;  
86 -  
87 - /* calculate H(A2) */  
88 - MD5Init (&Md5Ctx);  
89 - MD5Update (&Md5Ctx, (unsigned char *) pszMethod, (unsigned int) strlen (pszMethod));  
90 - MD5Update (&Md5Ctx, (unsigned char *) ":", 1);  
91 - MD5Update (&Md5Ctx, (unsigned char *) pszDigestUri, (unsigned int) strlen (pszDigestUri));  
92 -  
93 - if (pszQop == NULL) {  
94 - goto auth_withoutqop;  
95 - }  
96 - else if (0 == strcasecmp (pszQop, "auth-int")) {  
97 - goto auth_withauth_int;  
98 - }  
99 - else if (0 == strcasecmp (pszQop, "auth")) {  
100 - goto auth_withauth;  
101 - }  
102 -  
103 -auth_withoutqop:  
104 - MD5Final ((unsigned char *) HA2, &Md5Ctx);  
105 - my_CvtHex (HA2, HA2Hex);  
106 -  
107 - /* calculate response */  
108 - MD5Init (&Md5Ctx);  
109 - MD5Update (&Md5Ctx, (unsigned char *) HA1, HASHHEXLEN);  
110 - MD5Update (&Md5Ctx, (unsigned char *) ":", 1);  
111 - MD5Update (&Md5Ctx, (unsigned char *) pszNonce, (unsigned int) strlen (pszNonce));  
112 - MD5Update (&Md5Ctx, (unsigned char *) ":", 1);  
113 -  
114 - goto end;  
115 -  
116 -auth_withauth_int:  
117 -  
118 - MD5Update (&Md5Ctx, (unsigned char *) ":", 1);  
119 - MD5Update (&Md5Ctx, (unsigned char *) HEntity, HASHHEXLEN);  
120 -  
121 -auth_withauth:  
122 - MD5Final ((unsigned char *) HA2, &Md5Ctx);  
123 - my_CvtHex (HA2, HA2Hex);  
124 -  
125 - /* calculate response */  
126 - MD5Init (&Md5Ctx);  
127 - MD5Update (&Md5Ctx, (unsigned char *) HA1, HASHHEXLEN);  
128 - MD5Update (&Md5Ctx, (unsigned char *) ":", 1);  
129 - MD5Update (&Md5Ctx, (unsigned char *) pszNonce, (unsigned int) strlen (pszNonce));  
130 - MD5Update (&Md5Ctx, (unsigned char *) ":", 1);  
131 - if (Aka == 0) {  
132 - MD5Update (&Md5Ctx, (unsigned char *) pszNonceCount, (unsigned int) strlen (pszNonceCount));  
133 - MD5Update (&Md5Ctx, (unsigned char *) ":", 1);  
134 - MD5Update (&Md5Ctx, (unsigned char *) pszCNonce, (unsigned int) strlen (pszCNonce));  
135 - MD5Update (&Md5Ctx, (unsigned char *) ":", 1);  
136 - MD5Update (&Md5Ctx, (unsigned char *) pszQop, (unsigned int) strlen (pszQop));  
137 - MD5Update (&Md5Ctx, (unsigned char *) ":", 1);  
138 - }  
139 -end:  
140 - MD5Update (&Md5Ctx, (unsigned char *) HA2Hex, HASHHEXLEN);  
141 - MD5Final ((unsigned char *) RespHash, &Md5Ctx);  
142 - my_CvtHex (RespHash, Response);  
143 -}  
src/decoder/gb28181/sip/Utils/HTTPDigest.h deleted
1 -#define HASHLEN 16  
2 -typedef char HASH[HASHLEN];  
3 -#define HASHHEXLEN 32  
4 -typedef char HASHHEX[HASHHEXLEN+1];  
5 -#define IN  
6 -#define OUT  
7 -/* calculate H(A1) as per HTTP Digest spec */  
8 -void DigestCalcHA1 (IN const char *pszAlg,  
9 - IN const char *pszUserName,  
10 - IN const char *pszRealm,  
11 - IN const char *pszPassword,  
12 - IN const char *pszNonce,  
13 - IN const char *pszCNonce,  
14 - OUT HASHHEX SessionKey);  
15 -/* calculate request-digest/response-digest as per HTTP Digest spec */  
16 -void DigestCalcResponse (IN HASHHEX HA1, /* H(A1) */  
17 - IN const char *pszNonce, /* nonce from server */  
18 - IN const char *pszNonceCount, /* 8 hex digits */  
19 - IN const char *pszCNonce, /* client nonce */  
20 - IN const char *pszQop, /* qop-value: "", "auth", "auth-int" */  
21 - IN int Aka, /* Calculating AKAv1-MD5 response */  
22 - IN const char *pszMethod, /* method from the request */  
23 - IN const char *pszDigestUri, /* requested URL */  
24 - IN HASHHEX HEntity, /* H(entity body) if qop="auth-int" */  
25 - OUT HASHHEX Response  
26 - /* request-digest or response-digest */ );  
src/decoder/gb28181/sip/Utils/Log.h deleted
1 -//  
2 -// Created bxc on 2022/11/25.  
3 -//  
4 -  
5 -#ifndef BXC_SIPSERVER_LOG_H  
6 -#define BXC_SIPSERVER_LOG_H  
7 -#include <time.h>  
8 -#include <string>  
9 -  
10 -static std::string getTime() {  
11 - const char* time_fmt = "%Y-%m-%d %H:%M:%S";  
12 - time_t t = time(nullptr);  
13 - char time_str[64];  
14 - strftime(time_str, sizeof(time_str), time_fmt, localtime(&t));  
15 -  
16 - return time_str;  
17 -}  
18 -// __FILE__ 获取源文件的相对路径和名字  
19 -// __LINE__ 获取该行代码在文件中的行号  
20 -// __func__ 或 __FUNCTION__ 获取函数名  
21 -  
22 -#define LOGI(format, ...) fprintf(stderr,"[INFO]%s [%s:%d %s()] " format "\n", getTime().data(),__FILE__,__LINE__,__func__ ,##__VA_ARGS__)  
23 -#define LOGE(format, ...) fprintf(stderr,"[ERROR]%s [%s:%d %s()] " format "\n",getTime().data(),__FILE__,__LINE__,__func__ ,##__VA_ARGS__)  
24 -  
25 -#endif //BXC_SIPSERVER_LOG_H  
26 \ No newline at end of file 0 \ No newline at end of file
src/decoder/gb28181/sip/Utils/MD5.cpp deleted
1 -/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm  
2 -*/  
3 -/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All  
4 -rights reserved.  
5 -License to copy and use this software is granted provided that it  
6 -is identified as the "RSA Data Security, Inc. MD5 Message-Digest  
7 -Algorithm" in all material mentioning or referencing this software  
8 -or this function.  
9 -License is also granted to make and use derivative works provided  
10 -that such works are identified as "derived from the RSA Data  
11 -Security, Inc. MD5 Message-Digest Algorithm" in all material  
12 -mentioning or referencing the derived work.  
13 -RSA Data Security, Inc. makes no representations concerning either  
14 -the merchantability of this software or the suitability of this  
15 -software for any particular purpose. It is provided "as is"  
16 -without express or implied warranty of any kind.  
17 -These notices must be retained in any copies of any part of this  
18 -documentation and/or software.  
19 -*/  
20 -#include "MD5.h"  
21 -/* Constants for MD5Transform routine.  
22 -*/  
23 -#define S11 7  
24 -#define S12 12  
25 -#define S13 17  
26 -#define S14 22  
27 -#define S21 5  
28 -#define S22 9  
29 -#define S23 14  
30 -#define S24 20  
31 -#define S31 4  
32 -#define S32 11  
33 -#define S33 16  
34 -#define S34 23  
35 -#define S41 6  
36 -#define S42 10  
37 -#define S43 15  
38 -#define S44 21  
39 -  
40 -#if 0  
41 -static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));  
42 -static void Encode PROTO_LIST  
43 - ((unsigned char *, UINT4 *, unsigned int));  
44 -static void Decode PROTO_LIST  
45 - ((UINT4 *, unsigned char *, unsigned int));  
46 -static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));  
47 -static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));  
48 -#endif  
49 -  
50 -static void MD5Transform(UINT4 [4], unsigned char [64]);  
51 -static void Encode(unsigned char *, UINT4 *, unsigned int);  
52 -static void Decode(UINT4 *, unsigned char *, unsigned int);  
53 -static void MD5_memcpy(POINTER, POINTER, unsigned int);  
54 -static void MD5_memset(POINTER, int, unsigned int);  
55 -  
56 -  
57 -static unsigned char PADDING[64] = {  
58 - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  
59 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  
60 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0  
61 -};  
62 -/* F, G, H and I are basic MD5 functions.  
63 -*/  
64 -#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))  
65 -#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))  
66 -#define H(x, y, z) ((x) ^ (y) ^ (z))  
67 -#define I(x, y, z) ((y) ^ ((x) | (~z)))  
68 -/* ROTATE_LEFT rotates x left n bits.  
69 -*/  
70 -#define ROTATE_LEFT(x , n) (((x) << (n)) | ((x) >> (32-(n))))  
71 -/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.  
72 -Rotation is separate from addition to prevent recomputation.  
73 -*/  
74 -#define FF(a, b, c, d, x, s, ac) { \  
75 - (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \  
76 - (a) = ROTATE_LEFT ((a), (s));\  
77 - (a) += (b); \  
78 - }  
79 -#define GG(a, b, c, d, x, s, ac) { \  
80 - (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \  
81 - (a) = ROTATE_LEFT ((a), (s)); \  
82 - (a) += (b); \  
83 - }  
84 -#define HH(a, b, c, d, x, s, ac) { \  
85 - (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \  
86 - (a) = ROTATE_LEFT ((a), (s)); \  
87 - (a) += (b); \  
88 - }  
89 -#define II(a, b, c, d, x, s, ac) { \  
90 - (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \  
91 - (a) = ROTATE_LEFT ((a), (s)); \  
92 - (a) += (b); \  
93 - }  
94 -/* MD5 initialization. Begins an MD5 operation, writing a new context.  
95 -*/  
96 -void MD5Init (MD5_CTX * context)  
97 -{  
98 - context->count[0] = context->count[1] = 0;  
99 - /* Load magic initialization constants.  
100 - */  
101 - context->state[0] = 0x67452301;  
102 - context->state[1] = 0xefcdab89;  
103 - context->state[2] = 0x98badcfe;  
104 - context->state[3] = 0x10325476;  
105 -}  
106 -/* MD5 block update operation. Continues an MD5 message-digest  
107 -operation, processing another message block, and updating the  
108 -context.  
109 -*/  
110 -void MD5Update (MD5_CTX * context,unsigned char *input,unsigned int inputLen)  
111 -{  
112 - unsigned int i, index, partLen;  
113 - /* Compute number of bytes mod 64 */  
114 - index = (unsigned int)((context->count[0] >> 3) & 0x3F);  
115 - /* Update number of bits */  
116 - if ((context->count[0] += ((UINT4)inputLen << 3))< ((UINT4)inputLen << 3))  
117 - context->count[1]++;  
118 - context->count[1] += ((UINT4)inputLen >> 29);  
119 - partLen = 64 - index;  
120 - /* Transform as many times as possible.  
121 - */  
122 - if (inputLen >= partLen) {  
123 - MD5_memcpy((POINTER)&context->buffer[index], (POINTER)input, partLen);  
124 - MD5Transform (context->state, context->buffer);  
125 - for (i = partLen; i + 63 < inputLen; i += 64)  
126 - MD5Transform (context->state, &input[i]);  
127 - index = 0;  
128 - }  
129 - else  
130 - i = 0;  
131 - /* Buffer remaining input */  
132 - MD5_memcpy((POINTER)&context->buffer[index], (POINTER)&input[i],inputLen-i);  
133 -}  
134 -/* MD5 finalization. Ends an MD5 message-digest operation, writing the  
135 -the message digest and zeroizing the context.  
136 -*/  
137 -void MD5Final(unsigned char digest[16],MD5_CTX * context)  
138 -{  
139 - unsigned char bits[8];  
140 - unsigned int index, padLen;  
141 - /* Save number of bits */  
142 - Encode(bits, context->count, 8);  
143 - /* Pad out to 56 mod 64.  
144 - */  
145 - index = (unsigned int)((context->count[0] >> 3) & 0x3f);  
146 - padLen = (index < 56) ? (56 - index) : (120 - index);  
147 - MD5Update (context, PADDING, padLen);  
148 - /* Append length (before padding) */  
149 - MD5Update (context, bits, 8);  
150 - /* Store state in digest */  
151 - Encode (digest, context->state, 16);  
152 - /* Zeroize sensitive information.  
153 - */  
154 - MD5_memset ((POINTER)context, 0, sizeof (*context));  
155 -}  
156 -  
157 -  
158 -/* MD5 basic transformation. Transforms state based on block.  
159 -*/  
160 -static void MD5Transform(UINT4 state[4], unsigned char block[64])  
161 -{  
162 - UINT4 a = state[0], b = state[1], c = state[2], d = state[3],x[16];  
163 - Decode(x, block, 64);  
164 - /* Round 1 */  
165 - FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */  
166 - FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */  
167 - FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */  
168 - FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */  
169 - FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */  
170 - FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */  
171 - FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */  
172 - FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */  
173 - FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */  
174 - FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */  
175 - FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */  
176 - FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */  
177 - FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */  
178 - FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */  
179 - FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */  
180 - FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */  
181 - /* Round 2 */  
182 - GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */  
183 - GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */  
184 - GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */  
185 - GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */  
186 - GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */  
187 - GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */  
188 - GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */  
189 - GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */  
190 - GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */  
191 - GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */  
192 - GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */  
193 -  
194 - GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */  
195 - GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */  
196 - GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */  
197 - GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */  
198 - GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */  
199 - /* Round 3 */  
200 - HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */  
201 - HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */  
202 - HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */  
203 - HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */  
204 - HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */  
205 - HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */  
206 - HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */  
207 - HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */  
208 - HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */  
209 - HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */  
210 - HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */  
211 - HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */  
212 - HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */  
213 - HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */  
214 - HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */  
215 - HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */  
216 -  
217 - /* Round 4 */  
218 - II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */  
219 - II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */  
220 - II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */  
221 - II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */  
222 - II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */  
223 - II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */  
224 - II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */  
225 - II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */  
226 - II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */  
227 - II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */  
228 - II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */  
229 - II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */  
230 - II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */  
231 - II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */  
232 - II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */  
233 - II (b, c, d, a, x[ 9], S44,0xeb86d391); /* 64 */  
234 -  
235 - state[0] += a;  
236 - state[1] += b;  
237 - state[2] += c;  
238 - state[3] += d;  
239 - /* Zeroize sensitive information.  
240 -  
241 - */  
242 - MD5_memset((POINTER)x, 0, sizeof (x));  
243 -}  
244 -/* Encodes input (UINT4) into output (unsigned char). Assumes len is  
245 -a multiple of 4.  
246 -*/  
247 -static void Encode(unsigned char * output,UINT4 * input,unsigned int len)  
248 -{  
249 - unsigned int i, j;  
250 - for (i = 0, j = 0; j < len; i++, j += 4) {  
251 - output[j] = (unsigned char)(input[i] & 0xff);  
252 - output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);  
253 - output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);  
254 - output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);  
255 - }  
256 -}  
257 -  
258 -/* Decodes input (unsigned char) into output (UINT4). Assumes len is  
259 -a multiple of 4.  
260 -*/  
261 -static void Decode(UINT4 * output,unsigned char * input,unsigned int len)  
262 -{  
263 - unsigned int i, j;  
264 - for (i = 0, j = 0; j < len; i++, j += 4)  
265 - output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |  
266 - (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);  
267 -}  
268 -  
269 -/* Note: Replace "for loop" with standard memcpy if possible.  
270 -*/  
271 -static void MD5_memcpy(POINTER output,POINTER input,unsigned int len)  
272 -{  
273 - unsigned int i;  
274 - for (i = 0; i < len; i++)  
275 - output[i] = input[i];  
276 -}  
277 -/* Note: Replace "for loop" with standard memset if possible.  
278 -*/  
279 -static void MD5_memset( POINTER output, int value,unsigned int len)  
280 -{  
281 - unsigned int i;  
282 - for (i = 0; i < len; i++)  
283 - ((char *)output)[i] = (char)value;  
284 -}  
src/decoder/gb28181/sip/Utils/MD5.h deleted
1 -  
2 -/* GLOBAL.H - RSAREF types and constants  
3 -*/  
4 -/* PROTOTYPES should be set to one if and only if the compiler supports  
5 -function argument prototyping.  
6 -The following makes PROTOTYPES default to 0 if it has not already been defined with C compiler flags.  
7 -*/  
8 -  
9 -  
10 -#ifndef PROTOTYPES  
11 -#define PROTOTYPES 0  
12 -#endif  
13 -/* POINTER defines a generic pointer type */  
14 -typedef unsigned char *POINTER;  
15 -/* UINT2 defines a two byte word */  
16 -typedef unsigned short int UINT2;  
17 -/* UINT4 defines a four byte word */  
18 -typedef unsigned long int UINT4;  
19 -/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.  
20 -If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it  
21 -returns an empty list.  
22 -*/  
23 -#if PROTOTYPES  
24 -#define PROTO_LIST(list) list  
25 -#else  
26 -#define PROTO_LIST(list) ()  
27 -#endif  
28 -  
29 -  
30 -  
31 -/* MD5.H - header file for MD5C.C  
32 -*/  
33 -/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All  
34 -rights reserved.  
35 -License to copy and use this software is granted provided that it  
36 -is identified as the "RSA Data Security, Inc. MD5 Message-Digest  
37 -Algorithm" in all material mentioning or referencing this software  
38 -or this function.  
39 -License is also granted to make and use derivative works provided  
40 -that such works are identified as "derived from the RSA Data  
41 -Security, Inc. MD5 Message-Digest Algorithm" in all material  
42 -mentioning or referencing the derived work.  
43 -RSA Data Security, Inc. makes no representations concerning either  
44 -the merchantability of this software or the suitability of this  
45 -software for any particular purpose. It is provided "as is"  
46 -without express or implied warranty of any kind.  
47 -These notices must be retained in any copies of any part of this  
48 -documentation and/or software.  
49 -*/  
50 -/* MD5 context. */  
51 -  
52 -  
53 -typedef struct {  
54 - UINT4 state[4]; /* state (ABCD) */  
55 - UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */  
56 - unsigned char buffer[64]; /* input buffer */  
57 -} MD5_CTX;  
58 -  
59 -#if 0  
60 -void MD5Init PROTO_LIST ((MD5_CTX *));  
61 -void MD5Update PROTO_LIST  
62 - ((MD5_CTX *, unsigned char *, unsigned int));  
63 -void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *));  
64 -#endif  
65 -  
66 -void MD5Init(MD5_CTX *);  
67 -void MD5Update(MD5_CTX *, unsigned char *, unsigned int);  
68 -void MD5Final(unsigned char [16], MD5_CTX *);  
src/decoder/gb28181/sip/Utils/logger.hpp0 deleted
1 -/*  
2 - * @Author: yangzilong  
3 - * @Date: 2021-12-21 11:07:11  
4 - * @Last Modified by: yangzilong  
5 - * @Email: yangzilong@objecteye.com  
6 - * @Description:  
7 - */  
8 -  
9 -#ifndef __LOGGER_HPP__  
10 -#define __LOGGER_HPP__  
11 -  
12 -  
13 -#include <spdlog/spdlog.h>  
14 -#include <spdlog/common.h>  
15 -#include <spdlog/details/file_helper.h>  
16 -#include <spdlog/details/null_mutex.h>  
17 -#include <spdlog/fmt/fmt.h>  
18 -#include <spdlog/sinks/base_sink.h>  
19 -#include <spdlog/details/os.h>  
20 -#include <spdlog/details/circular_q.h>  
21 -#include <spdlog/details/synchronous_factory.h>  
22 -  
23 -#include <set>  
24 -#include <chrono>  
25 -#include <cstdio>  
26 -#include <ctime>  
27 -#include <mutex>  
28 -#include <string>  
29 -#include <memory>  
30 -#include <vector>  
31 -  
32 -  
33 -  
34 -#define LOG_TRACE_WITH_LOGGER(logger, ...) {SPDLOG_LOGGER_TRACE(logger, __VA_ARGS__);}  
35 -#define LOG_DEBUG_WITH_LOGGER(logger, ...) {SPDLOG_LOGGER_DEBUG(logger, __VA_ARGS__);}  
36 -#define LOG_WARN_WITH_LOGGER(logger, ...) {SPDLOG_LOGGER_WARN(logger, __VA_ARGS__);}  
37 -#define LOG_ERROR_WITH_LOGGER(logger, ...) {SPDLOG_LOGGER_ERROR(logger, __VA_ARGS__);}  
38 -#define LOG_INFO_WITH_LOGGER(logger, ...) {SPDLOG_LOGGER_INFO(logger, __VA_ARGS__);}  
39 -#define LOG_CRITICAL_WITH_LOGGER(logger, ...) {SPDLOG_LOGGER_CRITICAL(logger, __VA_ARGS__);}  
40 -  
41 -  
42 -#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)  
43 -  
44 -// use fmt lib, e.g. LOG_WARN("warn log, {1}, {1}, {2}", 1, 2);  
45 -#define LOG_TRACE(msg, ...) spdlog::log({__FILENAME__, __LINE__, __FUNCTION__}, spdlog::level::trace, msg, ##__VA_ARGS__)  
46 -#define LOG_DEBUG(msg, ...) spdlog::log({__FILENAME__, __LINE__, __FUNCTION__}, spdlog::level::debug, msg, ##__VA_ARGS__)  
47 -#define LOG_INFO(msg,...) spdlog::log({__FILENAME__, __LINE__, __FUNCTION__}, spdlog::level::info, msg, ##__VA_ARGS__)  
48 -#define LOG_WARN(msg,...) spdlog::log({__FILENAME__, __LINE__, __FUNCTION__}, spdlog::level::warn, msg, ##__VA_ARGS__)  
49 -#define LOG_ERROR(msg,...) spdlog::log({__FILENAME__, __LINE__, __FUNCTION__}, spdlog::level::err, msg, ##__VA_ARGS__)  
50 -#define LOG_FATAL(msg,...) spdlog::log({__FILENAME__, __LINE__, __FUNCTION__}, spdlog::level::critical, msg, ##__VA_ARGS__)  
51 -  
52 -  
53 -  
54 -namespace spdlog  
55 -{  
56 - namespace sinks  
57 - {  
58 - template<typename Mutex>  
59 - class easy_file_sink final : public base_sink<Mutex>  
60 - {  
61 - public:  
62 - easy_file_sink(filename_t base_filename, size_t max_size, size_t max_keep_days = 0)  
63 - : base_filename_(std::move(base_filename))  
64 - , max_size_(max_size)  
65 - , max_keep_days_(max_keep_days)  
66 - {  
67 - auto now = log_clock::now();  
68 - auto filename = gen_filename_by_daliy(base_filename_, now_tm(now));  
69 -  
70 - file_helper_.open(filename, false);  
71 - current_size_ = file_helper_.size();  
72 - rotation_tp_ = next_rotation_tp_();  
73 -  
74 - if (max_keep_days_ > 0)  
75 - {  
76 - filespath_q_.push_back(std::move(std::set<filename_t>()));  
77 - filespath_q_[filespath_q_.size() - 1].insert(filename);  
78 - }  
79 - }  
80 -  
81 - filename_t filename()  
82 - {  
83 - std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);  
84 - return file_helper_.filename();  
85 - }  
86 -  
87 - protected:  
88 - void sink_it_(const details::log_msg &msg) override  
89 - {  
90 - memory_buf_t formatted;  
91 - base_sink<Mutex>::formatter_->format(msg, formatted);  
92 - current_size_ += formatted.size();  
93 -  
94 - auto time = msg.time;  
95 - if (time >= rotation_tp_)  
96 - {  
97 - file_helper_.close();  
98 - auto filename = gen_filename_by_daliy(base_filename_, now_tm(time));  
99 - file_helper_.open(filename, false);  
100 - current_size_ = file_helper_.size();  
101 - rotation_tp_ = next_rotation_tp_();  
102 -  
103 - {  
104 - filespath_q_.push_back(std::move(std::set<filename_t>()));  
105 - filespath_q_[filespath_q_.size() - 1].emplace(filename);  
106 - }  
107 -  
108 - // Do the cleaning only at the end because it might throw on failure.  
109 - if (max_keep_days_ > 0 && filespath_q_.size() > max_keep_days_)  
110 - delete_old_();  
111 - }  
112 - else if (current_size_ >= max_size_)  
113 - {  
114 - file_helper_.close();  
115 - auto src_name = gen_filename_by_daliy(base_filename_, now_tm(time));  
116 - auto target_name = gen_filename_by_filesize(base_filename_, now_tm(time), filespath_q_[filespath_q_.size() - 1].size());  
117 -  
118 - // rename file if failed then us `target_name` as src_name.  
119 - if (!rename_file_(src_name, target_name))  
120 - {  
121 - details::os::sleep_for_millis(200);  
122 - if (!rename_file_(src_name, target_name))  
123 - {  
124 - fprintf(stderr, "%s:%d rename %s to %s failed\n", __FILENAME__, __LINE__, src_name.c_str(), target_name.c_str());  
125 - src_name = target_name;  
126 - }  
127 - }  
128 -  
129 - filespath_q_[filespath_q_.size() - 1].emplace(src_name);  
130 - if (src_name != target_name)  
131 - filespath_q_[filespath_q_.size() - 1].emplace(target_name);  
132 -  
133 - file_helper_.open(src_name, false);  
134 - current_size_ = file_helper_.size();  
135 - rotation_tp_ = next_rotation_tp_();  
136 - }  
137 -  
138 - file_helper_.write(formatted);  
139 -  
140 -  
141 - }  
142 -  
143 - void flush_() override  
144 - {  
145 - file_helper_.flush();  
146 - }  
147 -  
148 - private:  
149 -  
150 - tm now_tm(log_clock::time_point tp)  
151 - {  
152 - time_t tnow = log_clock::to_time_t(tp);  
153 - return spdlog::details::os::localtime(tnow);  
154 - }  
155 -  
156 - /**  
157 - * @brief Get next day tm.  
158 - *  
159 - * @return log_clock::time_point  
160 - */  
161 - log_clock::time_point next_rotation_tp_()  
162 - {  
163 - auto now = log_clock::now();  
164 - tm date = now_tm(now);  
165 - date.tm_hour = 0;  
166 - date.tm_min = 0;  
167 - date.tm_sec = 0;  
168 - auto rotation_time = log_clock::from_time_t(std::mktime(&date));  
169 - if (rotation_time > now)  
170 - return rotation_time;  
171 - return {rotation_time + std::chrono::hours(24)};  
172 - }  
173 -  
174 - // Delete the file N rotations ago.  
175 - // Throw spdlog_ex on failure to delete the old file.  
176 - void delete_old_()  
177 - {  
178 - for (auto iter = filespath_q_.begin(); iter != filespath_q_.end();)  
179 - {  
180 - if (filespath_q_.size() <= max_keep_days_)  
181 - break;  
182 -  
183 - for (auto it = iter->begin(); it != iter->end(); ++it)  
184 - {  
185 - bool ok = details::os::remove_if_exists(*it) == 0;  
186 - if (!ok)  
187 - throw_spdlog_ex("Failed removing daily file " + details::os::filename_to_str(*it), errno);  
188 - }  
189 - filespath_q_.erase(iter);  
190 - }  
191 - }  
192 -  
193 - /* */  
194 - static filename_t gen_filename_by_daliy(const filename_t &filename, const tm &now_tm)  
195 - {  
196 - filename_t basename, ext;  
197 - std::tie(basename, ext) = details::file_helper::split_by_extension(filename);  
198 - return fmt::format(SPDLOG_FILENAME_T("{}_{:04d}_{:02d}_{:02d}{}"),  
199 - basename,  
200 - now_tm.tm_year + 1900,  
201 - now_tm.tm_mon + 1,  
202 - now_tm.tm_mday,  
203 - ext);  
204 - }  
205 -  
206 - //  
207 - static filename_t gen_filename_by_filesize(const filename_t &filename, const tm &now_tm, const int &idx)  
208 - {  
209 - filename_t basename, ext;  
210 - std::tie(basename, ext) = details::file_helper::split_by_extension(filename);  
211 - return fmt::format(SPDLOG_FILENAME_T("{}_{:04d}_{:02d}_{:02d}_{:02d}{:02d}{:02d}.{:d}{}"),  
212 - basename,  
213 - now_tm.tm_year + 1900,  
214 - now_tm.tm_mon + 1,  
215 - now_tm.tm_mday,  
216 - now_tm.tm_hour,  
217 - now_tm.tm_min,  
218 - now_tm.tm_sec,  
219 - idx,  
220 - ext);  
221 - }  
222 -  
223 - static bool rename_file_(const filename_t &src_filename, const filename_t &target_filename)  
224 - {  
225 - (void)details::os::remove(target_filename);  
226 - return details::os::rename(src_filename, target_filename) == 0;  
227 - }  
228 -  
229 - filename_t base_filename_;  
230 - log_clock::time_point rotation_tp_;  
231 - details::file_helper file_helper_;  
232 - std::size_t max_size_;  
233 - std::size_t max_keep_days_;  
234 - std::size_t current_size_;  
235 - // std::vector<<std::set<filename_t>> filespath_q_;  
236 - std::vector<std::set<filename_t>> filespath_q_;  
237 - };  
238 -  
239 - using easy_file_sink_mt = easy_file_sink<std::mutex>;  
240 - using easy_file_sink_st = easy_file_sink<details::null_mutex>;  
241 -  
242 - } // namespace sinks  
243 -  
244 - template<typename Factory = spdlog::synchronous_factory>  
245 - inline std::shared_ptr<logger> easy_logger_mt(  
246 - const std::string &logger_name, const filename_t &filename, size_t max_size, size_t max_keep_days = -1)  
247 - {  
248 - return Factory::template create<sinks::easy_file_sink_mt>(logger_name, filename, max_size, max_keep_days);  
249 - }  
250 -  
251 - template<typename Factory = spdlog::synchronous_factory>  
252 - inline std::shared_ptr<logger> easy_logger_st(  
253 - const std::string &logger_name, const filename_t &filename, size_t max_size, size_t max_keep_days = -1)  
254 - {  
255 - return Factory::template create<sinks::easy_file_sink_st>(logger_name, filename, max_size, max_keep_days);  
256 - }  
257 -  
258 -} // namespace spdlog  
259 -  
260 -  
261 -enum class LogLevel  
262 -{  
263 - SPD_LOG_CLOSE = -1,  
264 - SPD_LOG_TRACE = 0,  
265 - SPD_LOG_DEBUG = 1,  
266 - SPD_LOG_INFO = 2,  
267 - SPD_LOG_WARN = 3,  
268 - SPD_LOG_ERROR = 4,  
269 - SPD_LOG_FATAL = 5,  
270 -};  
271 -  
272 -  
273 -class LoggerGenerator  
274 -{  
275 -public:  
276 - static LoggerGenerator* get_instance()  
277 - {  
278 - static LoggerGenerator logger;  
279 - return &logger;  
280 - }  
281 -  
282 - void destory(LoggerGenerator *ptr)  
283 - {  
284 - if (ptr != nullptr)  
285 - {  
286 - delete ptr;  
287 - ptr = nullptr;  
288 - }  
289 - }  
290 -  
291 - std::shared_ptr<spdlog::logger> gen_logger(const LogLevel &level, const std::string &logger_name,  
292 - const std::string &file_path, size_t max_file_size, size_t max_keep_days)  
293 - {  
294 - spdlog::level::level_enum spd_level;  
295 - if (LogLevel::SPD_LOG_TRACE == level)  
296 - spd_level = spdlog::level::trace;  
297 - else if (LogLevel::SPD_LOG_DEBUG == level)  
298 - spd_level = spdlog::level::debug;  
299 - else if (LogLevel::SPD_LOG_INFO == level)  
300 - spd_level = spdlog::level::info;  
301 - else if (LogLevel::SPD_LOG_WARN == level)  
302 - spd_level = spdlog::level::warn;  
303 - else if (LogLevel::SPD_LOG_ERROR == level)  
304 - spd_level = spdlog::level::err;  
305 - else if (LogLevel::SPD_LOG_FATAL == level)  
306 - spd_level = spdlog::level::critical;  
307 - else if (LogLevel::SPD_LOG_CLOSE == level)  
308 - spd_level = spdlog::level::off;  
309 -  
310 - auto sink_ptr = std::make_shared<spdlog::sinks::easy_file_sink_mt>(file_path, max_file_size, max_keep_days);  
311 - auto logger = std::make_shared<spdlog::logger>(logger_name, sink_ptr);  
312 - logger->set_level(spd_level);  
313 - logger->set_pattern("%s(%#): [%L %D %T.%e %P %t %!] %v");  
314 -  
315 - return logger;  
316 - }  
317 -  
318 - void set_default_logger(const LogLevel &level, const std::string &logger_name,  
319 - const std::string &file_name, size_t max_file_size, size_t max_keep_days)  
320 - {  
321 -  
322 - auto logger = gen_logger(level, logger_name, file_name, max_file_size, max_keep_days);  
323 - spdlog::set_default_logger(logger);  
324 - spdlog::set_level(logger->level());  
325 - spdlog::set_pattern("%s(%#): [%L %D %T.%e %P %t %!] %v");  
326 -  
327 - spdlog::flush_on(spdlog::level::trace);  
328 - spdlog::flush_every(std::chrono::seconds(1));  
329 - }  
330 -  
331 -};  
332 -  
333 -  
334 -static void set_default_logger(const LogLevel &level, const std::string &logger_name,  
335 - const std::string &file_path, size_t max_file_size, size_t max_keep_days)  
336 -{  
337 - static LoggerGenerator loggerGenerator;  
338 - loggerGenerator.set_default_logger(level, logger_name, file_path, max_file_size, max_keep_days);  
339 -}  
340 -  
341 -  
342 -static std::shared_ptr<spdlog::logger> get_simple_logger(const LogLevel &level, const std::string &logger_name,  
343 - const std::string &file_path, size_t max_file_size, size_t max_keep_days)  
344 -{  
345 - static LoggerGenerator loggerGenerator;  
346 - return loggerGenerator.gen_logger(level, logger_name, file_path, max_file_size, max_keep_days);  
347 -}  
348 -  
349 -  
350 -#endif // __LOGGER_HPP__  
351 \ No newline at end of file 0 \ No newline at end of file
src/decoder/gb28181/sip/sip_header.h deleted
1 -#ifndef __SIP_HEADER_H__  
2 -#define __SIP_HEADER_H__  
3 -  
4 -#include <string>  
5 -  
6 -using namespace std;  
7 -  
8 -enum EEventType  
9 -{  
10 - EVENT_ON = 0, // ����  
11 - EVENT_OFF, // ����  
12 - EVENT_VLOST, // ��Ƶ��ʧ  
13 - EVENT_DEFECT, // ����  
14 - EVENT_ADD, // ����  
15 - EVENT_DEL, // ɾ��  
16 - EVENT_UPDATE, // ����  
17 -  
18 - EVENT_UNKNOW,  
19 -};  
20 -  
21 -struct DeviceInfo  
22 -{  
23 - EEventType event;  
24 - std::string id;  
25 - std::string name;  
26 - std::string manufacturer;  
27 - std::string model;  
28 - std::string owner;  
29 - std::string civil;  
30 - std::string block;  
31 - std::string address;  
32 - std::string safetyway;  
33 - std::string registerway;  
34 - std::string certnum;  
35 - std::string certifiable;  
36 - std::string errcode;  
37 - std::string secrecy;  
38 - std::string parental;  
39 - std::string parentid;  
40 - std::string endtime;  
41 - std::string ip;  
42 - std::string port;  
43 - std::string password;  
44 - std::string status;  
45 - std::string longitude;  
46 - std::string latitude;  
47 - std::string ptz;  
48 - std::string position;  
49 - std::string room;  
50 - std::string use;  
51 - std::string supplylight;  
52 - std::string direction;  
53 - std::string resolution;  
54 - std::string businessgroup;  
55 -};  
56 -  
57 -class ServerInfo {  
58 -public:  
59 - ServerInfo() {}  
60 -  
61 - ServerInfo(string ua,string nonce, string ip, int port,  
62 - string sipId, string sipRealm, string sipPass, int sipTimeout, int sipExpiry, int minRtpPort, int maxRtpPort):  
63 - mUa(ua),mNonce(nonce),mIp(ip),mPort(port),mSipId(sipId),  
64 - mSipRealm(sipRealm),mSipPass(sipPass),mSipTimeout(sipTimeout),  
65 - mSipExpiry(sipExpiry),mMinRtpPort(minRtpPort),mMaxRtpPort(maxRtpPort){}  
66 -  
67 - ~ServerInfo() = default;  
68 -public:  
69 - string getUa() const{  
70 - return mUa;  
71 - }  
72 - void setUa(string ua) {  
73 - mUa = ua;  
74 - }  
75 - string getNonce() const{  
76 - return mNonce;  
77 - }  
78 - void setNonce(string nonce) {  
79 - mNonce = nonce;  
80 - }  
81 - string getIp() const{  
82 - return mIp;  
83 - }  
84 - void setIp(string s) {  
85 - mIp = s;  
86 - }  
87 - int getPort() const {  
88 - return mPort;  
89 - }  
90 - void setPort(int i) {  
91 - mPort = i;  
92 - }  
93 -  
94 - string getSipId() const{  
95 - return mSipId;  
96 - }  
97 - void setSipId(string s) {  
98 - mSipId = s;  
99 - }  
100 - string getSipRealm() const{  
101 - return mSipRealm;  
102 - }  
103 - void setSipRealm(string s) {  
104 - mSipRealm = s;  
105 - }  
106 - string getSipPass() const{  
107 - return mSipPass;  
108 - }  
109 - void setSipPass(string s) {  
110 - mSipPass = s;  
111 - }  
112 - int getTimeout() const {  
113 - return mSipTimeout;  
114 - }  
115 - void setTimeout(int i) {  
116 - mSipTimeout = i;  
117 - }  
118 - int getExpiry() const {  
119 - return mSipExpiry;  
120 - }  
121 - void setExpiry(int i) {  
122 - mSipExpiry = i;  
123 - }  
124 - int getMinRtpPort() const {  
125 - return mMinRtpPort;  
126 - }  
127 - void setMinRtpPort(int i) {  
128 - mMinRtpPort = i;  
129 - }  
130 - int getMaxRtpPort() const {  
131 - return mMaxRtpPort;  
132 - }  
133 - void setMaxRtpPort(int i) {  
134 - mMaxRtpPort = i;  
135 - }  
136 -  
137 -private:  
138 - string mUa;  
139 - string mNonce;//SIP服务随机数值  
140 - string mIp;//SIP服务IP  
141 - int mPort{0};//SIP服务端口  
142 - string mSipId; //SIP服务器ID  
143 - string mSipRealm;//SIP服务器域  
144 - string mSipPass;//SIP password  
145 - int mSipTimeout; //SIP timeout  
146 - int mSipExpiry;// SIP到期  
147 - int mMinRtpPort;  
148 - int mMaxRtpPort;  
149 -};  
150 -  
151 -  
152 -#endif //__SIP_HEADER_H__  
153 \ No newline at end of file 0 \ No newline at end of file
src/decoder/gb28181/sip/tinyxml2/tinyxml2.cpp deleted
1 -/*  
2 -Original code by Lee Thomason (www.grinninglizard.com)  
3 -  
4 -This software is provided 'as-is', without any express or implied  
5 -warranty. In no event will the authors be held liable for any  
6 -damages arising from the use of this software.  
7 -  
8 -Permission is granted to anyone to use this software for any  
9 -purpose, including commercial applications, and to alter it and  
10 -redistribute it freely, subject to the following restrictions:  
11 -  
12 -1. The origin of this software must not be misrepresented; you must  
13 -not claim that you wrote the original software. If you use this  
14 -software in a product, an acknowledgment in the product documentation  
15 -would be appreciated but is not required.  
16 -  
17 -2. Altered source versions must be plainly marked as such, and  
18 -must not be misrepresented as being the original software.  
19 -  
20 -3. This notice may not be removed or altered from any source  
21 -distribution.  
22 -*/  
23 -  
24 -#include "tinyxml2.h"  
25 -  
26 -#include <new> // yes, this one new style header, is in the Android SDK.  
27 -#if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__)  
28 -# include <stddef.h>  
29 -# include <stdarg.h>  
30 -#else  
31 -# include <cstddef>  
32 -# include <cstdarg>  
33 -#endif  
34 -  
35 -#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE)  
36 - // Microsoft Visual Studio, version 2005 and higher. Not WinCE.  
37 - /*int _snprintf_s(  
38 - char *buffer,  
39 - size_t sizeOfBuffer,  
40 - size_t count,  
41 - const char *format [,  
42 - argument] ...  
43 - );*/  
44 - static inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... )  
45 - {  
46 - va_list va;  
47 - va_start( va, format );  
48 - int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );  
49 - va_end( va );  
50 - return result;  
51 - }  
52 -  
53 - static inline int TIXML_VSNPRINTF( char* buffer, size_t size, const char* format, va_list va )  
54 - {  
55 - int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );  
56 - return result;  
57 - }  
58 -  
59 - #define TIXML_VSCPRINTF _vscprintf  
60 - #define TIXML_SSCANF sscanf_s  
61 -#elif defined _MSC_VER  
62 - // Microsoft Visual Studio 2003 and earlier or WinCE  
63 - #define TIXML_SNPRINTF _snprintf  
64 - #define TIXML_VSNPRINTF _vsnprintf  
65 - #define TIXML_SSCANF sscanf  
66 - #if (_MSC_VER < 1400 ) && (!defined WINCE)  
67 - // Microsoft Visual Studio 2003 and not WinCE.  
68 - #define TIXML_VSCPRINTF _vscprintf // VS2003's C runtime has this, but VC6 C runtime or WinCE SDK doesn't have.  
69 - #else  
70 - // Microsoft Visual Studio 2003 and earlier or WinCE.  
71 - static inline int TIXML_VSCPRINTF( const char* format, va_list va )  
72 - {  
73 - int len = 512;  
74 - for (;;) {  
75 - len = len*2;  
76 - char* str = new char[len]();  
77 - const int required = _vsnprintf(str, len, format, va);  
78 - delete[] str;  
79 - if ( required != -1 ) {  
80 - TIXMLASSERT( required >= 0 );  
81 - len = required;  
82 - break;  
83 - }  
84 - }  
85 - TIXMLASSERT( len >= 0 );  
86 - return len;  
87 - }  
88 - #endif  
89 -#else  
90 - // GCC version 3 and higher  
91 - //#warning( "Using sn* functions." )  
92 - #define TIXML_SNPRINTF snprintf  
93 - #define TIXML_VSNPRINTF vsnprintf  
94 - static inline int TIXML_VSCPRINTF( const char* format, va_list va )  
95 - {  
96 - int len = vsnprintf( 0, 0, format, va );  
97 - TIXMLASSERT( len >= 0 );  
98 - return len;  
99 - }  
100 - #define TIXML_SSCANF sscanf  
101 -#endif  
102 -  
103 -  
104 -static const char LINE_FEED = (char)0x0a; // all line endings are normalized to LF  
105 -static const char LF = LINE_FEED;  
106 -static const char CARRIAGE_RETURN = (char)0x0d; // CR gets filtered out  
107 -static const char CR = CARRIAGE_RETURN;  
108 -static const char SINGLE_QUOTE = '\'';  
109 -static const char DOUBLE_QUOTE = '\"';  
110 -  
111 -// Bunch of unicode info at:  
112 -// http://www.unicode.org/faq/utf_bom.html  
113 -// ef bb bf (Microsoft "lead bytes") - designates UTF-8  
114 -  
115 -static const unsigned char TIXML_UTF_LEAD_0 = 0xefU;  
116 -static const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;  
117 -static const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;  
118 -  
119 -namespace tinyxml2  
120 -{  
121 -  
122 -struct Entity {  
123 - const char* pattern;  
124 - int length;  
125 - char value;  
126 -};  
127 -  
128 -static const int NUM_ENTITIES = 5;  
129 -static const Entity entities[NUM_ENTITIES] = {  
130 - { "quot", 4, DOUBLE_QUOTE },  
131 - { "amp", 3, '&' },  
132 - { "apos", 4, SINGLE_QUOTE },  
133 - { "lt", 2, '<' },  
134 - { "gt", 2, '>' }  
135 -};  
136 -  
137 -  
138 -StrPair::~StrPair()  
139 -{  
140 - Reset();  
141 -}  
142 -  
143 -  
144 -void StrPair::TransferTo( StrPair* other )  
145 -{  
146 - if ( this == other ) {  
147 - return;  
148 - }  
149 - // This in effect implements the assignment operator by "moving"  
150 - // ownership (as in auto_ptr).  
151 -  
152 - TIXMLASSERT( other != 0 );  
153 - TIXMLASSERT( other->_flags == 0 );  
154 - TIXMLASSERT( other->_start == 0 );  
155 - TIXMLASSERT( other->_end == 0 );  
156 -  
157 - other->Reset();  
158 -  
159 - other->_flags = _flags;  
160 - other->_start = _start;  
161 - other->_end = _end;  
162 -  
163 - _flags = 0;  
164 - _start = 0;  
165 - _end = 0;  
166 -}  
167 -  
168 -  
169 -void StrPair::Reset()  
170 -{  
171 - if ( _flags & NEEDS_DELETE ) {  
172 - delete [] _start;  
173 - }  
174 - _flags = 0;  
175 - _start = 0;  
176 - _end = 0;  
177 -}  
178 -  
179 -  
180 -void StrPair::SetStr( const char* str, int flags )  
181 -{  
182 - TIXMLASSERT( str );  
183 - Reset();  
184 - size_t len = strlen( str );  
185 - TIXMLASSERT( _start == 0 );  
186 - _start = new char[ len+1 ];  
187 - memcpy( _start, str, len+1 );  
188 - _end = _start + len;  
189 - _flags = flags | NEEDS_DELETE;  
190 -}  
191 -  
192 -  
193 -char* StrPair::ParseText( char* p, const char* endTag, int strFlags, int* curLineNumPtr )  
194 -{  
195 - TIXMLASSERT( p );  
196 - TIXMLASSERT( endTag && *endTag );  
197 - TIXMLASSERT(curLineNumPtr);  
198 -  
199 - char* start = p;  
200 - char endChar = *endTag;  
201 - size_t length = strlen( endTag );  
202 -  
203 - // Inner loop of text parsing.  
204 - while ( *p ) {  
205 - if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) {  
206 - Set( start, p, strFlags );  
207 - return p + length;  
208 - } else if (*p == '\n') {  
209 - ++(*curLineNumPtr);  
210 - }  
211 - ++p;  
212 - TIXMLASSERT( p );  
213 - }  
214 - return 0;  
215 -}  
216 -  
217 -  
218 -char* StrPair::ParseName( char* p )  
219 -{  
220 - if ( !p || !(*p) ) {  
221 - return 0;  
222 - }  
223 - if ( !XMLUtil::IsNameStartChar( *p ) ) {  
224 - return 0;  
225 - }  
226 -  
227 - char* const start = p;  
228 - ++p;  
229 - while ( *p && XMLUtil::IsNameChar( *p ) ) {  
230 - ++p;  
231 - }  
232 -  
233 - Set( start, p, 0 );  
234 - return p;  
235 -}  
236 -  
237 -  
238 -void StrPair::CollapseWhitespace()  
239 -{  
240 - // Adjusting _start would cause undefined behavior on delete[]  
241 - TIXMLASSERT( ( _flags & NEEDS_DELETE ) == 0 );  
242 - // Trim leading space.  
243 - _start = XMLUtil::SkipWhiteSpace( _start, 0 );  
244 -  
245 - if ( *_start ) {  
246 - const char* p = _start; // the read pointer  
247 - char* q = _start; // the write pointer  
248 -  
249 - while( *p ) {  
250 - if ( XMLUtil::IsWhiteSpace( *p )) {  
251 - p = XMLUtil::SkipWhiteSpace( p, 0 );  
252 - if ( *p == 0 ) {  
253 - break; // don't write to q; this trims the trailing space.  
254 - }  
255 - *q = ' ';  
256 - ++q;  
257 - }  
258 - *q = *p;  
259 - ++q;  
260 - ++p;  
261 - }  
262 - *q = 0;  
263 - }  
264 -}  
265 -  
266 -  
267 -const char* StrPair::GetStr()  
268 -{  
269 - TIXMLASSERT( _start );  
270 - TIXMLASSERT( _end );  
271 - if ( _flags & NEEDS_FLUSH ) {  
272 - *_end = 0;  
273 - _flags ^= NEEDS_FLUSH;  
274 -  
275 - if ( _flags ) {  
276 - const char* p = _start; // the read pointer  
277 - char* q = _start; // the write pointer  
278 -  
279 - while( p < _end ) {  
280 - if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == CR ) {  
281 - // CR-LF pair becomes LF  
282 - // CR alone becomes LF  
283 - // LF-CR becomes LF  
284 - if ( *(p+1) == LF ) {  
285 - p += 2;  
286 - }  
287 - else {  
288 - ++p;  
289 - }  
290 - *q = LF;  
291 - ++q;  
292 - }  
293 - else if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == LF ) {  
294 - if ( *(p+1) == CR ) {  
295 - p += 2;  
296 - }  
297 - else {  
298 - ++p;  
299 - }  
300 - *q = LF;  
301 - ++q;  
302 - }  
303 - else if ( (_flags & NEEDS_ENTITY_PROCESSING) && *p == '&' ) {  
304 - // Entities handled by tinyXML2:  
305 - // - special entities in the entity table [in/out]  
306 - // - numeric character reference [in]  
307 - // &#20013; or &#x4e2d;  
308 -  
309 - if ( *(p+1) == '#' ) {  
310 - const int buflen = 10;  
311 - char buf[buflen] = { 0 };  
312 - int len = 0;  
313 - char* adjusted = const_cast<char*>( XMLUtil::GetCharacterRef( p, buf, &len ) );  
314 - if ( adjusted == 0 ) {  
315 - *q = *p;  
316 - ++p;  
317 - ++q;  
318 - }  
319 - else {  
320 - TIXMLASSERT( 0 <= len && len <= buflen );  
321 - TIXMLASSERT( q + len <= adjusted );  
322 - p = adjusted;  
323 - memcpy( q, buf, len );  
324 - q += len;  
325 - }  
326 - }  
327 - else {  
328 - bool entityFound = false;  
329 - for( int i = 0; i < NUM_ENTITIES; ++i ) {  
330 - const Entity& entity = entities[i];  
331 - if ( strncmp( p + 1, entity.pattern, entity.length ) == 0  
332 - && *( p + entity.length + 1 ) == ';' ) {  
333 - // Found an entity - convert.  
334 - *q = entity.value;  
335 - ++q;  
336 - p += entity.length + 2;  
337 - entityFound = true;  
338 - break;  
339 - }  
340 - }  
341 - if ( !entityFound ) {  
342 - // fixme: treat as error?  
343 - ++p;  
344 - ++q;  
345 - }  
346 - }  
347 - }  
348 - else {  
349 - *q = *p;  
350 - ++p;  
351 - ++q;  
352 - }  
353 - }  
354 - *q = 0;  
355 - }  
356 - // The loop below has plenty going on, and this  
357 - // is a less useful mode. Break it out.  
358 - if ( _flags & NEEDS_WHITESPACE_COLLAPSING ) {  
359 - CollapseWhitespace();  
360 - }  
361 - _flags = (_flags & NEEDS_DELETE);  
362 - }  
363 - TIXMLASSERT( _start );  
364 - return _start;  
365 -}  
366 -  
367 -  
368 -  
369 -  
370 -// --------- XMLUtil ----------- //  
371 -  
372 -const char* XMLUtil::writeBoolTrue = "true";  
373 -const char* XMLUtil::writeBoolFalse = "false";  
374 -  
375 -void XMLUtil::SetBoolSerialization(const char* writeTrue, const char* writeFalse)  
376 -{  
377 - static const char* defTrue = "true";  
378 - static const char* defFalse = "false";  
379 -  
380 - writeBoolTrue = (writeTrue) ? writeTrue : defTrue;  
381 - writeBoolFalse = (writeFalse) ? writeFalse : defFalse;  
382 -}  
383 -  
384 -  
385 -const char* XMLUtil::ReadBOM( const char* p, bool* bom )  
386 -{  
387 - TIXMLASSERT( p );  
388 - TIXMLASSERT( bom );  
389 - *bom = false;  
390 - const unsigned char* pu = reinterpret_cast<const unsigned char*>(p);  
391 - // Check for BOM:  
392 - if ( *(pu+0) == TIXML_UTF_LEAD_0  
393 - && *(pu+1) == TIXML_UTF_LEAD_1  
394 - && *(pu+2) == TIXML_UTF_LEAD_2 ) {  
395 - *bom = true;  
396 - p += 3;  
397 - }  
398 - TIXMLASSERT( p );  
399 - return p;  
400 -}  
401 -  
402 -  
403 -void XMLUtil::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length )  
404 -{  
405 - const unsigned long BYTE_MASK = 0xBF;  
406 - const unsigned long BYTE_MARK = 0x80;  
407 - const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };  
408 -  
409 - if (input < 0x80) {  
410 - *length = 1;  
411 - }  
412 - else if ( input < 0x800 ) {  
413 - *length = 2;  
414 - }  
415 - else if ( input < 0x10000 ) {  
416 - *length = 3;  
417 - }  
418 - else if ( input < 0x200000 ) {  
419 - *length = 4;  
420 - }  
421 - else {  
422 - *length = 0; // This code won't convert this correctly anyway.  
423 - return;  
424 - }  
425 -  
426 - output += *length;  
427 -  
428 - // Scary scary fall throughs are annotated with carefully designed comments  
429 - // to suppress compiler warnings such as -Wimplicit-fallthrough in gcc  
430 - switch (*length) {  
431 - case 4:  
432 - --output;  
433 - *output = (char)((input | BYTE_MARK) & BYTE_MASK);  
434 - input >>= 6;  
435 - //fall through  
436 - case 3:  
437 - --output;  
438 - *output = (char)((input | BYTE_MARK) & BYTE_MASK);  
439 - input >>= 6;  
440 - //fall through  
441 - case 2:  
442 - --output;  
443 - *output = (char)((input | BYTE_MARK) & BYTE_MASK);  
444 - input >>= 6;  
445 - //fall through  
446 - case 1:  
447 - --output;  
448 - *output = (char)(input | FIRST_BYTE_MARK[*length]);  
449 - break;  
450 - default:  
451 - TIXMLASSERT( false );  
452 - }  
453 -}  
454 -  
455 -  
456 -const char* XMLUtil::GetCharacterRef( const char* p, char* value, int* length )  
457 -{  
458 - // Presume an entity, and pull it out.  
459 - *length = 0;  
460 -  
461 - if ( *(p+1) == '#' && *(p+2) ) {  
462 - unsigned long ucs = 0;  
463 - TIXMLASSERT( sizeof( ucs ) >= 4 );  
464 - ptrdiff_t delta = 0;  
465 - unsigned mult = 1;  
466 - static const char SEMICOLON = ';';  
467 -  
468 - if ( *(p+2) == 'x' ) {  
469 - // Hexadecimal.  
470 - const char* q = p+3;  
471 - if ( !(*q) ) {  
472 - return 0;  
473 - }  
474 -  
475 - q = strchr( q, SEMICOLON );  
476 -  
477 - if ( !q ) {  
478 - return 0;  
479 - }  
480 - TIXMLASSERT( *q == SEMICOLON );  
481 -  
482 - delta = q-p;  
483 - --q;  
484 -  
485 - while ( *q != 'x' ) {  
486 - unsigned int digit = 0;  
487 -  
488 - if ( *q >= '0' && *q <= '9' ) {  
489 - digit = *q - '0';  
490 - }  
491 - else if ( *q >= 'a' && *q <= 'f' ) {  
492 - digit = *q - 'a' + 10;  
493 - }  
494 - else if ( *q >= 'A' && *q <= 'F' ) {  
495 - digit = *q - 'A' + 10;  
496 - }  
497 - else {  
498 - return 0;  
499 - }  
500 - TIXMLASSERT( digit < 16 );  
501 - TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit );  
502 - const unsigned int digitScaled = mult * digit;  
503 - TIXMLASSERT( ucs <= ULONG_MAX - digitScaled );  
504 - ucs += digitScaled;  
505 - TIXMLASSERT( mult <= UINT_MAX / 16 );  
506 - mult *= 16;  
507 - --q;  
508 - }  
509 - }  
510 - else {  
511 - // Decimal.  
512 - const char* q = p+2;  
513 - if ( !(*q) ) {  
514 - return 0;  
515 - }  
516 -  
517 - q = strchr( q, SEMICOLON );  
518 -  
519 - if ( !q ) {  
520 - return 0;  
521 - }  
522 - TIXMLASSERT( *q == SEMICOLON );  
523 -  
524 - delta = q-p;  
525 - --q;  
526 -  
527 - while ( *q != '#' ) {  
528 - if ( *q >= '0' && *q <= '9' ) {  
529 - const unsigned int digit = *q - '0';  
530 - TIXMLASSERT( digit < 10 );  
531 - TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit );  
532 - const unsigned int digitScaled = mult * digit;  
533 - TIXMLASSERT( ucs <= ULONG_MAX - digitScaled );  
534 - ucs += digitScaled;  
535 - }  
536 - else {  
537 - return 0;  
538 - }  
539 - TIXMLASSERT( mult <= UINT_MAX / 10 );  
540 - mult *= 10;  
541 - --q;  
542 - }  
543 - }  
544 - // convert the UCS to UTF-8  
545 - ConvertUTF32ToUTF8( ucs, value, length );  
546 - return p + delta + 1;  
547 - }  
548 - return p+1;  
549 -}  
550 -  
551 -  
552 -void XMLUtil::ToStr( int v, char* buffer, int bufferSize )  
553 -{  
554 - TIXML_SNPRINTF( buffer, bufferSize, "%d", v );  
555 -}  
556 -  
557 -  
558 -void XMLUtil::ToStr( unsigned v, char* buffer, int bufferSize )  
559 -{  
560 - TIXML_SNPRINTF( buffer, bufferSize, "%u", v );  
561 -}  
562 -  
563 -  
564 -void XMLUtil::ToStr( bool v, char* buffer, int bufferSize )  
565 -{  
566 - TIXML_SNPRINTF( buffer, bufferSize, "%s", v ? writeBoolTrue : writeBoolFalse);  
567 -}  
568 -  
569 -/*  
570 - ToStr() of a number is a very tricky topic.  
571 - https://github.com/leethomason/tinyxml2/issues/106  
572 -*/  
573 -void XMLUtil::ToStr( float v, char* buffer, int bufferSize )  
574 -{  
575 - TIXML_SNPRINTF( buffer, bufferSize, "%.8g", v );  
576 -}  
577 -  
578 -  
579 -void XMLUtil::ToStr( double v, char* buffer, int bufferSize )  
580 -{  
581 - TIXML_SNPRINTF( buffer, bufferSize, "%.17g", v );  
582 -}  
583 -  
584 -  
585 -void XMLUtil::ToStr(int64_t v, char* buffer, int bufferSize)  
586 -{  
587 - // horrible syntax trick to make the compiler happy about %lld  
588 - TIXML_SNPRINTF(buffer, bufferSize, "%lld", (long long)v);  
589 -}  
590 -  
591 -  
592 -bool XMLUtil::ToInt( const char* str, int* value )  
593 -{  
594 - if ( TIXML_SSCANF( str, "%d", value ) == 1 ) {  
595 - return true;  
596 - }  
597 - return false;  
598 -}  
599 -  
600 -bool XMLUtil::ToUnsigned( const char* str, unsigned *value )  
601 -{  
602 - if ( TIXML_SSCANF( str, "%u", value ) == 1 ) {  
603 - return true;  
604 - }  
605 - return false;  
606 -}  
607 -  
608 -bool XMLUtil::ToBool( const char* str, bool* value )  
609 -{  
610 - int ival = 0;  
611 - if ( ToInt( str, &ival )) {  
612 - *value = (ival==0) ? false : true;  
613 - return true;  
614 - }  
615 - if ( StringEqual( str, "true" ) ) {  
616 - *value = true;  
617 - return true;  
618 - }  
619 - else if ( StringEqual( str, "false" ) ) {  
620 - *value = false;  
621 - return true;  
622 - }  
623 - return false;  
624 -}  
625 -  
626 -  
627 -bool XMLUtil::ToFloat( const char* str, float* value )  
628 -{  
629 - if ( TIXML_SSCANF( str, "%f", value ) == 1 ) {  
630 - return true;  
631 - }  
632 - return false;  
633 -}  
634 -  
635 -  
636 -bool XMLUtil::ToDouble( const char* str, double* value )  
637 -{  
638 - if ( TIXML_SSCANF( str, "%lf", value ) == 1 ) {  
639 - return true;  
640 - }  
641 - return false;  
642 -}  
643 -  
644 -  
645 -bool XMLUtil::ToInt64(const char* str, int64_t* value)  
646 -{  
647 - long long v = 0; // horrible syntax trick to make the compiler happy about %lld  
648 - if (TIXML_SSCANF(str, "%lld", &v) == 1) {  
649 - *value = (int64_t)v;  
650 - return true;  
651 - }  
652 - return false;  
653 -}  
654 -  
655 -  
656 -char* XMLDocument::Identify( char* p, XMLNode** node )  
657 -{  
658 - TIXMLASSERT( node );  
659 - TIXMLASSERT( p );  
660 - char* const start = p;  
661 - int const startLine = _parseCurLineNum;  
662 - p = XMLUtil::SkipWhiteSpace( p, &_parseCurLineNum );  
663 - if( !*p ) {  
664 - *node = 0;  
665 - TIXMLASSERT( p );  
666 - return p;  
667 - }  
668 -  
669 - // These strings define the matching patterns:  
670 - static const char* xmlHeader = { "<?" };  
671 - static const char* commentHeader = { "<!--" };  
672 - static const char* cdataHeader = { "<![CDATA[" };  
673 - static const char* dtdHeader = { "<!" };  
674 - static const char* elementHeader = { "<" }; // and a header for everything else; check last.  
675 -  
676 - static const int xmlHeaderLen = 2;  
677 - static const int commentHeaderLen = 4;  
678 - static const int cdataHeaderLen = 9;  
679 - static const int dtdHeaderLen = 2;  
680 - static const int elementHeaderLen = 1;  
681 -  
682 - TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLUnknown ) ); // use same memory pool  
683 - TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLDeclaration ) ); // use same memory pool  
684 - XMLNode* returnNode = 0;  
685 - if ( XMLUtil::StringEqual( p, xmlHeader, xmlHeaderLen ) ) {  
686 - returnNode = CreateUnlinkedNode<XMLDeclaration>( _commentPool );  
687 - returnNode->_parseLineNum = _parseCurLineNum;  
688 - p += xmlHeaderLen;  
689 - }  
690 - else if ( XMLUtil::StringEqual( p, commentHeader, commentHeaderLen ) ) {  
691 - returnNode = CreateUnlinkedNode<XMLComment>( _commentPool );  
692 - returnNode->_parseLineNum = _parseCurLineNum;  
693 - p += commentHeaderLen;  
694 - }  
695 - else if ( XMLUtil::StringEqual( p, cdataHeader, cdataHeaderLen ) ) {  
696 - XMLText* text = CreateUnlinkedNode<XMLText>( _textPool );  
697 - returnNode = text;  
698 - returnNode->_parseLineNum = _parseCurLineNum;  
699 - p += cdataHeaderLen;  
700 - text->SetCData( true );  
701 - }  
702 - else if ( XMLUtil::StringEqual( p, dtdHeader, dtdHeaderLen ) ) {  
703 - returnNode = CreateUnlinkedNode<XMLUnknown>( _commentPool );  
704 - returnNode->_parseLineNum = _parseCurLineNum;  
705 - p += dtdHeaderLen;  
706 - }  
707 - else if ( XMLUtil::StringEqual( p, elementHeader, elementHeaderLen ) ) {  
708 - returnNode = CreateUnlinkedNode<XMLElement>( _elementPool );  
709 - returnNode->_parseLineNum = _parseCurLineNum;  
710 - p += elementHeaderLen;  
711 - }  
712 - else {  
713 - returnNode = CreateUnlinkedNode<XMLText>( _textPool );  
714 - returnNode->_parseLineNum = _parseCurLineNum; // Report line of first non-whitespace character  
715 - p = start; // Back it up, all the text counts.  
716 - _parseCurLineNum = startLine;  
717 - }  
718 -  
719 - TIXMLASSERT( returnNode );  
720 - TIXMLASSERT( p );  
721 - *node = returnNode;  
722 - return p;  
723 -}  
724 -  
725 -  
726 -bool XMLDocument::Accept( XMLVisitor* visitor ) const  
727 -{  
728 - TIXMLASSERT( visitor );  
729 - if ( visitor->VisitEnter( *this ) ) {  
730 - for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) {  
731 - if ( !node->Accept( visitor ) ) {  
732 - break;  
733 - }  
734 - }  
735 - }  
736 - return visitor->VisitExit( *this );  
737 -}  
738 -  
739 -  
740 -// --------- XMLNode ----------- //  
741 -  
742 -XMLNode::XMLNode( XMLDocument* doc ) :  
743 - _document( doc ),  
744 - _parent( 0 ),  
745 - _value(),  
746 - _parseLineNum( 0 ),  
747 - _firstChild( 0 ), _lastChild( 0 ),  
748 - _prev( 0 ), _next( 0 ),  
749 - _userData( 0 ),  
750 - _memPool( 0 )  
751 -{  
752 -}  
753 -  
754 -  
755 -XMLNode::~XMLNode()  
756 -{  
757 - DeleteChildren();  
758 - if ( _parent ) {  
759 - _parent->Unlink( this );  
760 - }  
761 -}  
762 -  
763 -const char* XMLNode::Value() const  
764 -{  
765 - // Edge case: XMLDocuments don't have a Value. Return null.  
766 - if ( this->ToDocument() )  
767 - return 0;  
768 - return _value.GetStr();  
769 -}  
770 -  
771 -void XMLNode::SetValue( const char* str, bool staticMem )  
772 -{  
773 - if ( staticMem ) {  
774 - _value.SetInternedStr( str );  
775 - }  
776 - else {  
777 - _value.SetStr( str );  
778 - }  
779 -}  
780 -  
781 -XMLNode* XMLNode::DeepClone(XMLDocument* target) const  
782 -{  
783 - XMLNode* clone = this->ShallowClone(target);  
784 - if (!clone) return 0;  
785 -  
786 - for (const XMLNode* child = this->FirstChild(); child; child = child->NextSibling()) {  
787 - XMLNode* childClone = child->DeepClone(target);  
788 - TIXMLASSERT(childClone);  
789 - clone->InsertEndChild(childClone);  
790 - }  
791 - return clone;  
792 -}  
793 -  
794 -void XMLNode::DeleteChildren()  
795 -{  
796 - while( _firstChild ) {  
797 - TIXMLASSERT( _lastChild );  
798 - DeleteChild( _firstChild );  
799 - }  
800 - _firstChild = _lastChild = 0;  
801 -}  
802 -  
803 -  
804 -void XMLNode::Unlink( XMLNode* child )  
805 -{  
806 - TIXMLASSERT( child );  
807 - TIXMLASSERT( child->_document == _document );  
808 - TIXMLASSERT( child->_parent == this );  
809 - if ( child == _firstChild ) {  
810 - _firstChild = _firstChild->_next;  
811 - }  
812 - if ( child == _lastChild ) {  
813 - _lastChild = _lastChild->_prev;  
814 - }  
815 -  
816 - if ( child->_prev ) {  
817 - child->_prev->_next = child->_next;  
818 - }  
819 - if ( child->_next ) {  
820 - child->_next->_prev = child->_prev;  
821 - }  
822 - child->_next = 0;  
823 - child->_prev = 0;  
824 - child->_parent = 0;  
825 -}  
826 -  
827 -  
828 -void XMLNode::DeleteChild( XMLNode* node )  
829 -{  
830 - TIXMLASSERT( node );  
831 - TIXMLASSERT( node->_document == _document );  
832 - TIXMLASSERT( node->_parent == this );  
833 - Unlink( node );  
834 - TIXMLASSERT(node->_prev == 0);  
835 - TIXMLASSERT(node->_next == 0);  
836 - TIXMLASSERT(node->_parent == 0);  
837 - DeleteNode( node );  
838 -}  
839 -  
840 -  
841 -XMLNode* XMLNode::InsertEndChild( XMLNode* addThis )  
842 -{  
843 - TIXMLASSERT( addThis );  
844 - if ( addThis->_document != _document ) {  
845 - TIXMLASSERT( false );  
846 - return 0;  
847 - }  
848 - InsertChildPreamble( addThis );  
849 -  
850 - if ( _lastChild ) {  
851 - TIXMLASSERT( _firstChild );  
852 - TIXMLASSERT( _lastChild->_next == 0 );  
853 - _lastChild->_next = addThis;  
854 - addThis->_prev = _lastChild;  
855 - _lastChild = addThis;  
856 -  
857 - addThis->_next = 0;  
858 - }  
859 - else {  
860 - TIXMLASSERT( _firstChild == 0 );  
861 - _firstChild = _lastChild = addThis;  
862 -  
863 - addThis->_prev = 0;  
864 - addThis->_next = 0;  
865 - }  
866 - addThis->_parent = this;  
867 - return addThis;  
868 -}  
869 -  
870 -  
871 -XMLNode* XMLNode::InsertFirstChild( XMLNode* addThis )  
872 -{  
873 - TIXMLASSERT( addThis );  
874 - if ( addThis->_document != _document ) {  
875 - TIXMLASSERT( false );  
876 - return 0;  
877 - }  
878 - InsertChildPreamble( addThis );  
879 -  
880 - if ( _firstChild ) {  
881 - TIXMLASSERT( _lastChild );  
882 - TIXMLASSERT( _firstChild->_prev == 0 );  
883 -  
884 - _firstChild->_prev = addThis;  
885 - addThis->_next = _firstChild;  
886 - _firstChild = addThis;  
887 -  
888 - addThis->_prev = 0;  
889 - }  
890 - else {  
891 - TIXMLASSERT( _lastChild == 0 );  
892 - _firstChild = _lastChild = addThis;  
893 -  
894 - addThis->_prev = 0;  
895 - addThis->_next = 0;  
896 - }  
897 - addThis->_parent = this;  
898 - return addThis;  
899 -}  
900 -  
901 -  
902 -XMLNode* XMLNode::InsertAfterChild( XMLNode* afterThis, XMLNode* addThis )  
903 -{  
904 - TIXMLASSERT( addThis );  
905 - if ( addThis->_document != _document ) {  
906 - TIXMLASSERT( false );  
907 - return 0;  
908 - }  
909 -  
910 - TIXMLASSERT( afterThis );  
911 -  
912 - if ( afterThis->_parent != this ) {  
913 - TIXMLASSERT( false );  
914 - return 0;  
915 - }  
916 - if ( afterThis == addThis ) {  
917 - // Current state: BeforeThis -> AddThis -> OneAfterAddThis  
918 - // Now AddThis must disappear from it's location and then  
919 - // reappear between BeforeThis and OneAfterAddThis.  
920 - // So just leave it where it is.  
921 - return addThis;  
922 - }  
923 -  
924 - if ( afterThis->_next == 0 ) {  
925 - // The last node or the only node.  
926 - return InsertEndChild( addThis );  
927 - }  
928 - InsertChildPreamble( addThis );  
929 - addThis->_prev = afterThis;  
930 - addThis->_next = afterThis->_next;  
931 - afterThis->_next->_prev = addThis;  
932 - afterThis->_next = addThis;  
933 - addThis->_parent = this;  
934 - return addThis;  
935 -}  
936 -  
937 -  
938 -  
939 -  
940 -const XMLElement* XMLNode::FirstChildElement( const char* name ) const  
941 -{  
942 - for( const XMLNode* node = _firstChild; node; node = node->_next ) {  
943 - const XMLElement* element = node->ToElementWithName( name );  
944 - if ( element ) {  
945 - return element;  
946 - }  
947 - }  
948 - return 0;  
949 -}  
950 -  
951 -  
952 -const XMLElement* XMLNode::LastChildElement( const char* name ) const  
953 -{  
954 - for( const XMLNode* node = _lastChild; node; node = node->_prev ) {  
955 - const XMLElement* element = node->ToElementWithName( name );  
956 - if ( element ) {  
957 - return element;  
958 - }  
959 - }  
960 - return 0;  
961 -}  
962 -  
963 -  
964 -const XMLElement* XMLNode::NextSiblingElement( const char* name ) const  
965 -{  
966 - for( const XMLNode* node = _next; node; node = node->_next ) {  
967 - const XMLElement* element = node->ToElementWithName( name );  
968 - if ( element ) {  
969 - return element;  
970 - }  
971 - }  
972 - return 0;  
973 -}  
974 -  
975 -  
976 -const XMLElement* XMLNode::PreviousSiblingElement( const char* name ) const  
977 -{  
978 - for( const XMLNode* node = _prev; node; node = node->_prev ) {  
979 - const XMLElement* element = node->ToElementWithName( name );  
980 - if ( element ) {  
981 - return element;  
982 - }  
983 - }  
984 - return 0;  
985 -}  
986 -  
987 -  
988 -char* XMLNode::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr )  
989 -{  
990 - // This is a recursive method, but thinking about it "at the current level"  
991 - // it is a pretty simple flat list:  
992 - // <foo/>  
993 - // <!-- comment -->  
994 - //  
995 - // With a special case:  
996 - // <foo>  
997 - // </foo>  
998 - // <!-- comment -->  
999 - //  
1000 - // Where the closing element (/foo) *must* be the next thing after the opening  
1001 - // element, and the names must match. BUT the tricky bit is that the closing  
1002 - // element will be read by the child.  
1003 - //  
1004 - // 'endTag' is the end tag for this node, it is returned by a call to a child.  
1005 - // 'parentEnd' is the end tag for the parent, which is filled in and returned.  
1006 -  
1007 - XMLDocument::DepthTracker tracker(_document);  
1008 - if (_document->Error())  
1009 - return 0;  
1010 -  
1011 - while( p && *p ) {  
1012 - XMLNode* node = 0;  
1013 -  
1014 - p = _document->Identify( p, &node );  
1015 - TIXMLASSERT( p );  
1016 - if ( node == 0 ) {  
1017 - break;  
1018 - }  
1019 -  
1020 - int initialLineNum = node->_parseLineNum;  
1021 -  
1022 - StrPair endTag;  
1023 - p = node->ParseDeep( p, &endTag, curLineNumPtr );  
1024 - if ( !p ) {  
1025 - DeleteNode( node );  
1026 - if ( !_document->Error() ) {  
1027 - _document->SetError( XML_ERROR_PARSING, initialLineNum, 0);  
1028 - }  
1029 - break;  
1030 - }  
1031 -  
1032 - XMLDeclaration* decl = node->ToDeclaration();  
1033 - if ( decl ) {  
1034 - // Declarations are only allowed at document level  
1035 - bool wellLocated = ( ToDocument() != 0 );  
1036 - if ( wellLocated ) {  
1037 - // Multiple declarations are allowed but all declarations  
1038 - // must occur before anything else  
1039 - for ( const XMLNode* existingNode = _document->FirstChild(); existingNode; existingNode = existingNode->NextSibling() ) {  
1040 - if ( !existingNode->ToDeclaration() ) {  
1041 - wellLocated = false;  
1042 - break;  
1043 - }  
1044 - }  
1045 - }  
1046 - if ( !wellLocated ) {  
1047 - _document->SetError( XML_ERROR_PARSING_DECLARATION, initialLineNum, "XMLDeclaration value=%s", decl->Value());  
1048 - DeleteNode( node );  
1049 - break;  
1050 - }  
1051 - }  
1052 -  
1053 - XMLElement* ele = node->ToElement();  
1054 - if ( ele ) {  
1055 - // We read the end tag. Return it to the parent.  
1056 - if ( ele->ClosingType() == XMLElement::CLOSING ) {  
1057 - if ( parentEndTag ) {  
1058 - ele->_value.TransferTo( parentEndTag );  
1059 - }  
1060 - node->_memPool->SetTracked(); // created and then immediately deleted.  
1061 - DeleteNode( node );  
1062 - return p;  
1063 - }  
1064 -  
1065 - // Handle an end tag returned to this level.  
1066 - // And handle a bunch of annoying errors.  
1067 - bool mismatch = false;  
1068 - if ( endTag.Empty() ) {  
1069 - if ( ele->ClosingType() == XMLElement::OPEN ) {  
1070 - mismatch = true;  
1071 - }  
1072 - }  
1073 - else {  
1074 - if ( ele->ClosingType() != XMLElement::OPEN ) {  
1075 - mismatch = true;  
1076 - }  
1077 - else if ( !XMLUtil::StringEqual( endTag.GetStr(), ele->Name() ) ) {  
1078 - mismatch = true;  
1079 - }  
1080 - }  
1081 - if ( mismatch ) {  
1082 - _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, initialLineNum, "XMLElement name=%s", ele->Name());  
1083 - DeleteNode( node );  
1084 - break;  
1085 - }  
1086 - }  
1087 - InsertEndChild( node );  
1088 - }  
1089 - return 0;  
1090 -}  
1091 -  
1092 -/*static*/ void XMLNode::DeleteNode( XMLNode* node )  
1093 -{  
1094 - if ( node == 0 ) {  
1095 - return;  
1096 - }  
1097 - TIXMLASSERT(node->_document);  
1098 - if (!node->ToDocument()) {  
1099 - node->_document->MarkInUse(node);  
1100 - }  
1101 -  
1102 - MemPool* pool = node->_memPool;  
1103 - node->~XMLNode();  
1104 - pool->Free( node );  
1105 -}  
1106 -  
1107 -void XMLNode::InsertChildPreamble( XMLNode* insertThis ) const  
1108 -{  
1109 - TIXMLASSERT( insertThis );  
1110 - TIXMLASSERT( insertThis->_document == _document );  
1111 -  
1112 - if (insertThis->_parent) {  
1113 - insertThis->_parent->Unlink( insertThis );  
1114 - }  
1115 - else {  
1116 - insertThis->_document->MarkInUse(insertThis);  
1117 - insertThis->_memPool->SetTracked();  
1118 - }  
1119 -}  
1120 -  
1121 -const XMLElement* XMLNode::ToElementWithName( const char* name ) const  
1122 -{  
1123 - const XMLElement* element = this->ToElement();  
1124 - if ( element == 0 ) {  
1125 - return 0;  
1126 - }  
1127 - if ( name == 0 ) {  
1128 - return element;  
1129 - }  
1130 - if ( XMLUtil::StringEqual( element->Name(), name ) ) {  
1131 - return element;  
1132 - }  
1133 - return 0;  
1134 -}  
1135 -  
1136 -// --------- XMLText ---------- //  
1137 -char* XMLText::ParseDeep( char* p, StrPair*, int* curLineNumPtr )  
1138 -{  
1139 - if ( this->CData() ) {  
1140 - p = _value.ParseText( p, "]]>", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr );  
1141 - if ( !p ) {  
1142 - _document->SetError( XML_ERROR_PARSING_CDATA, _parseLineNum, 0 );  
1143 - }  
1144 - return p;  
1145 - }  
1146 - else {  
1147 - int flags = _document->ProcessEntities() ? StrPair::TEXT_ELEMENT : StrPair::TEXT_ELEMENT_LEAVE_ENTITIES;  
1148 - if ( _document->WhitespaceMode() == COLLAPSE_WHITESPACE ) {  
1149 - flags |= StrPair::NEEDS_WHITESPACE_COLLAPSING;  
1150 - }  
1151 -  
1152 - p = _value.ParseText( p, "<", flags, curLineNumPtr );  
1153 - if ( p && *p ) {  
1154 - return p-1;  
1155 - }  
1156 - if ( !p ) {  
1157 - _document->SetError( XML_ERROR_PARSING_TEXT, _parseLineNum, 0 );  
1158 - }  
1159 - }  
1160 - return 0;  
1161 -}  
1162 -  
1163 -  
1164 -XMLNode* XMLText::ShallowClone( XMLDocument* doc ) const  
1165 -{  
1166 - if ( !doc ) {  
1167 - doc = _document;  
1168 - }  
1169 - XMLText* text = doc->NewText( Value() ); // fixme: this will always allocate memory. Intern?  
1170 - text->SetCData( this->CData() );  
1171 - return text;  
1172 -}  
1173 -  
1174 -  
1175 -bool XMLText::ShallowEqual( const XMLNode* compare ) const  
1176 -{  
1177 - TIXMLASSERT( compare );  
1178 - const XMLText* text = compare->ToText();  
1179 - return ( text && XMLUtil::StringEqual( text->Value(), Value() ) );  
1180 -}  
1181 -  
1182 -  
1183 -bool XMLText::Accept( XMLVisitor* visitor ) const  
1184 -{  
1185 - TIXMLASSERT( visitor );  
1186 - return visitor->Visit( *this );  
1187 -}  
1188 -  
1189 -  
1190 -// --------- XMLComment ---------- //  
1191 -  
1192 -XMLComment::XMLComment( XMLDocument* doc ) : XMLNode( doc )  
1193 -{  
1194 -}  
1195 -  
1196 -  
1197 -XMLComment::~XMLComment()  
1198 -{  
1199 -}  
1200 -  
1201 -  
1202 -char* XMLComment::ParseDeep( char* p, StrPair*, int* curLineNumPtr )  
1203 -{  
1204 - // Comment parses as text.  
1205 - p = _value.ParseText( p, "-->", StrPair::COMMENT, curLineNumPtr );  
1206 - if ( p == 0 ) {  
1207 - _document->SetError( XML_ERROR_PARSING_COMMENT, _parseLineNum, 0 );  
1208 - }  
1209 - return p;  
1210 -}  
1211 -  
1212 -  
1213 -XMLNode* XMLComment::ShallowClone( XMLDocument* doc ) const  
1214 -{  
1215 - if ( !doc ) {  
1216 - doc = _document;  
1217 - }  
1218 - XMLComment* comment = doc->NewComment( Value() ); // fixme: this will always allocate memory. Intern?  
1219 - return comment;  
1220 -}  
1221 -  
1222 -  
1223 -bool XMLComment::ShallowEqual( const XMLNode* compare ) const  
1224 -{  
1225 - TIXMLASSERT( compare );  
1226 - const XMLComment* comment = compare->ToComment();  
1227 - return ( comment && XMLUtil::StringEqual( comment->Value(), Value() ));  
1228 -}  
1229 -  
1230 -  
1231 -bool XMLComment::Accept( XMLVisitor* visitor ) const  
1232 -{  
1233 - TIXMLASSERT( visitor );  
1234 - return visitor->Visit( *this );  
1235 -}  
1236 -  
1237 -  
1238 -// --------- XMLDeclaration ---------- //  
1239 -  
1240 -XMLDeclaration::XMLDeclaration( XMLDocument* doc ) : XMLNode( doc )  
1241 -{  
1242 -}  
1243 -  
1244 -  
1245 -XMLDeclaration::~XMLDeclaration()  
1246 -{  
1247 - //printf( "~XMLDeclaration\n" );  
1248 -}  
1249 -  
1250 -  
1251 -char* XMLDeclaration::ParseDeep( char* p, StrPair*, int* curLineNumPtr )  
1252 -{  
1253 - // Declaration parses as text.  
1254 - p = _value.ParseText( p, "?>", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr );  
1255 - if ( p == 0 ) {  
1256 - _document->SetError( XML_ERROR_PARSING_DECLARATION, _parseLineNum, 0 );  
1257 - }  
1258 - return p;  
1259 -}  
1260 -  
1261 -  
1262 -XMLNode* XMLDeclaration::ShallowClone( XMLDocument* doc ) const  
1263 -{  
1264 - if ( !doc ) {  
1265 - doc = _document;  
1266 - }  
1267 - XMLDeclaration* dec = doc->NewDeclaration( Value() ); // fixme: this will always allocate memory. Intern?  
1268 - return dec;  
1269 -}  
1270 -  
1271 -  
1272 -bool XMLDeclaration::ShallowEqual( const XMLNode* compare ) const  
1273 -{  
1274 - TIXMLASSERT( compare );  
1275 - const XMLDeclaration* declaration = compare->ToDeclaration();  
1276 - return ( declaration && XMLUtil::StringEqual( declaration->Value(), Value() ));  
1277 -}  
1278 -  
1279 -  
1280 -  
1281 -bool XMLDeclaration::Accept( XMLVisitor* visitor ) const  
1282 -{  
1283 - TIXMLASSERT( visitor );  
1284 - return visitor->Visit( *this );  
1285 -}  
1286 -  
1287 -// --------- XMLUnknown ---------- //  
1288 -  
1289 -XMLUnknown::XMLUnknown( XMLDocument* doc ) : XMLNode( doc )  
1290 -{  
1291 -}  
1292 -  
1293 -  
1294 -XMLUnknown::~XMLUnknown()  
1295 -{  
1296 -}  
1297 -  
1298 -  
1299 -char* XMLUnknown::ParseDeep( char* p, StrPair*, int* curLineNumPtr )  
1300 -{  
1301 - // Unknown parses as text.  
1302 - p = _value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr );  
1303 - if ( !p ) {  
1304 - _document->SetError( XML_ERROR_PARSING_UNKNOWN, _parseLineNum, 0 );  
1305 - }  
1306 - return p;  
1307 -}  
1308 -  
1309 -  
1310 -XMLNode* XMLUnknown::ShallowClone( XMLDocument* doc ) const  
1311 -{  
1312 - if ( !doc ) {  
1313 - doc = _document;  
1314 - }  
1315 - XMLUnknown* text = doc->NewUnknown( Value() ); // fixme: this will always allocate memory. Intern?  
1316 - return text;  
1317 -}  
1318 -  
1319 -  
1320 -bool XMLUnknown::ShallowEqual( const XMLNode* compare ) const  
1321 -{  
1322 - TIXMLASSERT( compare );  
1323 - const XMLUnknown* unknown = compare->ToUnknown();  
1324 - return ( unknown && XMLUtil::StringEqual( unknown->Value(), Value() ));  
1325 -}  
1326 -  
1327 -  
1328 -bool XMLUnknown::Accept( XMLVisitor* visitor ) const  
1329 -{  
1330 - TIXMLASSERT( visitor );  
1331 - return visitor->Visit( *this );  
1332 -}  
1333 -  
1334 -// --------- XMLAttribute ---------- //  
1335 -  
1336 -const char* XMLAttribute::Name() const  
1337 -{  
1338 - return _name.GetStr();  
1339 -}  
1340 -  
1341 -const char* XMLAttribute::Value() const  
1342 -{  
1343 - return _value.GetStr();  
1344 -}  
1345 -  
1346 -char* XMLAttribute::ParseDeep( char* p, bool processEntities, int* curLineNumPtr )  
1347 -{  
1348 - // Parse using the name rules: bug fix, was using ParseText before  
1349 - p = _name.ParseName( p );  
1350 - if ( !p || !*p ) {  
1351 - return 0;  
1352 - }  
1353 -  
1354 - // Skip white space before =  
1355 - p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr );  
1356 - if ( *p != '=' ) {  
1357 - return 0;  
1358 - }  
1359 -  
1360 - ++p; // move up to opening quote  
1361 - p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr );  
1362 - if ( *p != '\"' && *p != '\'' ) {  
1363 - return 0;  
1364 - }  
1365 -  
1366 - char endTag[2] = { *p, 0 };  
1367 - ++p; // move past opening quote  
1368 -  
1369 - p = _value.ParseText( p, endTag, processEntities ? StrPair::ATTRIBUTE_VALUE : StrPair::ATTRIBUTE_VALUE_LEAVE_ENTITIES, curLineNumPtr );  
1370 - return p;  
1371 -}  
1372 -  
1373 -  
1374 -void XMLAttribute::SetName( const char* n )  
1375 -{  
1376 - _name.SetStr( n );  
1377 -}  
1378 -  
1379 -  
1380 -XMLError XMLAttribute::QueryIntValue( int* value ) const  
1381 -{  
1382 - if ( XMLUtil::ToInt( Value(), value )) {  
1383 - return XML_SUCCESS;  
1384 - }  
1385 - return XML_WRONG_ATTRIBUTE_TYPE;  
1386 -}  
1387 -  
1388 -  
1389 -XMLError XMLAttribute::QueryUnsignedValue( unsigned int* value ) const  
1390 -{  
1391 - if ( XMLUtil::ToUnsigned( Value(), value )) {  
1392 - return XML_SUCCESS;  
1393 - }  
1394 - return XML_WRONG_ATTRIBUTE_TYPE;  
1395 -}  
1396 -  
1397 -  
1398 -XMLError XMLAttribute::QueryInt64Value(int64_t* value) const  
1399 -{  
1400 - if (XMLUtil::ToInt64(Value(), value)) {  
1401 - return XML_SUCCESS;  
1402 - }  
1403 - return XML_WRONG_ATTRIBUTE_TYPE;  
1404 -}  
1405 -  
1406 -  
1407 -XMLError XMLAttribute::QueryBoolValue( bool* value ) const  
1408 -{  
1409 - if ( XMLUtil::ToBool( Value(), value )) {  
1410 - return XML_SUCCESS;  
1411 - }  
1412 - return XML_WRONG_ATTRIBUTE_TYPE;  
1413 -}  
1414 -  
1415 -  
1416 -XMLError XMLAttribute::QueryFloatValue( float* value ) const  
1417 -{  
1418 - if ( XMLUtil::ToFloat( Value(), value )) {  
1419 - return XML_SUCCESS;  
1420 - }  
1421 - return XML_WRONG_ATTRIBUTE_TYPE;  
1422 -}  
1423 -  
1424 -  
1425 -XMLError XMLAttribute::QueryDoubleValue( double* value ) const  
1426 -{  
1427 - if ( XMLUtil::ToDouble( Value(), value )) {  
1428 - return XML_SUCCESS;  
1429 - }  
1430 - return XML_WRONG_ATTRIBUTE_TYPE;  
1431 -}  
1432 -  
1433 -  
1434 -void XMLAttribute::SetAttribute( const char* v )  
1435 -{  
1436 - _value.SetStr( v );  
1437 -}  
1438 -  
1439 -  
1440 -void XMLAttribute::SetAttribute( int v )  
1441 -{  
1442 - char buf[BUF_SIZE];  
1443 - XMLUtil::ToStr( v, buf, BUF_SIZE );  
1444 - _value.SetStr( buf );  
1445 -}  
1446 -  
1447 -  
1448 -void XMLAttribute::SetAttribute( unsigned v )  
1449 -{  
1450 - char buf[BUF_SIZE];  
1451 - XMLUtil::ToStr( v, buf, BUF_SIZE );  
1452 - _value.SetStr( buf );  
1453 -}  
1454 -  
1455 -  
1456 -void XMLAttribute::SetAttribute(int64_t v)  
1457 -{  
1458 - char buf[BUF_SIZE];  
1459 - XMLUtil::ToStr(v, buf, BUF_SIZE);  
1460 - _value.SetStr(buf);  
1461 -}  
1462 -  
1463 -  
1464 -  
1465 -void XMLAttribute::SetAttribute( bool v )  
1466 -{  
1467 - char buf[BUF_SIZE];  
1468 - XMLUtil::ToStr( v, buf, BUF_SIZE );  
1469 - _value.SetStr( buf );  
1470 -}  
1471 -  
1472 -void XMLAttribute::SetAttribute( double v )  
1473 -{  
1474 - char buf[BUF_SIZE];  
1475 - XMLUtil::ToStr( v, buf, BUF_SIZE );  
1476 - _value.SetStr( buf );  
1477 -}  
1478 -  
1479 -void XMLAttribute::SetAttribute( float v )  
1480 -{  
1481 - char buf[BUF_SIZE];  
1482 - XMLUtil::ToStr( v, buf, BUF_SIZE );  
1483 - _value.SetStr( buf );  
1484 -}  
1485 -  
1486 -  
1487 -// --------- XMLElement ---------- //  
1488 -XMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ),  
1489 - _closingType( OPEN ),  
1490 - _rootAttribute( 0 )  
1491 -{  
1492 -}  
1493 -  
1494 -  
1495 -XMLElement::~XMLElement()  
1496 -{  
1497 - while( _rootAttribute ) {  
1498 - XMLAttribute* next = _rootAttribute->_next;  
1499 - DeleteAttribute( _rootAttribute );  
1500 - _rootAttribute = next;  
1501 - }  
1502 -}  
1503 -  
1504 -  
1505 -const XMLAttribute* XMLElement::FindAttribute( const char* name ) const  
1506 -{  
1507 - for( XMLAttribute* a = _rootAttribute; a; a = a->_next ) {  
1508 - if ( XMLUtil::StringEqual( a->Name(), name ) ) {  
1509 - return a;  
1510 - }  
1511 - }  
1512 - return 0;  
1513 -}  
1514 -  
1515 -  
1516 -const char* XMLElement::Attribute( const char* name, const char* value ) const  
1517 -{  
1518 - const XMLAttribute* a = FindAttribute( name );  
1519 - if ( !a ) {  
1520 - return 0;  
1521 - }  
1522 - if ( !value || XMLUtil::StringEqual( a->Value(), value )) {  
1523 - return a->Value();  
1524 - }  
1525 - return 0;  
1526 -}  
1527 -  
1528 -int XMLElement::IntAttribute(const char* name, int defaultValue) const  
1529 -{  
1530 - int i = defaultValue;  
1531 - QueryIntAttribute(name, &i);  
1532 - return i;  
1533 -}  
1534 -  
1535 -unsigned XMLElement::UnsignedAttribute(const char* name, unsigned defaultValue) const  
1536 -{  
1537 - unsigned i = defaultValue;  
1538 - QueryUnsignedAttribute(name, &i);  
1539 - return i;  
1540 -}  
1541 -  
1542 -int64_t XMLElement::Int64Attribute(const char* name, int64_t defaultValue) const  
1543 -{  
1544 - int64_t i = defaultValue;  
1545 - QueryInt64Attribute(name, &i);  
1546 - return i;  
1547 -}  
1548 -  
1549 -bool XMLElement::BoolAttribute(const char* name, bool defaultValue) const  
1550 -{  
1551 - bool b = defaultValue;  
1552 - QueryBoolAttribute(name, &b);  
1553 - return b;  
1554 -}  
1555 -  
1556 -double XMLElement::DoubleAttribute(const char* name, double defaultValue) const  
1557 -{  
1558 - double d = defaultValue;  
1559 - QueryDoubleAttribute(name, &d);  
1560 - return d;  
1561 -}  
1562 -  
1563 -float XMLElement::FloatAttribute(const char* name, float defaultValue) const  
1564 -{  
1565 - float f = defaultValue;  
1566 - QueryFloatAttribute(name, &f);  
1567 - return f;  
1568 -}  
1569 -  
1570 -const char* XMLElement::GetText() const  
1571 -{  
1572 - if ( FirstChild() && FirstChild()->ToText() ) {  
1573 - return FirstChild()->Value();  
1574 - }  
1575 - return 0;  
1576 -}  
1577 -  
1578 -  
1579 -void XMLElement::SetText( const char* inText )  
1580 -{  
1581 - if ( FirstChild() && FirstChild()->ToText() )  
1582 - FirstChild()->SetValue( inText );  
1583 - else {  
1584 - XMLText* theText = GetDocument()->NewText( inText );  
1585 - InsertFirstChild( theText );  
1586 - }  
1587 -}  
1588 -  
1589 -  
1590 -void XMLElement::SetText( int v )  
1591 -{  
1592 - char buf[BUF_SIZE];  
1593 - XMLUtil::ToStr( v, buf, BUF_SIZE );  
1594 - SetText( buf );  
1595 -}  
1596 -  
1597 -  
1598 -void XMLElement::SetText( unsigned v )  
1599 -{  
1600 - char buf[BUF_SIZE];  
1601 - XMLUtil::ToStr( v, buf, BUF_SIZE );  
1602 - SetText( buf );  
1603 -}  
1604 -  
1605 -  
1606 -void XMLElement::SetText(int64_t v)  
1607 -{  
1608 - char buf[BUF_SIZE];  
1609 - XMLUtil::ToStr(v, buf, BUF_SIZE);  
1610 - SetText(buf);  
1611 -}  
1612 -  
1613 -  
1614 -void XMLElement::SetText( bool v )  
1615 -{  
1616 - char buf[BUF_SIZE];  
1617 - XMLUtil::ToStr( v, buf, BUF_SIZE );  
1618 - SetText( buf );  
1619 -}  
1620 -  
1621 -  
1622 -void XMLElement::SetText( float v )  
1623 -{  
1624 - char buf[BUF_SIZE];  
1625 - XMLUtil::ToStr( v, buf, BUF_SIZE );  
1626 - SetText( buf );  
1627 -}  
1628 -  
1629 -  
1630 -void XMLElement::SetText( double v )  
1631 -{  
1632 - char buf[BUF_SIZE];  
1633 - XMLUtil::ToStr( v, buf, BUF_SIZE );  
1634 - SetText( buf );  
1635 -}  
1636 -  
1637 -  
1638 -XMLError XMLElement::QueryIntText( int* ival ) const  
1639 -{  
1640 - if ( FirstChild() && FirstChild()->ToText() ) {  
1641 - const char* t = FirstChild()->Value();  
1642 - if ( XMLUtil::ToInt( t, ival ) ) {  
1643 - return XML_SUCCESS;  
1644 - }  
1645 - return XML_CAN_NOT_CONVERT_TEXT;  
1646 - }  
1647 - return XML_NO_TEXT_NODE;  
1648 -}  
1649 -  
1650 -  
1651 -XMLError XMLElement::QueryUnsignedText( unsigned* uval ) const  
1652 -{  
1653 - if ( FirstChild() && FirstChild()->ToText() ) {  
1654 - const char* t = FirstChild()->Value();  
1655 - if ( XMLUtil::ToUnsigned( t, uval ) ) {  
1656 - return XML_SUCCESS;  
1657 - }  
1658 - return XML_CAN_NOT_CONVERT_TEXT;  
1659 - }  
1660 - return XML_NO_TEXT_NODE;  
1661 -}  
1662 -  
1663 -  
1664 -XMLError XMLElement::QueryInt64Text(int64_t* ival) const  
1665 -{  
1666 - if (FirstChild() && FirstChild()->ToText()) {  
1667 - const char* t = FirstChild()->Value();  
1668 - if (XMLUtil::ToInt64(t, ival)) {  
1669 - return XML_SUCCESS;  
1670 - }  
1671 - return XML_CAN_NOT_CONVERT_TEXT;  
1672 - }  
1673 - return XML_NO_TEXT_NODE;  
1674 -}  
1675 -  
1676 -  
1677 -XMLError XMLElement::QueryBoolText( bool* bval ) const  
1678 -{  
1679 - if ( FirstChild() && FirstChild()->ToText() ) {  
1680 - const char* t = FirstChild()->Value();  
1681 - if ( XMLUtil::ToBool( t, bval ) ) {  
1682 - return XML_SUCCESS;  
1683 - }  
1684 - return XML_CAN_NOT_CONVERT_TEXT;  
1685 - }  
1686 - return XML_NO_TEXT_NODE;  
1687 -}  
1688 -  
1689 -  
1690 -XMLError XMLElement::QueryDoubleText( double* dval ) const  
1691 -{  
1692 - if ( FirstChild() && FirstChild()->ToText() ) {  
1693 - const char* t = FirstChild()->Value();  
1694 - if ( XMLUtil::ToDouble( t, dval ) ) {  
1695 - return XML_SUCCESS;  
1696 - }  
1697 - return XML_CAN_NOT_CONVERT_TEXT;  
1698 - }  
1699 - return XML_NO_TEXT_NODE;  
1700 -}  
1701 -  
1702 -  
1703 -XMLError XMLElement::QueryFloatText( float* fval ) const  
1704 -{  
1705 - if ( FirstChild() && FirstChild()->ToText() ) {  
1706 - const char* t = FirstChild()->Value();  
1707 - if ( XMLUtil::ToFloat( t, fval ) ) {  
1708 - return XML_SUCCESS;  
1709 - }  
1710 - return XML_CAN_NOT_CONVERT_TEXT;  
1711 - }  
1712 - return XML_NO_TEXT_NODE;  
1713 -}  
1714 -  
1715 -int XMLElement::IntText(int defaultValue) const  
1716 -{  
1717 - int i = defaultValue;  
1718 - QueryIntText(&i);  
1719 - return i;  
1720 -}  
1721 -  
1722 -unsigned XMLElement::UnsignedText(unsigned defaultValue) const  
1723 -{  
1724 - unsigned i = defaultValue;  
1725 - QueryUnsignedText(&i);  
1726 - return i;  
1727 -}  
1728 -  
1729 -int64_t XMLElement::Int64Text(int64_t defaultValue) const  
1730 -{  
1731 - int64_t i = defaultValue;  
1732 - QueryInt64Text(&i);  
1733 - return i;  
1734 -}  
1735 -  
1736 -bool XMLElement::BoolText(bool defaultValue) const  
1737 -{  
1738 - bool b = defaultValue;  
1739 - QueryBoolText(&b);  
1740 - return b;  
1741 -}  
1742 -  
1743 -double XMLElement::DoubleText(double defaultValue) const  
1744 -{  
1745 - double d = defaultValue;  
1746 - QueryDoubleText(&d);  
1747 - return d;  
1748 -}  
1749 -  
1750 -float XMLElement::FloatText(float defaultValue) const  
1751 -{  
1752 - float f = defaultValue;  
1753 - QueryFloatText(&f);  
1754 - return f;  
1755 -}  
1756 -  
1757 -  
1758 -XMLAttribute* XMLElement::FindOrCreateAttribute( const char* name )  
1759 -{  
1760 - XMLAttribute* last = 0;  
1761 - XMLAttribute* attrib = 0;  
1762 - for( attrib = _rootAttribute;  
1763 - attrib;  
1764 - last = attrib, attrib = attrib->_next ) {  
1765 - if ( XMLUtil::StringEqual( attrib->Name(), name ) ) {  
1766 - break;  
1767 - }  
1768 - }  
1769 - if ( !attrib ) {  
1770 - attrib = CreateAttribute();  
1771 - TIXMLASSERT( attrib );  
1772 - if ( last ) {  
1773 - TIXMLASSERT( last->_next == 0 );  
1774 - last->_next = attrib;  
1775 - }  
1776 - else {  
1777 - TIXMLASSERT( _rootAttribute == 0 );  
1778 - _rootAttribute = attrib;  
1779 - }  
1780 - attrib->SetName( name );  
1781 - }  
1782 - return attrib;  
1783 -}  
1784 -  
1785 -  
1786 -void XMLElement::DeleteAttribute( const char* name )  
1787 -{  
1788 - XMLAttribute* prev = 0;  
1789 - for( XMLAttribute* a=_rootAttribute; a; a=a->_next ) {  
1790 - if ( XMLUtil::StringEqual( name, a->Name() ) ) {  
1791 - if ( prev ) {  
1792 - prev->_next = a->_next;  
1793 - }  
1794 - else {  
1795 - _rootAttribute = a->_next;  
1796 - }  
1797 - DeleteAttribute( a );  
1798 - break;  
1799 - }  
1800 - prev = a;  
1801 - }  
1802 -}  
1803 -  
1804 -  
1805 -char* XMLElement::ParseAttributes( char* p, int* curLineNumPtr )  
1806 -{  
1807 - XMLAttribute* prevAttribute = 0;  
1808 -  
1809 - // Read the attributes.  
1810 - while( p ) {  
1811 - p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr );  
1812 - if ( !(*p) ) {  
1813 - _document->SetError( XML_ERROR_PARSING_ELEMENT, _parseLineNum, "XMLElement name=%s", Name() );  
1814 - return 0;  
1815 - }  
1816 -  
1817 - // attribute.  
1818 - if (XMLUtil::IsNameStartChar( *p ) ) {  
1819 - XMLAttribute* attrib = CreateAttribute();  
1820 - TIXMLASSERT( attrib );  
1821 - attrib->_parseLineNum = _document->_parseCurLineNum;  
1822 -  
1823 - int attrLineNum = attrib->_parseLineNum;  
1824 -  
1825 - p = attrib->ParseDeep( p, _document->ProcessEntities(), curLineNumPtr );  
1826 - if ( !p || Attribute( attrib->Name() ) ) {  
1827 - DeleteAttribute( attrib );  
1828 - _document->SetError( XML_ERROR_PARSING_ATTRIBUTE, attrLineNum, "XMLElement name=%s", Name() );  
1829 - return 0;  
1830 - }  
1831 - // There is a minor bug here: if the attribute in the source xml  
1832 - // document is duplicated, it will not be detected and the  
1833 - // attribute will be doubly added. However, tracking the 'prevAttribute'  
1834 - // avoids re-scanning the attribute list. Preferring performance for  
1835 - // now, may reconsider in the future.  
1836 - if ( prevAttribute ) {  
1837 - TIXMLASSERT( prevAttribute->_next == 0 );  
1838 - prevAttribute->_next = attrib;  
1839 - }  
1840 - else {  
1841 - TIXMLASSERT( _rootAttribute == 0 );  
1842 - _rootAttribute = attrib;  
1843 - }  
1844 - prevAttribute = attrib;  
1845 - }  
1846 - // end of the tag  
1847 - else if ( *p == '>' ) {  
1848 - ++p;  
1849 - break;  
1850 - }  
1851 - // end of the tag  
1852 - else if ( *p == '/' && *(p+1) == '>' ) {  
1853 - _closingType = CLOSED;  
1854 - return p+2; // done; sealed element.  
1855 - }  
1856 - else {  
1857 - _document->SetError( XML_ERROR_PARSING_ELEMENT, _parseLineNum, 0 );  
1858 - return 0;  
1859 - }  
1860 - }  
1861 - return p;  
1862 -}  
1863 -  
1864 -void XMLElement::DeleteAttribute( XMLAttribute* attribute )  
1865 -{  
1866 - if ( attribute == 0 ) {  
1867 - return;  
1868 - }  
1869 - MemPool* pool = attribute->_memPool;  
1870 - attribute->~XMLAttribute();  
1871 - pool->Free( attribute );  
1872 -}  
1873 -  
1874 -XMLAttribute* XMLElement::CreateAttribute()  
1875 -{  
1876 - TIXMLASSERT( sizeof( XMLAttribute ) == _document->_attributePool.ItemSize() );  
1877 - XMLAttribute* attrib = new (_document->_attributePool.Alloc() ) XMLAttribute();  
1878 - TIXMLASSERT( attrib );  
1879 - attrib->_memPool = &_document->_attributePool;  
1880 - attrib->_memPool->SetTracked();  
1881 - return attrib;  
1882 -}  
1883 -  
1884 -//  
1885 -// <ele></ele>  
1886 -// <ele>foo<b>bar</b></ele>  
1887 -//  
1888 -char* XMLElement::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr )  
1889 -{  
1890 - // Read the element name.  
1891 - p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr );  
1892 -  
1893 - // The closing element is the </element> form. It is  
1894 - // parsed just like a regular element then deleted from  
1895 - // the DOM.  
1896 - if ( *p == '/' ) {  
1897 - _closingType = CLOSING;  
1898 - ++p;  
1899 - }  
1900 -  
1901 - p = _value.ParseName( p );  
1902 - if ( _value.Empty() ) {  
1903 - return 0;  
1904 - }  
1905 -  
1906 - p = ParseAttributes( p, curLineNumPtr );  
1907 - if ( !p || !*p || _closingType != OPEN ) {  
1908 - return p;  
1909 - }  
1910 -  
1911 - p = XMLNode::ParseDeep( p, parentEndTag, curLineNumPtr );  
1912 - return p;  
1913 -}  
1914 -  
1915 -  
1916 -  
1917 -XMLNode* XMLElement::ShallowClone( XMLDocument* doc ) const  
1918 -{  
1919 - if ( !doc ) {  
1920 - doc = _document;  
1921 - }  
1922 - XMLElement* element = doc->NewElement( Value() ); // fixme: this will always allocate memory. Intern?  
1923 - for( const XMLAttribute* a=FirstAttribute(); a; a=a->Next() ) {  
1924 - element->SetAttribute( a->Name(), a->Value() ); // fixme: this will always allocate memory. Intern?  
1925 - }  
1926 - return element;  
1927 -}  
1928 -  
1929 -  
1930 -bool XMLElement::ShallowEqual( const XMLNode* compare ) const  
1931 -{  
1932 - TIXMLASSERT( compare );  
1933 - const XMLElement* other = compare->ToElement();  
1934 - if ( other && XMLUtil::StringEqual( other->Name(), Name() )) {  
1935 -  
1936 - const XMLAttribute* a=FirstAttribute();  
1937 - const XMLAttribute* b=other->FirstAttribute();  
1938 -  
1939 - while ( a && b ) {  
1940 - if ( !XMLUtil::StringEqual( a->Value(), b->Value() ) ) {  
1941 - return false;  
1942 - }  
1943 - a = a->Next();  
1944 - b = b->Next();  
1945 - }  
1946 - if ( a || b ) {  
1947 - // different count  
1948 - return false;  
1949 - }  
1950 - return true;  
1951 - }  
1952 - return false;  
1953 -}  
1954 -  
1955 -  
1956 -bool XMLElement::Accept( XMLVisitor* visitor ) const  
1957 -{  
1958 - TIXMLASSERT( visitor );  
1959 - if ( visitor->VisitEnter( *this, _rootAttribute ) ) {  
1960 - for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) {  
1961 - if ( !node->Accept( visitor ) ) {  
1962 - break;  
1963 - }  
1964 - }  
1965 - }  
1966 - return visitor->VisitExit( *this );  
1967 -}  
1968 -  
1969 -  
1970 -// --------- XMLDocument ----------- //  
1971 -  
1972 -// Warning: List must match 'enum XMLError'  
1973 -const char* XMLDocument::_errorNames[XML_ERROR_COUNT] = {  
1974 - "XML_SUCCESS",  
1975 - "XML_NO_ATTRIBUTE",  
1976 - "XML_WRONG_ATTRIBUTE_TYPE",  
1977 - "XML_ERROR_FILE_NOT_FOUND",  
1978 - "XML_ERROR_FILE_COULD_NOT_BE_OPENED",  
1979 - "XML_ERROR_FILE_READ_ERROR",  
1980 - "UNUSED_XML_ERROR_ELEMENT_MISMATCH",  
1981 - "XML_ERROR_PARSING_ELEMENT",  
1982 - "XML_ERROR_PARSING_ATTRIBUTE",  
1983 - "UNUSED_XML_ERROR_IDENTIFYING_TAG",  
1984 - "XML_ERROR_PARSING_TEXT",  
1985 - "XML_ERROR_PARSING_CDATA",  
1986 - "XML_ERROR_PARSING_COMMENT",  
1987 - "XML_ERROR_PARSING_DECLARATION",  
1988 - "XML_ERROR_PARSING_UNKNOWN",  
1989 - "XML_ERROR_EMPTY_DOCUMENT",  
1990 - "XML_ERROR_MISMATCHED_ELEMENT",  
1991 - "XML_ERROR_PARSING",  
1992 - "XML_CAN_NOT_CONVERT_TEXT",  
1993 - "XML_NO_TEXT_NODE",  
1994 - "XML_ELEMENT_DEPTH_EXCEEDED"  
1995 -};  
1996 -  
1997 -  
1998 -XMLDocument::XMLDocument( bool processEntities, Whitespace whitespaceMode ) :  
1999 - XMLNode( 0 ),  
2000 - _writeBOM( false ),  
2001 - _processEntities( processEntities ),  
2002 - _errorID(XML_SUCCESS),  
2003 - _whitespaceMode( whitespaceMode ),  
2004 - _errorStr(),  
2005 - _errorLineNum( 0 ),  
2006 - _charBuffer( 0 ),  
2007 - _parseCurLineNum( 0 ),  
2008 - _parsingDepth(0),  
2009 - _unlinked(),  
2010 - _elementPool(),  
2011 - _attributePool(),  
2012 - _textPool(),  
2013 - _commentPool()  
2014 -{  
2015 - // avoid VC++ C4355 warning about 'this' in initializer list (C4355 is off by default in VS2012+)  
2016 - _document = this;  
2017 -}  
2018 -  
2019 -  
2020 -XMLDocument::~XMLDocument()  
2021 -{  
2022 - Clear();  
2023 -}  
2024 -  
2025 -  
2026 -void XMLDocument::MarkInUse(XMLNode* node)  
2027 -{  
2028 - TIXMLASSERT(node);  
2029 - TIXMLASSERT(node->_parent == 0);  
2030 -  
2031 - for (int i = 0; i < _unlinked.Size(); ++i) {  
2032 - if (node == _unlinked[i]) {  
2033 - _unlinked.SwapRemove(i);  
2034 - break;  
2035 - }  
2036 - }  
2037 -}  
2038 -  
2039 -void XMLDocument::Clear()  
2040 -{  
2041 - DeleteChildren();  
2042 - while( _unlinked.Size()) {  
2043 - DeleteNode(_unlinked[0]); // Will remove from _unlinked as part of delete.  
2044 - }  
2045 -  
2046 -#ifdef TINYXML2_DEBUG  
2047 - const bool hadError = Error();  
2048 -#endif  
2049 - ClearError();  
2050 -  
2051 - delete [] _charBuffer;  
2052 - _charBuffer = 0;  
2053 - _parsingDepth = 0;  
2054 -  
2055 -#if 0  
2056 - _textPool.Trace( "text" );  
2057 - _elementPool.Trace( "element" );  
2058 - _commentPool.Trace( "comment" );  
2059 - _attributePool.Trace( "attribute" );  
2060 -#endif  
2061 -  
2062 -#ifdef TINYXML2_DEBUG  
2063 - if ( !hadError ) {  
2064 - TIXMLASSERT( _elementPool.CurrentAllocs() == _elementPool.Untracked() );  
2065 - TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() );  
2066 - TIXMLASSERT( _textPool.CurrentAllocs() == _textPool.Untracked() );  
2067 - TIXMLASSERT( _commentPool.CurrentAllocs() == _commentPool.Untracked() );  
2068 - }  
2069 -#endif  
2070 -}  
2071 -  
2072 -  
2073 -void XMLDocument::DeepCopy(XMLDocument* target) const  
2074 -{  
2075 - TIXMLASSERT(target);  
2076 - if (target == this) {  
2077 - return; // technically success - a no-op.  
2078 - }  
2079 -  
2080 - target->Clear();  
2081 - for (const XMLNode* node = this->FirstChild(); node; node = node->NextSibling()) {  
2082 - target->InsertEndChild(node->DeepClone(target));  
2083 - }  
2084 -}  
2085 -  
2086 -XMLElement* XMLDocument::NewElement( const char* name )  
2087 -{  
2088 - XMLElement* ele = CreateUnlinkedNode<XMLElement>( _elementPool );  
2089 - ele->SetName( name );  
2090 - return ele;  
2091 -}  
2092 -  
2093 -  
2094 -XMLComment* XMLDocument::NewComment( const char* str )  
2095 -{  
2096 - XMLComment* comment = CreateUnlinkedNode<XMLComment>( _commentPool );  
2097 - comment->SetValue( str );  
2098 - return comment;  
2099 -}  
2100 -  
2101 -  
2102 -XMLText* XMLDocument::NewText( const char* str )  
2103 -{  
2104 - XMLText* text = CreateUnlinkedNode<XMLText>( _textPool );  
2105 - text->SetValue( str );  
2106 - return text;  
2107 -}  
2108 -  
2109 -  
2110 -XMLDeclaration* XMLDocument::NewDeclaration( const char* str )  
2111 -{  
2112 - XMLDeclaration* dec = CreateUnlinkedNode<XMLDeclaration>( _commentPool );  
2113 - dec->SetValue( str ? str : "xml version=\"1.0\" encoding=\"UTF-8\"" );  
2114 - return dec;  
2115 -}  
2116 -  
2117 -  
2118 -XMLUnknown* XMLDocument::NewUnknown( const char* str )  
2119 -{  
2120 - XMLUnknown* unk = CreateUnlinkedNode<XMLUnknown>( _commentPool );  
2121 - unk->SetValue( str );  
2122 - return unk;  
2123 -}  
2124 -  
2125 -static FILE* callfopen( const char* filepath, const char* mode )  
2126 -{  
2127 - TIXMLASSERT( filepath );  
2128 - TIXMLASSERT( mode );  
2129 -#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE)  
2130 - FILE* fp = 0;  
2131 - errno_t err = fopen_s( &fp, filepath, mode );  
2132 - if ( err ) {  
2133 - return 0;  
2134 - }  
2135 -#else  
2136 - FILE* fp = fopen( filepath, mode );  
2137 -#endif  
2138 - return fp;  
2139 -}  
2140 -  
2141 -void XMLDocument::DeleteNode( XMLNode* node ) {  
2142 - TIXMLASSERT( node );  
2143 - TIXMLASSERT(node->_document == this );  
2144 - if (node->_parent) {  
2145 - node->_parent->DeleteChild( node );  
2146 - }  
2147 - else {  
2148 - // Isn't in the tree.  
2149 - // Use the parent delete.  
2150 - // Also, we need to mark it tracked: we 'know'  
2151 - // it was never used.  
2152 - node->_memPool->SetTracked();  
2153 - // Call the static XMLNode version:  
2154 - XMLNode::DeleteNode(node);  
2155 - }  
2156 -}  
2157 -  
2158 -  
2159 -XMLError XMLDocument::LoadFile( const char* filename )  
2160 -{  
2161 - if ( !filename ) {  
2162 - TIXMLASSERT( false );  
2163 - SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=<null>" );  
2164 - return _errorID;  
2165 - }  
2166 -  
2167 - Clear();  
2168 - FILE* fp = callfopen( filename, "rb" );  
2169 - if ( !fp ) {  
2170 - SetError( XML_ERROR_FILE_NOT_FOUND, 0, "filename=%s", filename );  
2171 - return _errorID;  
2172 - }  
2173 - LoadFile( fp );  
2174 - fclose( fp );  
2175 - return _errorID;  
2176 -}  
2177 -  
2178 -// This is likely overengineered template art to have a check that unsigned long value incremented  
2179 -// by one still fits into size_t. If size_t type is larger than unsigned long type  
2180 -// (x86_64-w64-mingw32 target) then the check is redundant and gcc and clang emit  
2181 -// -Wtype-limits warning. This piece makes the compiler select code with a check when a check  
2182 -// is useful and code with no check when a check is redundant depending on how size_t and unsigned long  
2183 -// types sizes relate to each other.  
2184 -template  
2185 -<bool = (sizeof(unsigned long) >= sizeof(size_t))>  
2186 -struct LongFitsIntoSizeTMinusOne {  
2187 - static bool Fits( unsigned long value )  
2188 - {  
2189 - return value < (size_t)-1;  
2190 - }  
2191 -};  
2192 -  
2193 -template <>  
2194 -struct LongFitsIntoSizeTMinusOne<false> {  
2195 - static bool Fits( unsigned long )  
2196 - {  
2197 - return true;  
2198 - }  
2199 -};  
2200 -  
2201 -XMLError XMLDocument::LoadFile( FILE* fp )  
2202 -{  
2203 - Clear();  
2204 -  
2205 - fseek( fp, 0, SEEK_SET );  
2206 - if ( fgetc( fp ) == EOF && ferror( fp ) != 0 ) {  
2207 - SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 );  
2208 - return _errorID;  
2209 - }  
2210 -  
2211 - fseek( fp, 0, SEEK_END );  
2212 - const long filelength = ftell( fp );  
2213 - fseek( fp, 0, SEEK_SET );  
2214 - if ( filelength == -1L ) {  
2215 - SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 );  
2216 - return _errorID;  
2217 - }  
2218 - TIXMLASSERT( filelength >= 0 );  
2219 -  
2220 - if ( !LongFitsIntoSizeTMinusOne<>::Fits( filelength ) ) {  
2221 - // Cannot handle files which won't fit in buffer together with null terminator  
2222 - SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 );  
2223 - return _errorID;  
2224 - }  
2225 -  
2226 - if ( filelength == 0 ) {  
2227 - SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );  
2228 - return _errorID;  
2229 - }  
2230 -  
2231 - const size_t size = filelength;  
2232 - TIXMLASSERT( _charBuffer == 0 );  
2233 - _charBuffer = new char[size+1];  
2234 - size_t read = fread( _charBuffer, 1, size, fp );  
2235 - if ( read != size ) {  
2236 - SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 );  
2237 - return _errorID;  
2238 - }  
2239 -  
2240 - _charBuffer[size] = 0;  
2241 -  
2242 - Parse();  
2243 - return _errorID;  
2244 -}  
2245 -  
2246 -  
2247 -XMLError XMLDocument::SaveFile( const char* filename, bool compact )  
2248 -{  
2249 - if ( !filename ) {  
2250 - TIXMLASSERT( false );  
2251 - SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=<null>" );  
2252 - return _errorID;  
2253 - }  
2254 -  
2255 - FILE* fp = callfopen( filename, "w" );  
2256 - if ( !fp ) {  
2257 - SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=%s", filename );  
2258 - return _errorID;  
2259 - }  
2260 - SaveFile(fp, compact);  
2261 - fclose( fp );  
2262 - return _errorID;  
2263 -}  
2264 -  
2265 -  
2266 -XMLError XMLDocument::SaveFile( FILE* fp, bool compact )  
2267 -{  
2268 - // Clear any error from the last save, otherwise it will get reported  
2269 - // for *this* call.  
2270 - ClearError();  
2271 - XMLPrinter stream( fp, compact );  
2272 - Print( &stream );  
2273 - return _errorID;  
2274 -}  
2275 -  
2276 -  
2277 -XMLError XMLDocument::Parse( const char* p, size_t len )  
2278 -{  
2279 - Clear();  
2280 -  
2281 - if ( len == 0 || !p || !*p ) {  
2282 - SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );  
2283 - return _errorID;  
2284 - }  
2285 - if ( len == (size_t)(-1) ) {  
2286 - len = strlen( p );  
2287 - }  
2288 - TIXMLASSERT( _charBuffer == 0 );  
2289 - _charBuffer = new char[ len+1 ];  
2290 - memcpy( _charBuffer, p, len );  
2291 - _charBuffer[len] = 0;  
2292 -  
2293 - Parse();  
2294 - if ( Error() ) {  
2295 - // clean up now essentially dangling memory.  
2296 - // and the parse fail can put objects in the  
2297 - // pools that are dead and inaccessible.  
2298 - DeleteChildren();  
2299 - _elementPool.Clear();  
2300 - _attributePool.Clear();  
2301 - _textPool.Clear();  
2302 - _commentPool.Clear();  
2303 - }  
2304 - return _errorID;  
2305 -}  
2306 -  
2307 -  
2308 -void XMLDocument::Print( XMLPrinter* streamer ) const  
2309 -{  
2310 - if ( streamer ) {  
2311 - Accept( streamer );  
2312 - }  
2313 - else {  
2314 - XMLPrinter stdoutStreamer( stdout );  
2315 - Accept( &stdoutStreamer );  
2316 - }  
2317 -}  
2318 -  
2319 -  
2320 -void XMLDocument::SetError( XMLError error, int lineNum, const char* format, ... )  
2321 -{  
2322 - TIXMLASSERT( error >= 0 && error < XML_ERROR_COUNT );  
2323 - _errorID = error;  
2324 - _errorLineNum = lineNum;  
2325 - _errorStr.Reset();  
2326 -  
2327 - size_t BUFFER_SIZE = 1000;  
2328 - char* buffer = new char[BUFFER_SIZE];  
2329 -  
2330 - TIXML_SNPRINTF(buffer, BUFFER_SIZE, "Error=%s ErrorID=%d (0x%x) Line number=%d", ErrorIDToName(error), int(error), int(error), lineNum);  
2331 -  
2332 - if (format) {  
2333 - size_t len = strlen(buffer);  
2334 - TIXML_SNPRINTF(buffer + len, BUFFER_SIZE - len, ": ");  
2335 - len = strlen(buffer);  
2336 -  
2337 - va_list va;  
2338 - va_start(va, format);  
2339 - TIXML_VSNPRINTF(buffer + len, BUFFER_SIZE - len, format, va);  
2340 - va_end(va);  
2341 - }  
2342 - _errorStr.SetStr(buffer);  
2343 - delete[] buffer;  
2344 -}  
2345 -  
2346 -  
2347 -/*static*/ const char* XMLDocument::ErrorIDToName(XMLError errorID)  
2348 -{  
2349 - TIXMLASSERT( errorID >= 0 && errorID < XML_ERROR_COUNT );  
2350 - const char* errorName = _errorNames[errorID];  
2351 - TIXMLASSERT( errorName && errorName[0] );  
2352 - return errorName;  
2353 -}  
2354 -  
2355 -const char* XMLDocument::ErrorStr() const  
2356 -{  
2357 - return _errorStr.Empty() ? "" : _errorStr.GetStr();  
2358 -}  
2359 -  
2360 -  
2361 -void XMLDocument::PrintError() const  
2362 -{  
2363 - printf("%s\n", ErrorStr());  
2364 -}  
2365 -  
2366 -const char* XMLDocument::ErrorName() const  
2367 -{  
2368 - return ErrorIDToName(_errorID);  
2369 -}  
2370 -  
2371 -void XMLDocument::Parse()  
2372 -{  
2373 - TIXMLASSERT( NoChildren() ); // Clear() must have been called previously  
2374 - TIXMLASSERT( _charBuffer );  
2375 - _parseCurLineNum = 1;  
2376 - _parseLineNum = 1;  
2377 - char* p = _charBuffer;  
2378 - p = XMLUtil::SkipWhiteSpace( p, &_parseCurLineNum );  
2379 - p = const_cast<char*>( XMLUtil::ReadBOM( p, &_writeBOM ) );  
2380 - if ( !*p ) {  
2381 - SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );  
2382 - return;  
2383 - }  
2384 - ParseDeep(p, 0, &_parseCurLineNum );  
2385 -}  
2386 -  
2387 -void XMLDocument::PushDepth()  
2388 -{  
2389 - _parsingDepth++;  
2390 - if (_parsingDepth == TINYXML2_MAX_ELEMENT_DEPTH) {  
2391 - SetError(XML_ELEMENT_DEPTH_EXCEEDED, _parseCurLineNum, "Element nesting is too deep." );  
2392 - }  
2393 -}  
2394 -  
2395 -void XMLDocument::PopDepth()  
2396 -{  
2397 - TIXMLASSERT(_parsingDepth > 0);  
2398 - --_parsingDepth;  
2399 -}  
2400 -  
2401 -XMLPrinter::XMLPrinter( FILE* file, bool compact, int depth ) :  
2402 - _elementJustOpened( false ),  
2403 - _stack(),  
2404 - _firstElement( true ),  
2405 - _fp( file ),  
2406 - _depth( depth ),  
2407 - _textDepth( -1 ),  
2408 - _processEntities( true ),  
2409 - _compactMode( compact ),  
2410 - _buffer()  
2411 -{  
2412 - for( int i=0; i<ENTITY_RANGE; ++i ) {  
2413 - _entityFlag[i] = false;  
2414 - _restrictedEntityFlag[i] = false;  
2415 - }  
2416 - for( int i=0; i<NUM_ENTITIES; ++i ) {  
2417 - const char entityValue = entities[i].value;  
2418 - const unsigned char flagIndex = (unsigned char)entityValue;  
2419 - TIXMLASSERT( flagIndex < ENTITY_RANGE );  
2420 - _entityFlag[flagIndex] = true;  
2421 - }  
2422 - _restrictedEntityFlag[(unsigned char)'&'] = true;  
2423 - _restrictedEntityFlag[(unsigned char)'<'] = true;  
2424 - _restrictedEntityFlag[(unsigned char)'>'] = true; // not required, but consistency is nice  
2425 - _buffer.Push( 0 );  
2426 -}  
2427 -  
2428 -  
2429 -void XMLPrinter::Print( const char* format, ... )  
2430 -{  
2431 - va_list va;  
2432 - va_start( va, format );  
2433 -  
2434 - if ( _fp ) {  
2435 - vfprintf( _fp, format, va );  
2436 - }  
2437 - else {  
2438 - const int len = TIXML_VSCPRINTF( format, va );  
2439 - // Close out and re-start the va-args  
2440 - va_end( va );  
2441 - TIXMLASSERT( len >= 0 );  
2442 - va_start( va, format );  
2443 - TIXMLASSERT( _buffer.Size() > 0 && _buffer[_buffer.Size() - 1] == 0 );  
2444 - char* p = _buffer.PushArr( len ) - 1; // back up over the null terminator.  
2445 - TIXML_VSNPRINTF( p, len+1, format, va );  
2446 - }  
2447 - va_end( va );  
2448 -}  
2449 -  
2450 -  
2451 -void XMLPrinter::Write( const char* data, size_t size )  
2452 -{  
2453 - if ( _fp ) {  
2454 - fwrite ( data , sizeof(char), size, _fp);  
2455 - }  
2456 - else {  
2457 - char* p = _buffer.PushArr( static_cast<int>(size) ) - 1; // back up over the null terminator.  
2458 - memcpy( p, data, size );  
2459 - p[size] = 0;  
2460 - }  
2461 -}  
2462 -  
2463 -  
2464 -void XMLPrinter::Putc( char ch )  
2465 -{  
2466 - if ( _fp ) {  
2467 - fputc ( ch, _fp);  
2468 - }  
2469 - else {  
2470 - char* p = _buffer.PushArr( sizeof(char) ) - 1; // back up over the null terminator.  
2471 - p[0] = ch;  
2472 - p[1] = 0;  
2473 - }  
2474 -}  
2475 -  
2476 -  
2477 -void XMLPrinter::PrintSpace( int depth )  
2478 -{  
2479 - for( int i=0; i<depth; ++i ) {  
2480 - Write( " " );  
2481 - }  
2482 -}  
2483 -  
2484 -  
2485 -void XMLPrinter::PrintString( const char* p, bool restricted )  
2486 -{  
2487 - // Look for runs of bytes between entities to print.  
2488 - const char* q = p;  
2489 -  
2490 - if ( _processEntities ) {  
2491 - const bool* flag = restricted ? _restrictedEntityFlag : _entityFlag;  
2492 - while ( *q ) {  
2493 - TIXMLASSERT( p <= q );  
2494 - // Remember, char is sometimes signed. (How many times has that bitten me?)  
2495 - if ( *q > 0 && *q < ENTITY_RANGE ) {  
2496 - // Check for entities. If one is found, flush  
2497 - // the stream up until the entity, write the  
2498 - // entity, and keep looking.  
2499 - if ( flag[(unsigned char)(*q)] ) {  
2500 - while ( p < q ) {  
2501 - const size_t delta = q - p;  
2502 - const int toPrint = ( INT_MAX < delta ) ? INT_MAX : (int)delta;  
2503 - Write( p, toPrint );  
2504 - p += toPrint;  
2505 - }  
2506 - bool entityPatternPrinted = false;  
2507 - for( int i=0; i<NUM_ENTITIES; ++i ) {  
2508 - if ( entities[i].value == *q ) {  
2509 - Putc( '&' );  
2510 - Write( entities[i].pattern, entities[i].length );  
2511 - Putc( ';' );  
2512 - entityPatternPrinted = true;  
2513 - break;  
2514 - }  
2515 - }  
2516 - if ( !entityPatternPrinted ) {  
2517 - // TIXMLASSERT( entityPatternPrinted ) causes gcc -Wunused-but-set-variable in release  
2518 - TIXMLASSERT( false );  
2519 - }  
2520 - ++p;  
2521 - }  
2522 - }  
2523 - ++q;  
2524 - TIXMLASSERT( p <= q );  
2525 - }  
2526 - }  
2527 - // Flush the remaining string. This will be the entire  
2528 - // string if an entity wasn't found.  
2529 - TIXMLASSERT( p <= q );  
2530 - if ( !_processEntities || ( p < q ) ) {  
2531 - const size_t delta = q - p;  
2532 - const int toPrint = ( INT_MAX < delta ) ? INT_MAX : (int)delta;  
2533 - Write( p, toPrint );  
2534 - }  
2535 -}  
2536 -  
2537 -  
2538 -void XMLPrinter::PushHeader( bool writeBOM, bool writeDec )  
2539 -{  
2540 - if ( writeBOM ) {  
2541 - static const unsigned char bom[] = { TIXML_UTF_LEAD_0, TIXML_UTF_LEAD_1, TIXML_UTF_LEAD_2, 0 };  
2542 - Write( reinterpret_cast< const char* >( bom ) );  
2543 - }  
2544 - if ( writeDec ) {  
2545 - PushDeclaration( "xml version=\"1.0\"" );  
2546 - }  
2547 -}  
2548 -  
2549 -  
2550 -void XMLPrinter::OpenElement( const char* name, bool compactMode )  
2551 -{  
2552 - SealElementIfJustOpened();  
2553 - _stack.Push( name );  
2554 -  
2555 - if ( _textDepth < 0 && !_firstElement && !compactMode ) {  
2556 - Putc( '\n' );  
2557 - }  
2558 - if ( !compactMode ) {  
2559 - PrintSpace( _depth );  
2560 - }  
2561 -  
2562 - Write ( "<" );  
2563 - Write ( name );  
2564 -  
2565 - _elementJustOpened = true;  
2566 - _firstElement = false;  
2567 - ++_depth;  
2568 -}  
2569 -  
2570 -  
2571 -void XMLPrinter::PushAttribute( const char* name, const char* value )  
2572 -{  
2573 - TIXMLASSERT( _elementJustOpened );  
2574 - Putc ( ' ' );  
2575 - Write( name );  
2576 - Write( "=\"" );  
2577 - PrintString( value, false );  
2578 - Putc ( '\"' );  
2579 -}  
2580 -  
2581 -  
2582 -void XMLPrinter::PushAttribute( const char* name, int v )  
2583 -{  
2584 - char buf[BUF_SIZE];  
2585 - XMLUtil::ToStr( v, buf, BUF_SIZE );  
2586 - PushAttribute( name, buf );  
2587 -}  
2588 -  
2589 -  
2590 -void XMLPrinter::PushAttribute( const char* name, unsigned v )  
2591 -{  
2592 - char buf[BUF_SIZE];  
2593 - XMLUtil::ToStr( v, buf, BUF_SIZE );  
2594 - PushAttribute( name, buf );  
2595 -}  
2596 -  
2597 -  
2598 -void XMLPrinter::PushAttribute(const char* name, int64_t v)  
2599 -{  
2600 - char buf[BUF_SIZE];  
2601 - XMLUtil::ToStr(v, buf, BUF_SIZE);  
2602 - PushAttribute(name, buf);  
2603 -}  
2604 -  
2605 -  
2606 -void XMLPrinter::PushAttribute( const char* name, bool v )  
2607 -{  
2608 - char buf[BUF_SIZE];  
2609 - XMLUtil::ToStr( v, buf, BUF_SIZE );  
2610 - PushAttribute( name, buf );  
2611 -}  
2612 -  
2613 -  
2614 -void XMLPrinter::PushAttribute( const char* name, double v )  
2615 -{  
2616 - char buf[BUF_SIZE];  
2617 - XMLUtil::ToStr( v, buf, BUF_SIZE );  
2618 - PushAttribute( name, buf );  
2619 -}  
2620 -  
2621 -  
2622 -void XMLPrinter::CloseElement( bool compactMode )  
2623 -{  
2624 - --_depth;  
2625 - const char* name = _stack.Pop();  
2626 -  
2627 - if ( _elementJustOpened ) {  
2628 - Write( "/>" );  
2629 - }  
2630 - else {  
2631 - if ( _textDepth < 0 && !compactMode) {  
2632 - Putc( '\n' );  
2633 - PrintSpace( _depth );  
2634 - }  
2635 - Write ( "</" );  
2636 - Write ( name );  
2637 - Write ( ">" );  
2638 - }  
2639 -  
2640 - if ( _textDepth == _depth ) {  
2641 - _textDepth = -1;  
2642 - }  
2643 - if ( _depth == 0 && !compactMode) {  
2644 - Putc( '\n' );  
2645 - }  
2646 - _elementJustOpened = false;  
2647 -}  
2648 -  
2649 -  
2650 -void XMLPrinter::SealElementIfJustOpened()  
2651 -{  
2652 - if ( !_elementJustOpened ) {  
2653 - return;  
2654 - }  
2655 - _elementJustOpened = false;  
2656 - Putc( '>' );  
2657 -}  
2658 -  
2659 -  
2660 -void XMLPrinter::PushText( const char* text, bool cdata )  
2661 -{  
2662 - _textDepth = _depth-1;  
2663 -  
2664 - SealElementIfJustOpened();  
2665 - if ( cdata ) {  
2666 - Write( "<![CDATA[" );  
2667 - Write( text );  
2668 - Write( "]]>" );  
2669 - }  
2670 - else {  
2671 - PrintString( text, true );  
2672 - }  
2673 -}  
2674 -  
2675 -void XMLPrinter::PushText( int64_t value )  
2676 -{  
2677 - char buf[BUF_SIZE];  
2678 - XMLUtil::ToStr( value, buf, BUF_SIZE );  
2679 - PushText( buf, false );  
2680 -}  
2681 -  
2682 -void XMLPrinter::PushText( int value )  
2683 -{  
2684 - char buf[BUF_SIZE];  
2685 - XMLUtil::ToStr( value, buf, BUF_SIZE );  
2686 - PushText( buf, false );  
2687 -}  
2688 -  
2689 -  
2690 -void XMLPrinter::PushText( unsigned value )  
2691 -{  
2692 - char buf[BUF_SIZE];  
2693 - XMLUtil::ToStr( value, buf, BUF_SIZE );  
2694 - PushText( buf, false );  
2695 -}  
2696 -  
2697 -  
2698 -void XMLPrinter::PushText( bool value )  
2699 -{  
2700 - char buf[BUF_SIZE];  
2701 - XMLUtil::ToStr( value, buf, BUF_SIZE );  
2702 - PushText( buf, false );  
2703 -}  
2704 -  
2705 -  
2706 -void XMLPrinter::PushText( float value )  
2707 -{  
2708 - char buf[BUF_SIZE];  
2709 - XMLUtil::ToStr( value, buf, BUF_SIZE );  
2710 - PushText( buf, false );  
2711 -}  
2712 -  
2713 -  
2714 -void XMLPrinter::PushText( double value )  
2715 -{  
2716 - char buf[BUF_SIZE];  
2717 - XMLUtil::ToStr( value, buf, BUF_SIZE );  
2718 - PushText( buf, false );  
2719 -}  
2720 -  
2721 -  
2722 -void XMLPrinter::PushComment( const char* comment )  
2723 -{  
2724 - SealElementIfJustOpened();  
2725 - if ( _textDepth < 0 && !_firstElement && !_compactMode) {  
2726 - Putc( '\n' );  
2727 - PrintSpace( _depth );  
2728 - }  
2729 - _firstElement = false;  
2730 -  
2731 - Write( "<!--" );  
2732 - Write( comment );  
2733 - Write( "-->" );  
2734 -}  
2735 -  
2736 -  
2737 -void XMLPrinter::PushDeclaration( const char* value )  
2738 -{  
2739 - SealElementIfJustOpened();  
2740 - if ( _textDepth < 0 && !_firstElement && !_compactMode) {  
2741 - Putc( '\n' );  
2742 - PrintSpace( _depth );  
2743 - }  
2744 - _firstElement = false;  
2745 -  
2746 - Write( "<?" );  
2747 - Write( value );  
2748 - Write( "?>" );  
2749 -}  
2750 -  
2751 -  
2752 -void XMLPrinter::PushUnknown( const char* value )  
2753 -{  
2754 - SealElementIfJustOpened();  
2755 - if ( _textDepth < 0 && !_firstElement && !_compactMode) {  
2756 - Putc( '\n' );  
2757 - PrintSpace( _depth );  
2758 - }  
2759 - _firstElement = false;  
2760 -  
2761 - Write( "<!" );  
2762 - Write( value );  
2763 - Putc( '>' );  
2764 -}  
2765 -  
2766 -  
2767 -bool XMLPrinter::VisitEnter( const XMLDocument& doc )  
2768 -{  
2769 - _processEntities = doc.ProcessEntities();  
2770 - if ( doc.HasBOM() ) {  
2771 - PushHeader( true, false );  
2772 - }  
2773 - return true;  
2774 -}  
2775 -  
2776 -  
2777 -bool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute )  
2778 -{  
2779 - const XMLElement* parentElem = 0;  
2780 - if ( element.Parent() ) {  
2781 - parentElem = element.Parent()->ToElement();  
2782 - }  
2783 - const bool compactMode = parentElem ? CompactMode( *parentElem ) : _compactMode;  
2784 - OpenElement( element.Name(), compactMode );  
2785 - while ( attribute ) {  
2786 - PushAttribute( attribute->Name(), attribute->Value() );  
2787 - attribute = attribute->Next();  
2788 - }  
2789 - return true;  
2790 -}  
2791 -  
2792 -  
2793 -bool XMLPrinter::VisitExit( const XMLElement& element )  
2794 -{  
2795 - CloseElement( CompactMode(element) );  
2796 - return true;  
2797 -}  
2798 -  
2799 -  
2800 -bool XMLPrinter::Visit( const XMLText& text )  
2801 -{  
2802 - PushText( text.Value(), text.CData() );  
2803 - return true;  
2804 -}  
2805 -  
2806 -  
2807 -bool XMLPrinter::Visit( const XMLComment& comment )  
2808 -{  
2809 - PushComment( comment.Value() );  
2810 - return true;  
2811 -}  
2812 -  
2813 -bool XMLPrinter::Visit( const XMLDeclaration& declaration )  
2814 -{  
2815 - PushDeclaration( declaration.Value() );  
2816 - return true;  
2817 -}  
2818 -  
2819 -  
2820 -bool XMLPrinter::Visit( const XMLUnknown& unknown )  
2821 -{  
2822 - PushUnknown( unknown.Value() );  
2823 - return true;  
2824 -}  
2825 -  
2826 -} // namespace tinyxml2  
src/decoder/gb28181/sip/tinyxml2/tinyxml2.h deleted
1 -/*  
2 -Original code by Lee Thomason (www.grinninglizard.com)  
3 -  
4 -This software is provided 'as-is', without any express or implied  
5 -warranty. In no event will the authors be held liable for any  
6 -damages arising from the use of this software.  
7 -  
8 -Permission is granted to anyone to use this software for any  
9 -purpose, including commercial applications, and to alter it and  
10 -redistribute it freely, subject to the following restrictions:  
11 -  
12 -1. The origin of this software must not be misrepresented; you must  
13 -not claim that you wrote the original software. If you use this  
14 -software in a product, an acknowledgment in the product documentation  
15 -would be appreciated but is not required.  
16 -  
17 -2. Altered source versions must be plainly marked as such, and  
18 -must not be misrepresented as being the original software.  
19 -  
20 -3. This notice may not be removed or altered from any source  
21 -distribution.  
22 -*/  
23 -  
24 -#ifndef TINYXML2_INCLUDED  
25 -#define TINYXML2_INCLUDED  
26 -  
27 -#if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__)  
28 -# include <ctype.h>  
29 -# include <limits.h>  
30 -# include <stdio.h>  
31 -# include <stdlib.h>  
32 -# include <string.h>  
33 -# if defined(__PS3__)  
34 -# include <stddef.h>  
35 -# endif  
36 -#else  
37 -# include <cctype>  
38 -# include <climits>  
39 -# include <cstdio>  
40 -# include <cstdlib>  
41 -# include <cstring>  
42 -#endif  
43 -#include <stdint.h>  
44 -  
45 -/*  
46 - TODO: intern strings instead of allocation.  
47 -*/  
48 -/*  
49 - gcc:  
50 - g++ -Wall -DTINYXML2_DEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe  
51 -  
52 - Formatting, Artistic Style:  
53 - AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h  
54 -*/  
55 -  
56 -#if defined( _DEBUG ) || defined (__DEBUG__)  
57 -# ifndef TINYXML2_DEBUG  
58 -# define TINYXML2_DEBUG  
59 -# endif  
60 -#endif  
61 -  
62 -#ifdef _MSC_VER  
63 -# pragma warning(push)  
64 -# pragma warning(disable: 4251)  
65 -#endif  
66 -  
67 -#ifdef _WIN32  
68 -# ifdef TINYXML2_EXPORT  
69 -# define TINYXML2_LIB __declspec(dllexport)  
70 -# elif defined(TINYXML2_IMPORT)  
71 -# define TINYXML2_LIB __declspec(dllimport)  
72 -# else  
73 -# define TINYXML2_LIB  
74 -# endif  
75 -#elif __GNUC__ >= 4  
76 -# define TINYXML2_LIB __attribute__((visibility("default")))  
77 -#else  
78 -# define TINYXML2_LIB  
79 -#endif  
80 -  
81 -  
82 -#if defined(TINYXML2_DEBUG)  
83 -# if defined(_MSC_VER)  
84 -# // "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like  
85 -# define TIXMLASSERT( x ) if ( !((void)0,(x))) { __debugbreak(); }  
86 -# elif defined (ANDROID_NDK)  
87 -# include <android/log.h>  
88 -# define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }  
89 -# else  
90 -# include <assert.h>  
91 -# define TIXMLASSERT assert  
92 -# endif  
93 -#else  
94 -# define TIXMLASSERT( x ) {}  
95 -#endif  
96 -  
97 -  
98 -/* Versioning, past 1.0.14:  
99 - http://semver.org/  
100 -*/  
101 -static const int TIXML2_MAJOR_VERSION = 6;  
102 -static const int TIXML2_MINOR_VERSION = 2;  
103 -static const int TIXML2_PATCH_VERSION = 0;  
104 -  
105 -#define TINYXML2_MAJOR_VERSION 6  
106 -#define TINYXML2_MINOR_VERSION 2  
107 -#define TINYXML2_PATCH_VERSION 0  
108 -  
109 -// A fixed element depth limit is problematic. There needs to be a  
110 -// limit to avoid a stack overflow. However, that limit varies per  
111 -// system, and the capacity of the stack. On the other hand, it's a trivial  
112 -// attack that can result from ill, malicious, or even correctly formed XML,  
113 -// so there needs to be a limit in place.  
114 -static const int TINYXML2_MAX_ELEMENT_DEPTH = 100;  
115 -  
116 -namespace tinyxml2  
117 -{  
118 -class XMLDocument;  
119 -class XMLElement;  
120 -class XMLAttribute;  
121 -class XMLComment;  
122 -class XMLText;  
123 -class XMLDeclaration;  
124 -class XMLUnknown;  
125 -class XMLPrinter;  
126 -  
127 -/*  
128 - A class that wraps strings. Normally stores the start and end  
129 - pointers into the XML file itself, and will apply normalization  
130 - and entity translation if actually read. Can also store (and memory  
131 - manage) a traditional char[]  
132 -*/  
133 -class StrPair  
134 -{  
135 -public:  
136 - enum {  
137 - NEEDS_ENTITY_PROCESSING = 0x01,  
138 - NEEDS_NEWLINE_NORMALIZATION = 0x02,  
139 - NEEDS_WHITESPACE_COLLAPSING = 0x04,  
140 -  
141 - TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,  
142 - TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,  
143 - ATTRIBUTE_NAME = 0,  
144 - ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,  
145 - ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,  
146 - COMMENT = NEEDS_NEWLINE_NORMALIZATION  
147 - };  
148 -  
149 - StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}  
150 - ~StrPair();  
151 -  
152 - void Set( char* start, char* end, int flags ) {  
153 - TIXMLASSERT( start );  
154 - TIXMLASSERT( end );  
155 - Reset();  
156 - _start = start;  
157 - _end = end;  
158 - _flags = flags | NEEDS_FLUSH;  
159 - }  
160 -  
161 - const char* GetStr();  
162 -  
163 - bool Empty() const {  
164 - return _start == _end;  
165 - }  
166 -  
167 - void SetInternedStr( const char* str ) {  
168 - Reset();  
169 - _start = const_cast<char*>(str);  
170 - }  
171 -  
172 - void SetStr( const char* str, int flags=0 );  
173 -  
174 - char* ParseText( char* in, const char* endTag, int strFlags, int* curLineNumPtr );  
175 - char* ParseName( char* in );  
176 -  
177 - void TransferTo( StrPair* other );  
178 - void Reset();  
179 -  
180 -private:  
181 - void CollapseWhitespace();  
182 -  
183 - enum {  
184 - NEEDS_FLUSH = 0x100,  
185 - NEEDS_DELETE = 0x200  
186 - };  
187 -  
188 - int _flags;  
189 - char* _start;  
190 - char* _end;  
191 -  
192 - StrPair( const StrPair& other ); // not supported  
193 - void operator=( StrPair& other ); // not supported, use TransferTo()  
194 -};  
195 -  
196 -  
197 -/*  
198 - A dynamic array of Plain Old Data. Doesn't support constructors, etc.  
199 - Has a small initial memory pool, so that low or no usage will not  
200 - cause a call to new/delete  
201 -*/  
202 -template <class T, int INITIAL_SIZE>  
203 -class DynArray  
204 -{  
205 -public:  
206 - DynArray() :  
207 - _mem( _pool ),  
208 - _allocated( INITIAL_SIZE ),  
209 - _size( 0 )  
210 - {  
211 - }  
212 -  
213 - ~DynArray() {  
214 - if ( _mem != _pool ) {  
215 - delete [] _mem;  
216 - }  
217 - }  
218 -  
219 - void Clear() {  
220 - _size = 0;  
221 - }  
222 -  
223 - void Push( T t ) {  
224 - TIXMLASSERT( _size < INT_MAX );  
225 - EnsureCapacity( _size+1 );  
226 - _mem[_size] = t;  
227 - ++_size;  
228 - }  
229 -  
230 - T* PushArr( int count ) {  
231 - TIXMLASSERT( count >= 0 );  
232 - TIXMLASSERT( _size <= INT_MAX - count );  
233 - EnsureCapacity( _size+count );  
234 - T* ret = &_mem[_size];  
235 - _size += count;  
236 - return ret;  
237 - }  
238 -  
239 - T Pop() {  
240 - TIXMLASSERT( _size > 0 );  
241 - --_size;  
242 - return _mem[_size];  
243 - }  
244 -  
245 - void PopArr( int count ) {  
246 - TIXMLASSERT( _size >= count );  
247 - _size -= count;  
248 - }  
249 -  
250 - bool Empty() const {  
251 - return _size == 0;  
252 - }  
253 -  
254 - T& operator[](int i) {  
255 - TIXMLASSERT( i>= 0 && i < _size );  
256 - return _mem[i];  
257 - }  
258 -  
259 - const T& operator[](int i) const {  
260 - TIXMLASSERT( i>= 0 && i < _size );  
261 - return _mem[i];  
262 - }  
263 -  
264 - const T& PeekTop() const {  
265 - TIXMLASSERT( _size > 0 );  
266 - return _mem[ _size - 1];  
267 - }  
268 -  
269 - int Size() const {  
270 - TIXMLASSERT( _size >= 0 );  
271 - return _size;  
272 - }  
273 -  
274 - int Capacity() const {  
275 - TIXMLASSERT( _allocated >= INITIAL_SIZE );  
276 - return _allocated;  
277 - }  
278 -  
279 - void SwapRemove(int i) {  
280 - TIXMLASSERT(i >= 0 && i < _size);  
281 - TIXMLASSERT(_size > 0);  
282 - _mem[i] = _mem[_size - 1];  
283 - --_size;  
284 - }  
285 -  
286 - const T* Mem() const {  
287 - TIXMLASSERT( _mem );  
288 - return _mem;  
289 - }  
290 -  
291 - T* Mem() {  
292 - TIXMLASSERT( _mem );  
293 - return _mem;  
294 - }  
295 -  
296 -private:  
297 - DynArray( const DynArray& ); // not supported  
298 - void operator=( const DynArray& ); // not supported  
299 -  
300 - void EnsureCapacity( int cap ) {  
301 - TIXMLASSERT( cap > 0 );  
302 - if ( cap > _allocated ) {  
303 - TIXMLASSERT( cap <= INT_MAX / 2 );  
304 - int newAllocated = cap * 2;  
305 - T* newMem = new T[newAllocated];  
306 - TIXMLASSERT( newAllocated >= _size );  
307 - memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs  
308 - if ( _mem != _pool ) {  
309 - delete [] _mem;  
310 - }  
311 - _mem = newMem;  
312 - _allocated = newAllocated;  
313 - }  
314 - }  
315 -  
316 - T* _mem;  
317 - T _pool[INITIAL_SIZE];  
318 - int _allocated; // objects allocated  
319 - int _size; // number objects in use  
320 -};  
321 -  
322 -  
323 -/*  
324 - Parent virtual class of a pool for fast allocation  
325 - and deallocation of objects.  
326 -*/  
327 -class MemPool  
328 -{  
329 -public:  
330 - MemPool() {}  
331 - virtual ~MemPool() {}  
332 -  
333 - virtual int ItemSize() const = 0;  
334 - virtual void* Alloc() = 0;  
335 - virtual void Free( void* ) = 0;  
336 - virtual void SetTracked() = 0;  
337 - virtual void Clear() = 0;  
338 -};  
339 -  
340 -  
341 -/*  
342 - Template child class to create pools of the correct type.  
343 -*/  
344 -template< int ITEM_SIZE >  
345 -class MemPoolT : public MemPool  
346 -{  
347 -public:  
348 - MemPoolT() : _blockPtrs(), _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}  
349 - ~MemPoolT() {  
350 - Clear();  
351 - }  
352 -  
353 - void Clear() {  
354 - // Delete the blocks.  
355 - while( !_blockPtrs.Empty()) {  
356 - Block* lastBlock = _blockPtrs.Pop();  
357 - delete lastBlock;  
358 - }  
359 - _root = 0;  
360 - _currentAllocs = 0;  
361 - _nAllocs = 0;  
362 - _maxAllocs = 0;  
363 - _nUntracked = 0;  
364 - }  
365 -  
366 - virtual int ItemSize() const {  
367 - return ITEM_SIZE;  
368 - }  
369 - int CurrentAllocs() const {  
370 - return _currentAllocs;  
371 - }  
372 -  
373 - virtual void* Alloc() {  
374 - if ( !_root ) {  
375 - // Need a new block.  
376 - Block* block = new Block();  
377 - _blockPtrs.Push( block );  
378 -  
379 - Item* blockItems = block->items;  
380 - for( int i = 0; i < ITEMS_PER_BLOCK - 1; ++i ) {  
381 - blockItems[i].next = &(blockItems[i + 1]);  
382 - }  
383 - blockItems[ITEMS_PER_BLOCK - 1].next = 0;  
384 - _root = blockItems;  
385 - }  
386 - Item* const result = _root;  
387 - TIXMLASSERT( result != 0 );  
388 - _root = _root->next;  
389 -  
390 - ++_currentAllocs;  
391 - if ( _currentAllocs > _maxAllocs ) {  
392 - _maxAllocs = _currentAllocs;  
393 - }  
394 - ++_nAllocs;  
395 - ++_nUntracked;  
396 - return result;  
397 - }  
398 -  
399 - virtual void Free( void* mem ) {  
400 - if ( !mem ) {  
401 - return;  
402 - }  
403 - --_currentAllocs;  
404 - Item* item = static_cast<Item*>( mem );  
405 -#ifdef TINYXML2_DEBUG  
406 - memset( item, 0xfe, sizeof( *item ) );  
407 -#endif  
408 - item->next = _root;  
409 - _root = item;  
410 - }  
411 - void Trace( const char* name ) {  
412 - printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",  
413 - name, _maxAllocs, _maxAllocs * ITEM_SIZE / 1024, _currentAllocs,  
414 - ITEM_SIZE, _nAllocs, _blockPtrs.Size() );  
415 - }  
416 -  
417 - void SetTracked() {  
418 - --_nUntracked;  
419 - }  
420 -  
421 - int Untracked() const {  
422 - return _nUntracked;  
423 - }  
424 -  
425 - // This number is perf sensitive. 4k seems like a good tradeoff on my machine.  
426 - // The test file is large, 170k.  
427 - // Release: VS2010 gcc(no opt)  
428 - // 1k: 4000  
429 - // 2k: 4000  
430 - // 4k: 3900 21000  
431 - // 16k: 5200  
432 - // 32k: 4300  
433 - // 64k: 4000 21000  
434 - // Declared public because some compilers do not accept to use ITEMS_PER_BLOCK  
435 - // in private part if ITEMS_PER_BLOCK is private  
436 - enum { ITEMS_PER_BLOCK = (4 * 1024) / ITEM_SIZE };  
437 -  
438 -private:  
439 - MemPoolT( const MemPoolT& ); // not supported  
440 - void operator=( const MemPoolT& ); // not supported  
441 -  
442 - union Item {  
443 - Item* next;  
444 - char itemData[ITEM_SIZE];  
445 - };  
446 - struct Block {  
447 - Item items[ITEMS_PER_BLOCK];  
448 - };  
449 - DynArray< Block*, 10 > _blockPtrs;  
450 - Item* _root;  
451 -  
452 - int _currentAllocs;  
453 - int _nAllocs;  
454 - int _maxAllocs;  
455 - int _nUntracked;  
456 -};  
457 -  
458 -  
459 -  
460 -/**  
461 - Implements the interface to the "Visitor pattern" (see the Accept() method.)  
462 - If you call the Accept() method, it requires being passed a XMLVisitor  
463 - class to handle callbacks. For nodes that contain other nodes (Document, Element)  
464 - you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs  
465 - are simply called with Visit().  
466 -  
467 - If you return 'true' from a Visit method, recursive parsing will continue. If you return  
468 - false, <b>no children of this node or its siblings</b> will be visited.  
469 -  
470 - All flavors of Visit methods have a default implementation that returns 'true' (continue  
471 - visiting). You need to only override methods that are interesting to you.  
472 -  
473 - Generally Accept() is called on the XMLDocument, although all nodes support visiting.  
474 -  
475 - You should never change the document from a callback.  
476 -  
477 - @sa XMLNode::Accept()  
478 -*/  
479 -class TINYXML2_LIB XMLVisitor  
480 -{  
481 -public:  
482 - virtual ~XMLVisitor() {}  
483 -  
484 - /// Visit a document.  
485 - virtual bool VisitEnter( const XMLDocument& /*doc*/ ) {  
486 - return true;  
487 - }  
488 - /// Visit a document.  
489 - virtual bool VisitExit( const XMLDocument& /*doc*/ ) {  
490 - return true;  
491 - }  
492 -  
493 - /// Visit an element.  
494 - virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) {  
495 - return true;  
496 - }  
497 - /// Visit an element.  
498 - virtual bool VisitExit( const XMLElement& /*element*/ ) {  
499 - return true;  
500 - }  
501 -  
502 - /// Visit a declaration.  
503 - virtual bool Visit( const XMLDeclaration& /*declaration*/ ) {  
504 - return true;  
505 - }  
506 - /// Visit a text node.  
507 - virtual bool Visit( const XMLText& /*text*/ ) {  
508 - return true;  
509 - }  
510 - /// Visit a comment node.  
511 - virtual bool Visit( const XMLComment& /*comment*/ ) {  
512 - return true;  
513 - }  
514 - /// Visit an unknown node.  
515 - virtual bool Visit( const XMLUnknown& /*unknown*/ ) {  
516 - return true;  
517 - }  
518 -};  
519 -  
520 -// WARNING: must match XMLDocument::_errorNames[]  
521 -enum XMLError {  
522 - XML_SUCCESS = 0,  
523 - XML_NO_ATTRIBUTE,  
524 - XML_WRONG_ATTRIBUTE_TYPE,  
525 - XML_ERROR_FILE_NOT_FOUND,  
526 - XML_ERROR_FILE_COULD_NOT_BE_OPENED,  
527 - XML_ERROR_FILE_READ_ERROR,  
528 - UNUSED_XML_ERROR_ELEMENT_MISMATCH, // remove at next major version  
529 - XML_ERROR_PARSING_ELEMENT,  
530 - XML_ERROR_PARSING_ATTRIBUTE,  
531 - UNUSED_XML_ERROR_IDENTIFYING_TAG, // remove at next major version  
532 - XML_ERROR_PARSING_TEXT,  
533 - XML_ERROR_PARSING_CDATA,  
534 - XML_ERROR_PARSING_COMMENT,  
535 - XML_ERROR_PARSING_DECLARATION,  
536 - XML_ERROR_PARSING_UNKNOWN,  
537 - XML_ERROR_EMPTY_DOCUMENT,  
538 - XML_ERROR_MISMATCHED_ELEMENT,  
539 - XML_ERROR_PARSING,  
540 - XML_CAN_NOT_CONVERT_TEXT,  
541 - XML_NO_TEXT_NODE,  
542 - XML_ELEMENT_DEPTH_EXCEEDED,  
543 -  
544 - XML_ERROR_COUNT  
545 -};  
546 -  
547 -  
548 -/*  
549 - Utility functionality.  
550 -*/  
551 -class TINYXML2_LIB XMLUtil  
552 -{  
553 -public:  
554 - static const char* SkipWhiteSpace( const char* p, int* curLineNumPtr ) {  
555 - TIXMLASSERT( p );  
556 -  
557 - while( IsWhiteSpace(*p) ) {  
558 - if (curLineNumPtr && *p == '\n') {  
559 - ++(*curLineNumPtr);  
560 - }  
561 - ++p;  
562 - }  
563 - TIXMLASSERT( p );  
564 - return p;  
565 - }  
566 - static char* SkipWhiteSpace( char* p, int* curLineNumPtr ) {  
567 - return const_cast<char*>( SkipWhiteSpace( const_cast<const char*>(p), curLineNumPtr ) );  
568 - }  
569 -  
570 - // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't  
571 - // correct, but simple, and usually works.  
572 - static bool IsWhiteSpace( char p ) {  
573 - return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );  
574 - }  
575 -  
576 - inline static bool IsNameStartChar( unsigned char ch ) {  
577 - if ( ch >= 128 ) {  
578 - // This is a heuristic guess in attempt to not implement Unicode-aware isalpha()  
579 - return true;  
580 - }  
581 - if ( isalpha( ch ) ) {  
582 - return true;  
583 - }  
584 - return ch == ':' || ch == '_';  
585 - }  
586 -  
587 - inline static bool IsNameChar( unsigned char ch ) {  
588 - return IsNameStartChar( ch )  
589 - || isdigit( ch )  
590 - || ch == '.'  
591 - || ch == '-';  
592 - }  
593 -  
594 - inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {  
595 - if ( p == q ) {  
596 - return true;  
597 - }  
598 - TIXMLASSERT( p );  
599 - TIXMLASSERT( q );  
600 - TIXMLASSERT( nChar >= 0 );  
601 - return strncmp( p, q, nChar ) == 0;  
602 - }  
603 -  
604 - inline static bool IsUTF8Continuation( char p ) {  
605 - return ( p & 0x80 ) != 0;  
606 - }  
607 -  
608 - static const char* ReadBOM( const char* p, bool* hasBOM );  
609 - // p is the starting location,  
610 - // the UTF-8 value of the entity will be placed in value, and length filled in.  
611 - static const char* GetCharacterRef( const char* p, char* value, int* length );  
612 - static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );  
613 -  
614 - // converts primitive types to strings  
615 - static void ToStr( int v, char* buffer, int bufferSize );  
616 - static void ToStr( unsigned v, char* buffer, int bufferSize );  
617 - static void ToStr( bool v, char* buffer, int bufferSize );  
618 - static void ToStr( float v, char* buffer, int bufferSize );  
619 - static void ToStr( double v, char* buffer, int bufferSize );  
620 - static void ToStr(int64_t v, char* buffer, int bufferSize);  
621 -  
622 - // converts strings to primitive types  
623 - static bool ToInt( const char* str, int* value );  
624 - static bool ToUnsigned( const char* str, unsigned* value );  
625 - static bool ToBool( const char* str, bool* value );  
626 - static bool ToFloat( const char* str, float* value );  
627 - static bool ToDouble( const char* str, double* value );  
628 - static bool ToInt64(const char* str, int64_t* value);  
629 -  
630 - // Changes what is serialized for a boolean value.  
631 - // Default to "true" and "false". Shouldn't be changed  
632 - // unless you have a special testing or compatibility need.  
633 - // Be careful: static, global, & not thread safe.  
634 - // Be sure to set static const memory as parameters.  
635 - static void SetBoolSerialization(const char* writeTrue, const char* writeFalse);  
636 -  
637 -private:  
638 - static const char* writeBoolTrue;  
639 - static const char* writeBoolFalse;  
640 -};  
641 -  
642 -  
643 -/** XMLNode is a base class for every object that is in the  
644 - XML Document Object Model (DOM), except XMLAttributes.  
645 - Nodes have siblings, a parent, and children which can  
646 - be navigated. A node is always in a XMLDocument.  
647 - The type of a XMLNode can be queried, and it can  
648 - be cast to its more defined type.  
649 -  
650 - A XMLDocument allocates memory for all its Nodes.  
651 - When the XMLDocument gets deleted, all its Nodes  
652 - will also be deleted.  
653 -  
654 - @verbatim  
655 - A Document can contain: Element (container or leaf)  
656 - Comment (leaf)  
657 - Unknown (leaf)  
658 - Declaration( leaf )  
659 -  
660 - An Element can contain: Element (container or leaf)  
661 - Text (leaf)  
662 - Attributes (not on tree)  
663 - Comment (leaf)  
664 - Unknown (leaf)  
665 -  
666 - @endverbatim  
667 -*/  
668 -class TINYXML2_LIB XMLNode  
669 -{  
670 - friend class XMLDocument;  
671 - friend class XMLElement;  
672 -public:  
673 -  
674 - /// Get the XMLDocument that owns this XMLNode.  
675 - const XMLDocument* GetDocument() const {  
676 - TIXMLASSERT( _document );  
677 - return _document;  
678 - }  
679 - /// Get the XMLDocument that owns this XMLNode.  
680 - XMLDocument* GetDocument() {  
681 - TIXMLASSERT( _document );  
682 - return _document;  
683 - }  
684 -  
685 - /// Safely cast to an Element, or null.  
686 - virtual XMLElement* ToElement() {  
687 - return 0;  
688 - }  
689 - /// Safely cast to Text, or null.  
690 - virtual XMLText* ToText() {  
691 - return 0;  
692 - }  
693 - /// Safely cast to a Comment, or null.  
694 - virtual XMLComment* ToComment() {  
695 - return 0;  
696 - }  
697 - /// Safely cast to a Document, or null.  
698 - virtual XMLDocument* ToDocument() {  
699 - return 0;  
700 - }  
701 - /// Safely cast to a Declaration, or null.  
702 - virtual XMLDeclaration* ToDeclaration() {  
703 - return 0;  
704 - }  
705 - /// Safely cast to an Unknown, or null.  
706 - virtual XMLUnknown* ToUnknown() {  
707 - return 0;  
708 - }  
709 -  
710 - virtual const XMLElement* ToElement() const {  
711 - return 0;  
712 - }  
713 - virtual const XMLText* ToText() const {  
714 - return 0;  
715 - }  
716 - virtual const XMLComment* ToComment() const {  
717 - return 0;  
718 - }  
719 - virtual const XMLDocument* ToDocument() const {  
720 - return 0;  
721 - }  
722 - virtual const XMLDeclaration* ToDeclaration() const {  
723 - return 0;  
724 - }  
725 - virtual const XMLUnknown* ToUnknown() const {  
726 - return 0;  
727 - }  
728 -  
729 - /** The meaning of 'value' changes for the specific type.  
730 - @verbatim  
731 - Document: empty (NULL is returned, not an empty string)  
732 - Element: name of the element  
733 - Comment: the comment text  
734 - Unknown: the tag contents  
735 - Text: the text string  
736 - @endverbatim  
737 - */  
738 - const char* Value() const;  
739 -  
740 - /** Set the Value of an XML node.  
741 - @sa Value()  
742 - */  
743 - void SetValue( const char* val, bool staticMem=false );  
744 -  
745 - /// Gets the line number the node is in, if the document was parsed from a file.  
746 - int GetLineNum() const { return _parseLineNum; }  
747 -  
748 - /// Get the parent of this node on the DOM.  
749 - const XMLNode* Parent() const {  
750 - return _parent;  
751 - }  
752 -  
753 - XMLNode* Parent() {  
754 - return _parent;  
755 - }  
756 -  
757 - /// Returns true if this node has no children.  
758 - bool NoChildren() const {  
759 - return !_firstChild;  
760 - }  
761 -  
762 - /// Get the first child node, or null if none exists.  
763 - const XMLNode* FirstChild() const {  
764 - return _firstChild;  
765 - }  
766 -  
767 - XMLNode* FirstChild() {  
768 - return _firstChild;  
769 - }  
770 -  
771 - /** Get the first child element, or optionally the first child  
772 - element with the specified name.  
773 - */  
774 - const XMLElement* FirstChildElement( const char* name = 0 ) const;  
775 -  
776 - XMLElement* FirstChildElement( const char* name = 0 ) {  
777 - return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( name ));  
778 - }  
779 -  
780 - /// Get the last child node, or null if none exists.  
781 - const XMLNode* LastChild() const {  
782 - return _lastChild;  
783 - }  
784 -  
785 - XMLNode* LastChild() {  
786 - return _lastChild;  
787 - }  
788 -  
789 - /** Get the last child element or optionally the last child  
790 - element with the specified name.  
791 - */  
792 - const XMLElement* LastChildElement( const char* name = 0 ) const;  
793 -  
794 - XMLElement* LastChildElement( const char* name = 0 ) {  
795 - return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(name) );  
796 - }  
797 -  
798 - /// Get the previous (left) sibling node of this node.  
799 - const XMLNode* PreviousSibling() const {  
800 - return _prev;  
801 - }  
802 -  
803 - XMLNode* PreviousSibling() {  
804 - return _prev;  
805 - }  
806 -  
807 - /// Get the previous (left) sibling element of this node, with an optionally supplied name.  
808 - const XMLElement* PreviousSiblingElement( const char* name = 0 ) const ;  
809 -  
810 - XMLElement* PreviousSiblingElement( const char* name = 0 ) {  
811 - return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( name ) );  
812 - }  
813 -  
814 - /// Get the next (right) sibling node of this node.  
815 - const XMLNode* NextSibling() const {  
816 - return _next;  
817 - }  
818 -  
819 - XMLNode* NextSibling() {  
820 - return _next;  
821 - }  
822 -  
823 - /// Get the next (right) sibling element of this node, with an optionally supplied name.  
824 - const XMLElement* NextSiblingElement( const char* name = 0 ) const;  
825 -  
826 - XMLElement* NextSiblingElement( const char* name = 0 ) {  
827 - return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( name ) );  
828 - }  
829 -  
830 - /**  
831 - Add a child node as the last (right) child.  
832 - If the child node is already part of the document,  
833 - it is moved from its old location to the new location.  
834 - Returns the addThis argument or 0 if the node does not  
835 - belong to the same document.  
836 - */  
837 - XMLNode* InsertEndChild( XMLNode* addThis );  
838 -  
839 - XMLNode* LinkEndChild( XMLNode* addThis ) {  
840 - return InsertEndChild( addThis );  
841 - }  
842 - /**  
843 - Add a child node as the first (left) child.  
844 - If the child node is already part of the document,  
845 - it is moved from its old location to the new location.  
846 - Returns the addThis argument or 0 if the node does not  
847 - belong to the same document.  
848 - */  
849 - XMLNode* InsertFirstChild( XMLNode* addThis );  
850 - /**  
851 - Add a node after the specified child node.  
852 - If the child node is already part of the document,  
853 - it is moved from its old location to the new location.  
854 - Returns the addThis argument or 0 if the afterThis node  
855 - is not a child of this node, or if the node does not  
856 - belong to the same document.  
857 - */  
858 - XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );  
859 -  
860 - /**  
861 - Delete all the children of this node.  
862 - */  
863 - void DeleteChildren();  
864 -  
865 - /**  
866 - Delete a child of this node.  
867 - */  
868 - void DeleteChild( XMLNode* node );  
869 -  
870 - /**  
871 - Make a copy of this node, but not its children.  
872 - You may pass in a Document pointer that will be  
873 - the owner of the new Node. If the 'document' is  
874 - null, then the node returned will be allocated  
875 - from the current Document. (this->GetDocument())  
876 -  
877 - Note: if called on a XMLDocument, this will return null.  
878 - */  
879 - virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;  
880 -  
881 - /**  
882 - Make a copy of this node and all its children.  
883 -  
884 - If the 'target' is null, then the nodes will  
885 - be allocated in the current document. If 'target'  
886 - is specified, the memory will be allocated is the  
887 - specified XMLDocument.  
888 -  
889 - NOTE: This is probably not the correct tool to  
890 - copy a document, since XMLDocuments can have multiple  
891 - top level XMLNodes. You probably want to use  
892 - XMLDocument::DeepCopy()  
893 - */  
894 - XMLNode* DeepClone( XMLDocument* target ) const;  
895 -  
896 - /**  
897 - Test if 2 nodes are the same, but don't test children.  
898 - The 2 nodes do not need to be in the same Document.  
899 -  
900 - Note: if called on a XMLDocument, this will return false.  
901 - */  
902 - virtual bool ShallowEqual( const XMLNode* compare ) const = 0;  
903 -  
904 - /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the  
905 - XML tree will be conditionally visited and the host will be called back  
906 - via the XMLVisitor interface.  
907 -  
908 - This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse  
909 - the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this  
910 - interface versus any other.)  
911 -  
912 - The interface has been based on ideas from:  
913 -  
914 - - http://www.saxproject.org/  
915 - - http://c2.com/cgi/wiki?HierarchicalVisitorPattern  
916 -  
917 - Which are both good references for "visiting".  
918 -  
919 - An example of using Accept():  
920 - @verbatim  
921 - XMLPrinter printer;  
922 - tinyxmlDoc.Accept( &printer );  
923 - const char* xmlcstr = printer.CStr();  
924 - @endverbatim  
925 - */  
926 - virtual bool Accept( XMLVisitor* visitor ) const = 0;  
927 -  
928 - /**  
929 - Set user data into the XMLNode. TinyXML-2 in  
930 - no way processes or interprets user data.  
931 - It is initially 0.  
932 - */  
933 - void SetUserData(void* userData) { _userData = userData; }  
934 -  
935 - /**  
936 - Get user data set into the XMLNode. TinyXML-2 in  
937 - no way processes or interprets user data.  
938 - It is initially 0.  
939 - */  
940 - void* GetUserData() const { return _userData; }  
941 -  
942 -protected:  
943 - XMLNode( XMLDocument* );  
944 - virtual ~XMLNode();  
945 -  
946 - virtual char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr);  
947 -  
948 - XMLDocument* _document;  
949 - XMLNode* _parent;  
950 - mutable StrPair _value;  
951 - int _parseLineNum;  
952 -  
953 - XMLNode* _firstChild;  
954 - XMLNode* _lastChild;  
955 -  
956 - XMLNode* _prev;  
957 - XMLNode* _next;  
958 -  
959 - void* _userData;  
960 -  
961 -private:  
962 - MemPool* _memPool;  
963 - void Unlink( XMLNode* child );  
964 - static void DeleteNode( XMLNode* node );  
965 - void InsertChildPreamble( XMLNode* insertThis ) const;  
966 - const XMLElement* ToElementWithName( const char* name ) const;  
967 -  
968 - XMLNode( const XMLNode& ); // not supported  
969 - XMLNode& operator=( const XMLNode& ); // not supported  
970 -};  
971 -  
972 -  
973 -/** XML text.  
974 -  
975 - Note that a text node can have child element nodes, for example:  
976 - @verbatim  
977 - <root>This is <b>bold</b></root>  
978 - @endverbatim  
979 -  
980 - A text node can have 2 ways to output the next. "normal" output  
981 - and CDATA. It will default to the mode it was parsed from the XML file and  
982 - you generally want to leave it alone, but you can change the output mode with  
983 - SetCData() and query it with CData().  
984 -*/  
985 -class TINYXML2_LIB XMLText : public XMLNode  
986 -{  
987 - friend class XMLDocument;  
988 -public:  
989 - virtual bool Accept( XMLVisitor* visitor ) const;  
990 -  
991 - virtual XMLText* ToText() {  
992 - return this;  
993 - }  
994 - virtual const XMLText* ToText() const {  
995 - return this;  
996 - }  
997 -  
998 - /// Declare whether this should be CDATA or standard text.  
999 - void SetCData( bool isCData ) {  
1000 - _isCData = isCData;  
1001 - }  
1002 - /// Returns true if this is a CDATA text element.  
1003 - bool CData() const {  
1004 - return _isCData;  
1005 - }  
1006 -  
1007 - virtual XMLNode* ShallowClone( XMLDocument* document ) const;  
1008 - virtual bool ShallowEqual( const XMLNode* compare ) const;  
1009 -  
1010 -protected:  
1011 - XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}  
1012 - virtual ~XMLText() {}  
1013 -  
1014 - char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );  
1015 -  
1016 -private:  
1017 - bool _isCData;  
1018 -  
1019 - XMLText( const XMLText& ); // not supported  
1020 - XMLText& operator=( const XMLText& ); // not supported  
1021 -};  
1022 -  
1023 -  
1024 -/** An XML Comment. */  
1025 -class TINYXML2_LIB XMLComment : public XMLNode  
1026 -{  
1027 - friend class XMLDocument;  
1028 -public:  
1029 - virtual XMLComment* ToComment() {  
1030 - return this;  
1031 - }  
1032 - virtual const XMLComment* ToComment() const {  
1033 - return this;  
1034 - }  
1035 -  
1036 - virtual bool Accept( XMLVisitor* visitor ) const;  
1037 -  
1038 - virtual XMLNode* ShallowClone( XMLDocument* document ) const;  
1039 - virtual bool ShallowEqual( const XMLNode* compare ) const;  
1040 -  
1041 -protected:  
1042 - XMLComment( XMLDocument* doc );  
1043 - virtual ~XMLComment();  
1044 -  
1045 - char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr);  
1046 -  
1047 -private:  
1048 - XMLComment( const XMLComment& ); // not supported  
1049 - XMLComment& operator=( const XMLComment& ); // not supported  
1050 -};  
1051 -  
1052 -  
1053 -/** In correct XML the declaration is the first entry in the file.  
1054 - @verbatim  
1055 - <?xml version="1.0" standalone="yes"?>  
1056 - @endverbatim  
1057 -  
1058 - TinyXML-2 will happily read or write files without a declaration,  
1059 - however.  
1060 -  
1061 - The text of the declaration isn't interpreted. It is parsed  
1062 - and written as a string.  
1063 -*/  
1064 -class TINYXML2_LIB XMLDeclaration : public XMLNode  
1065 -{  
1066 - friend class XMLDocument;  
1067 -public:  
1068 - virtual XMLDeclaration* ToDeclaration() {  
1069 - return this;  
1070 - }  
1071 - virtual const XMLDeclaration* ToDeclaration() const {  
1072 - return this;  
1073 - }  
1074 -  
1075 - virtual bool Accept( XMLVisitor* visitor ) const;  
1076 -  
1077 - virtual XMLNode* ShallowClone( XMLDocument* document ) const;  
1078 - virtual bool ShallowEqual( const XMLNode* compare ) const;  
1079 -  
1080 -protected:  
1081 - XMLDeclaration( XMLDocument* doc );  
1082 - virtual ~XMLDeclaration();  
1083 -  
1084 - char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );  
1085 -  
1086 -private:  
1087 - XMLDeclaration( const XMLDeclaration& ); // not supported  
1088 - XMLDeclaration& operator=( const XMLDeclaration& ); // not supported  
1089 -};  
1090 -  
1091 -  
1092 -/** Any tag that TinyXML-2 doesn't recognize is saved as an  
1093 - unknown. It is a tag of text, but should not be modified.  
1094 - It will be written back to the XML, unchanged, when the file  
1095 - is saved.  
1096 -  
1097 - DTD tags get thrown into XMLUnknowns.  
1098 -*/  
1099 -class TINYXML2_LIB XMLUnknown : public XMLNode  
1100 -{  
1101 - friend class XMLDocument;  
1102 -public:  
1103 - virtual XMLUnknown* ToUnknown() {  
1104 - return this;  
1105 - }  
1106 - virtual const XMLUnknown* ToUnknown() const {  
1107 - return this;  
1108 - }  
1109 -  
1110 - virtual bool Accept( XMLVisitor* visitor ) const;  
1111 -  
1112 - virtual XMLNode* ShallowClone( XMLDocument* document ) const;  
1113 - virtual bool ShallowEqual( const XMLNode* compare ) const;  
1114 -  
1115 -protected:  
1116 - XMLUnknown( XMLDocument* doc );  
1117 - virtual ~XMLUnknown();  
1118 -  
1119 - char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );  
1120 -  
1121 -private:  
1122 - XMLUnknown( const XMLUnknown& ); // not supported  
1123 - XMLUnknown& operator=( const XMLUnknown& ); // not supported  
1124 -};  
1125 -  
1126 -  
1127 -  
1128 -/** An attribute is a name-value pair. Elements have an arbitrary  
1129 - number of attributes, each with a unique name.  
1130 -  
1131 - @note The attributes are not XMLNodes. You may only query the  
1132 - Next() attribute in a list.  
1133 -*/  
1134 -class TINYXML2_LIB XMLAttribute  
1135 -{  
1136 - friend class XMLElement;  
1137 -public:  
1138 - /// The name of the attribute.  
1139 - const char* Name() const;  
1140 -  
1141 - /// The value of the attribute.  
1142 - const char* Value() const;  
1143 -  
1144 - /// Gets the line number the attribute is in, if the document was parsed from a file.  
1145 - int GetLineNum() const { return _parseLineNum; }  
1146 -  
1147 - /// The next attribute in the list.  
1148 - const XMLAttribute* Next() const {  
1149 - return _next;  
1150 - }  
1151 -  
1152 - /** IntValue interprets the attribute as an integer, and returns the value.  
1153 - If the value isn't an integer, 0 will be returned. There is no error checking;  
1154 - use QueryIntValue() if you need error checking.  
1155 - */  
1156 - int IntValue() const {  
1157 - int i = 0;  
1158 - QueryIntValue(&i);  
1159 - return i;  
1160 - }  
1161 -  
1162 - int64_t Int64Value() const {  
1163 - int64_t i = 0;  
1164 - QueryInt64Value(&i);  
1165 - return i;  
1166 - }  
1167 -  
1168 - /// Query as an unsigned integer. See IntValue()  
1169 - unsigned UnsignedValue() const {  
1170 - unsigned i=0;  
1171 - QueryUnsignedValue( &i );  
1172 - return i;  
1173 - }  
1174 - /// Query as a boolean. See IntValue()  
1175 - bool BoolValue() const {  
1176 - bool b=false;  
1177 - QueryBoolValue( &b );  
1178 - return b;  
1179 - }  
1180 - /// Query as a double. See IntValue()  
1181 - double DoubleValue() const {  
1182 - double d=0;  
1183 - QueryDoubleValue( &d );  
1184 - return d;  
1185 - }  
1186 - /// Query as a float. See IntValue()  
1187 - float FloatValue() const {  
1188 - float f=0;  
1189 - QueryFloatValue( &f );  
1190 - return f;  
1191 - }  
1192 -  
1193 - /** QueryIntValue interprets the attribute as an integer, and returns the value  
1194 - in the provided parameter. The function will return XML_SUCCESS on success,  
1195 - and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.  
1196 - */  
1197 - XMLError QueryIntValue( int* value ) const;  
1198 - /// See QueryIntValue  
1199 - XMLError QueryUnsignedValue( unsigned int* value ) const;  
1200 - /// See QueryIntValue  
1201 - XMLError QueryInt64Value(int64_t* value) const;  
1202 - /// See QueryIntValue  
1203 - XMLError QueryBoolValue( bool* value ) const;  
1204 - /// See QueryIntValue  
1205 - XMLError QueryDoubleValue( double* value ) const;  
1206 - /// See QueryIntValue  
1207 - XMLError QueryFloatValue( float* value ) const;  
1208 -  
1209 - /// Set the attribute to a string value.  
1210 - void SetAttribute( const char* value );  
1211 - /// Set the attribute to value.  
1212 - void SetAttribute( int value );  
1213 - /// Set the attribute to value.  
1214 - void SetAttribute( unsigned value );  
1215 - /// Set the attribute to value.  
1216 - void SetAttribute(int64_t value);  
1217 - /// Set the attribute to value.  
1218 - void SetAttribute( bool value );  
1219 - /// Set the attribute to value.  
1220 - void SetAttribute( double value );  
1221 - /// Set the attribute to value.  
1222 - void SetAttribute( float value );  
1223 -  
1224 -private:  
1225 - enum { BUF_SIZE = 200 };  
1226 -  
1227 - XMLAttribute() : _name(), _value(),_parseLineNum( 0 ), _next( 0 ), _memPool( 0 ) {}  
1228 - virtual ~XMLAttribute() {}  
1229 -  
1230 - XMLAttribute( const XMLAttribute& ); // not supported  
1231 - void operator=( const XMLAttribute& ); // not supported  
1232 - void SetName( const char* name );  
1233 -  
1234 - char* ParseDeep( char* p, bool processEntities, int* curLineNumPtr );  
1235 -  
1236 - mutable StrPair _name;  
1237 - mutable StrPair _value;  
1238 - int _parseLineNum;  
1239 - XMLAttribute* _next;  
1240 - MemPool* _memPool;  
1241 -};  
1242 -  
1243 -  
1244 -/** The element is a container class. It has a value, the element name,  
1245 - and can contain other elements, text, comments, and unknowns.  
1246 - Elements also contain an arbitrary number of attributes.  
1247 -*/  
1248 -class TINYXML2_LIB XMLElement : public XMLNode  
1249 -{  
1250 - friend class XMLDocument;  
1251 -public:  
1252 - /// Get the name of an element (which is the Value() of the node.)  
1253 - const char* Name() const {  
1254 - return Value();  
1255 - }  
1256 - /// Set the name of the element.  
1257 - void SetName( const char* str, bool staticMem=false ) {  
1258 - SetValue( str, staticMem );  
1259 - }  
1260 -  
1261 - virtual XMLElement* ToElement() {  
1262 - return this;  
1263 - }  
1264 - virtual const XMLElement* ToElement() const {  
1265 - return this;  
1266 - }  
1267 - virtual bool Accept( XMLVisitor* visitor ) const;  
1268 -  
1269 - /** Given an attribute name, Attribute() returns the value  
1270 - for the attribute of that name, or null if none  
1271 - exists. For example:  
1272 -  
1273 - @verbatim  
1274 - const char* value = ele->Attribute( "foo" );  
1275 - @endverbatim  
1276 -  
1277 - The 'value' parameter is normally null. However, if specified,  
1278 - the attribute will only be returned if the 'name' and 'value'  
1279 - match. This allow you to write code:  
1280 -  
1281 - @verbatim  
1282 - if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();  
1283 - @endverbatim  
1284 -  
1285 - rather than:  
1286 - @verbatim  
1287 - if ( ele->Attribute( "foo" ) ) {  
1288 - if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();  
1289 - }  
1290 - @endverbatim  
1291 - */  
1292 - const char* Attribute( const char* name, const char* value=0 ) const;  
1293 -  
1294 - /** Given an attribute name, IntAttribute() returns the value  
1295 - of the attribute interpreted as an integer. The default  
1296 - value will be returned if the attribute isn't present,  
1297 - or if there is an error. (For a method with error  
1298 - checking, see QueryIntAttribute()).  
1299 - */  
1300 - int IntAttribute(const char* name, int defaultValue = 0) const;  
1301 - /// See IntAttribute()  
1302 - unsigned UnsignedAttribute(const char* name, unsigned defaultValue = 0) const;  
1303 - /// See IntAttribute()  
1304 - int64_t Int64Attribute(const char* name, int64_t defaultValue = 0) const;  
1305 - /// See IntAttribute()  
1306 - bool BoolAttribute(const char* name, bool defaultValue = false) const;  
1307 - /// See IntAttribute()  
1308 - double DoubleAttribute(const char* name, double defaultValue = 0) const;  
1309 - /// See IntAttribute()  
1310 - float FloatAttribute(const char* name, float defaultValue = 0) const;  
1311 -  
1312 - /** Given an attribute name, QueryIntAttribute() returns  
1313 - XML_SUCCESS, XML_WRONG_ATTRIBUTE_TYPE if the conversion  
1314 - can't be performed, or XML_NO_ATTRIBUTE if the attribute  
1315 - doesn't exist. If successful, the result of the conversion  
1316 - will be written to 'value'. If not successful, nothing will  
1317 - be written to 'value'. This allows you to provide default  
1318 - value:  
1319 -  
1320 - @verbatim  
1321 - int value = 10;  
1322 - QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10  
1323 - @endverbatim  
1324 - */  
1325 - XMLError QueryIntAttribute( const char* name, int* value ) const {  
1326 - const XMLAttribute* a = FindAttribute( name );  
1327 - if ( !a ) {  
1328 - return XML_NO_ATTRIBUTE;  
1329 - }  
1330 - return a->QueryIntValue( value );  
1331 - }  
1332 -  
1333 - /// See QueryIntAttribute()  
1334 - XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const {  
1335 - const XMLAttribute* a = FindAttribute( name );  
1336 - if ( !a ) {  
1337 - return XML_NO_ATTRIBUTE;  
1338 - }  
1339 - return a->QueryUnsignedValue( value );  
1340 - }  
1341 -  
1342 - /// See QueryIntAttribute()  
1343 - XMLError QueryInt64Attribute(const char* name, int64_t* value) const {  
1344 - const XMLAttribute* a = FindAttribute(name);  
1345 - if (!a) {  
1346 - return XML_NO_ATTRIBUTE;  
1347 - }  
1348 - return a->QueryInt64Value(value);  
1349 - }  
1350 -  
1351 - /// See QueryIntAttribute()  
1352 - XMLError QueryBoolAttribute( const char* name, bool* value ) const {  
1353 - const XMLAttribute* a = FindAttribute( name );  
1354 - if ( !a ) {  
1355 - return XML_NO_ATTRIBUTE;  
1356 - }  
1357 - return a->QueryBoolValue( value );  
1358 - }  
1359 - /// See QueryIntAttribute()  
1360 - XMLError QueryDoubleAttribute( const char* name, double* value ) const {  
1361 - const XMLAttribute* a = FindAttribute( name );  
1362 - if ( !a ) {  
1363 - return XML_NO_ATTRIBUTE;  
1364 - }  
1365 - return a->QueryDoubleValue( value );  
1366 - }  
1367 - /// See QueryIntAttribute()  
1368 - XMLError QueryFloatAttribute( const char* name, float* value ) const {  
1369 - const XMLAttribute* a = FindAttribute( name );  
1370 - if ( !a ) {  
1371 - return XML_NO_ATTRIBUTE;  
1372 - }  
1373 - return a->QueryFloatValue( value );  
1374 - }  
1375 -  
1376 - /// See QueryIntAttribute()  
1377 - XMLError QueryStringAttribute(const char* name, const char** value) const {  
1378 - const XMLAttribute* a = FindAttribute(name);  
1379 - if (!a) {  
1380 - return XML_NO_ATTRIBUTE;  
1381 - }  
1382 - *value = a->Value();  
1383 - return XML_SUCCESS;  
1384 - }  
1385 -  
1386 -  
1387 -  
1388 - /** Given an attribute name, QueryAttribute() returns  
1389 - XML_SUCCESS, XML_WRONG_ATTRIBUTE_TYPE if the conversion  
1390 - can't be performed, or XML_NO_ATTRIBUTE if the attribute  
1391 - doesn't exist. It is overloaded for the primitive types,  
1392 - and is a generally more convenient replacement of  
1393 - QueryIntAttribute() and related functions.  
1394 -  
1395 - If successful, the result of the conversion  
1396 - will be written to 'value'. If not successful, nothing will  
1397 - be written to 'value'. This allows you to provide default  
1398 - value:  
1399 -  
1400 - @verbatim  
1401 - int value = 10;  
1402 - QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10  
1403 - @endverbatim  
1404 - */  
1405 - int QueryAttribute( const char* name, int* value ) const {  
1406 - return QueryIntAttribute( name, value );  
1407 - }  
1408 -  
1409 - int QueryAttribute( const char* name, unsigned int* value ) const {  
1410 - return QueryUnsignedAttribute( name, value );  
1411 - }  
1412 -  
1413 - int QueryAttribute(const char* name, int64_t* value) const {  
1414 - return QueryInt64Attribute(name, value);  
1415 - }  
1416 -  
1417 - int QueryAttribute( const char* name, bool* value ) const {  
1418 - return QueryBoolAttribute( name, value );  
1419 - }  
1420 -  
1421 - int QueryAttribute( const char* name, double* value ) const {  
1422 - return QueryDoubleAttribute( name, value );  
1423 - }  
1424 -  
1425 - int QueryAttribute( const char* name, float* value ) const {  
1426 - return QueryFloatAttribute( name, value );  
1427 - }  
1428 -  
1429 - /// Sets the named attribute to value.  
1430 - void SetAttribute( const char* name, const char* value ) {  
1431 - XMLAttribute* a = FindOrCreateAttribute( name );  
1432 - a->SetAttribute( value );  
1433 - }  
1434 - /// Sets the named attribute to value.  
1435 - void SetAttribute( const char* name, int value ) {  
1436 - XMLAttribute* a = FindOrCreateAttribute( name );  
1437 - a->SetAttribute( value );  
1438 - }  
1439 - /// Sets the named attribute to value.  
1440 - void SetAttribute( const char* name, unsigned value ) {  
1441 - XMLAttribute* a = FindOrCreateAttribute( name );  
1442 - a->SetAttribute( value );  
1443 - }  
1444 -  
1445 - /// Sets the named attribute to value.  
1446 - void SetAttribute(const char* name, int64_t value) {  
1447 - XMLAttribute* a = FindOrCreateAttribute(name);  
1448 - a->SetAttribute(value);  
1449 - }  
1450 -  
1451 - /// Sets the named attribute to value.  
1452 - void SetAttribute( const char* name, bool value ) {  
1453 - XMLAttribute* a = FindOrCreateAttribute( name );  
1454 - a->SetAttribute( value );  
1455 - }  
1456 - /// Sets the named attribute to value.  
1457 - void SetAttribute( const char* name, double value ) {  
1458 - XMLAttribute* a = FindOrCreateAttribute( name );  
1459 - a->SetAttribute( value );  
1460 - }  
1461 - /// Sets the named attribute to value.  
1462 - void SetAttribute( const char* name, float value ) {  
1463 - XMLAttribute* a = FindOrCreateAttribute( name );  
1464 - a->SetAttribute( value );  
1465 - }  
1466 -  
1467 - /**  
1468 - Delete an attribute.  
1469 - */  
1470 - void DeleteAttribute( const char* name );  
1471 -  
1472 - /// Return the first attribute in the list.  
1473 - const XMLAttribute* FirstAttribute() const {  
1474 - return _rootAttribute;  
1475 - }  
1476 - /// Query a specific attribute in the list.  
1477 - const XMLAttribute* FindAttribute( const char* name ) const;  
1478 -  
1479 - /** Convenience function for easy access to the text inside an element. Although easy  
1480 - and concise, GetText() is limited compared to getting the XMLText child  
1481 - and accessing it directly.  
1482 -  
1483 - If the first child of 'this' is a XMLText, the GetText()  
1484 - returns the character string of the Text node, else null is returned.  
1485 -  
1486 - This is a convenient method for getting the text of simple contained text:  
1487 - @verbatim  
1488 - <foo>This is text</foo>  
1489 - const char* str = fooElement->GetText();  
1490 - @endverbatim  
1491 -  
1492 - 'str' will be a pointer to "This is text".  
1493 -  
1494 - Note that this function can be misleading. If the element foo was created from  
1495 - this XML:  
1496 - @verbatim  
1497 - <foo><b>This is text</b></foo>  
1498 - @endverbatim  
1499 -  
1500 - then the value of str would be null. The first child node isn't a text node, it is  
1501 - another element. From this XML:  
1502 - @verbatim  
1503 - <foo>This is <b>text</b></foo>  
1504 - @endverbatim  
1505 - GetText() will return "This is ".  
1506 - */  
1507 - const char* GetText() const;  
1508 -  
1509 - /** Convenience function for easy access to the text inside an element. Although easy  
1510 - and concise, SetText() is limited compared to creating an XMLText child  
1511 - and mutating it directly.  
1512 -  
1513 - If the first child of 'this' is a XMLText, SetText() sets its value to  
1514 - the given string, otherwise it will create a first child that is an XMLText.  
1515 -  
1516 - This is a convenient method for setting the text of simple contained text:  
1517 - @verbatim  
1518 - <foo>This is text</foo>  
1519 - fooElement->SetText( "Hullaballoo!" );  
1520 - <foo>Hullaballoo!</foo>  
1521 - @endverbatim  
1522 -  
1523 - Note that this function can be misleading. If the element foo was created from  
1524 - this XML:  
1525 - @verbatim  
1526 - <foo><b>This is text</b></foo>  
1527 - @endverbatim  
1528 -  
1529 - then it will not change "This is text", but rather prefix it with a text element:  
1530 - @verbatim  
1531 - <foo>Hullaballoo!<b>This is text</b></foo>  
1532 - @endverbatim  
1533 -  
1534 - For this XML:  
1535 - @verbatim  
1536 - <foo />  
1537 - @endverbatim  
1538 - SetText() will generate  
1539 - @verbatim  
1540 - <foo>Hullaballoo!</foo>  
1541 - @endverbatim  
1542 - */  
1543 - void SetText( const char* inText );  
1544 - /// Convenience method for setting text inside an element. See SetText() for important limitations.  
1545 - void SetText( int value );  
1546 - /// Convenience method for setting text inside an element. See SetText() for important limitations.  
1547 - void SetText( unsigned value );  
1548 - /// Convenience method for setting text inside an element. See SetText() for important limitations.  
1549 - void SetText(int64_t value);  
1550 - /// Convenience method for setting text inside an element. See SetText() for important limitations.  
1551 - void SetText( bool value );  
1552 - /// Convenience method for setting text inside an element. See SetText() for important limitations.  
1553 - void SetText( double value );  
1554 - /// Convenience method for setting text inside an element. See SetText() for important limitations.  
1555 - void SetText( float value );  
1556 -  
1557 - /**  
1558 - Convenience method to query the value of a child text node. This is probably best  
1559 - shown by example. Given you have a document is this form:  
1560 - @verbatim  
1561 - <point>  
1562 - <x>1</x>  
1563 - <y>1.4</y>  
1564 - </point>  
1565 - @endverbatim  
1566 -  
1567 - The QueryIntText() and similar functions provide a safe and easier way to get to the  
1568 - "value" of x and y.  
1569 -  
1570 - @verbatim  
1571 - int x = 0;  
1572 - float y = 0; // types of x and y are contrived for example  
1573 - const XMLElement* xElement = pointElement->FirstChildElement( "x" );  
1574 - const XMLElement* yElement = pointElement->FirstChildElement( "y" );  
1575 - xElement->QueryIntText( &x );  
1576 - yElement->QueryFloatText( &y );  
1577 - @endverbatim  
1578 -  
1579 - @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted  
1580 - to the requested type, and XML_NO_TEXT_NODE if there is no child text to query.  
1581 -  
1582 - */  
1583 - XMLError QueryIntText( int* ival ) const;  
1584 - /// See QueryIntText()  
1585 - XMLError QueryUnsignedText( unsigned* uval ) const;  
1586 - /// See QueryIntText()  
1587 - XMLError QueryInt64Text(int64_t* uval) const;  
1588 - /// See QueryIntText()  
1589 - XMLError QueryBoolText( bool* bval ) const;  
1590 - /// See QueryIntText()  
1591 - XMLError QueryDoubleText( double* dval ) const;  
1592 - /// See QueryIntText()  
1593 - XMLError QueryFloatText( float* fval ) const;  
1594 -  
1595 - int IntText(int defaultValue = 0) const;  
1596 -  
1597 - /// See QueryIntText()  
1598 - unsigned UnsignedText(unsigned defaultValue = 0) const;  
1599 - /// See QueryIntText()  
1600 - int64_t Int64Text(int64_t defaultValue = 0) const;  
1601 - /// See QueryIntText()  
1602 - bool BoolText(bool defaultValue = false) const;  
1603 - /// See QueryIntText()  
1604 - double DoubleText(double defaultValue = 0) const;  
1605 - /// See QueryIntText()  
1606 - float FloatText(float defaultValue = 0) const;  
1607 -  
1608 - // internal:  
1609 - enum ElementClosingType {  
1610 - OPEN, // <foo>  
1611 - CLOSED, // <foo/>  
1612 - CLOSING // </foo>  
1613 - };  
1614 - ElementClosingType ClosingType() const {  
1615 - return _closingType;  
1616 - }  
1617 - virtual XMLNode* ShallowClone( XMLDocument* document ) const;  
1618 - virtual bool ShallowEqual( const XMLNode* compare ) const;  
1619 -  
1620 -protected:  
1621 - char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );  
1622 -  
1623 -private:  
1624 - XMLElement( XMLDocument* doc );  
1625 - virtual ~XMLElement();  
1626 - XMLElement( const XMLElement& ); // not supported  
1627 - void operator=( const XMLElement& ); // not supported  
1628 -  
1629 - XMLAttribute* FindAttribute( const char* name ) {  
1630 - return const_cast<XMLAttribute*>(const_cast<const XMLElement*>(this)->FindAttribute( name ));  
1631 - }  
1632 - XMLAttribute* FindOrCreateAttribute( const char* name );  
1633 - //void LinkAttribute( XMLAttribute* attrib );  
1634 - char* ParseAttributes( char* p, int* curLineNumPtr );  
1635 - static void DeleteAttribute( XMLAttribute* attribute );  
1636 - XMLAttribute* CreateAttribute();  
1637 -  
1638 - enum { BUF_SIZE = 200 };  
1639 - ElementClosingType _closingType;  
1640 - // The attribute list is ordered; there is no 'lastAttribute'  
1641 - // because the list needs to be scanned for dupes before adding  
1642 - // a new attribute.  
1643 - XMLAttribute* _rootAttribute;  
1644 -};  
1645 -  
1646 -  
1647 -enum Whitespace {  
1648 - PRESERVE_WHITESPACE,  
1649 - COLLAPSE_WHITESPACE  
1650 -};  
1651 -  
1652 -  
1653 -/** A Document binds together all the functionality.  
1654 - It can be saved, loaded, and printed to the screen.  
1655 - All Nodes are connected and allocated to a Document.  
1656 - If the Document is deleted, all its Nodes are also deleted.  
1657 -*/  
1658 -class TINYXML2_LIB XMLDocument : public XMLNode  
1659 -{  
1660 - friend class XMLElement;  
1661 - // Gives access to SetError and Push/PopDepth, but over-access for everything else.  
1662 - // Wishing C++ had "internal" scope.  
1663 - friend class XMLNode;  
1664 - friend class XMLText;  
1665 - friend class XMLComment;  
1666 - friend class XMLDeclaration;  
1667 - friend class XMLUnknown;  
1668 -public:  
1669 - /// constructor  
1670 - XMLDocument( bool processEntities = true, Whitespace whitespaceMode = PRESERVE_WHITESPACE );  
1671 - ~XMLDocument();  
1672 -  
1673 - virtual XMLDocument* ToDocument() {  
1674 - TIXMLASSERT( this == _document );  
1675 - return this;  
1676 - }  
1677 - virtual const XMLDocument* ToDocument() const {  
1678 - TIXMLASSERT( this == _document );  
1679 - return this;  
1680 - }  
1681 -  
1682 - /**  
1683 - Parse an XML file from a character string.  
1684 - Returns XML_SUCCESS (0) on success, or  
1685 - an errorID.  
1686 -  
1687 - You may optionally pass in the 'nBytes', which is  
1688 - the number of bytes which will be parsed. If not  
1689 - specified, TinyXML-2 will assume 'xml' points to a  
1690 - null terminated string.  
1691 - */  
1692 - XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );  
1693 -  
1694 - /**  
1695 - Load an XML file from disk.  
1696 - Returns XML_SUCCESS (0) on success, or  
1697 - an errorID.  
1698 - */  
1699 - XMLError LoadFile( const char* filename );  
1700 -  
1701 - /**  
1702 - Load an XML file from disk. You are responsible  
1703 - for providing and closing the FILE*.  
1704 -  
1705 - NOTE: The file should be opened as binary ("rb")  
1706 - not text in order for TinyXML-2 to correctly  
1707 - do newline normalization.  
1708 -  
1709 - Returns XML_SUCCESS (0) on success, or  
1710 - an errorID.  
1711 - */  
1712 - XMLError LoadFile( FILE* );  
1713 -  
1714 - /**  
1715 - Save the XML file to disk.  
1716 - Returns XML_SUCCESS (0) on success, or  
1717 - an errorID.  
1718 - */  
1719 - XMLError SaveFile( const char* filename, bool compact = false );  
1720 -  
1721 - /**  
1722 - Save the XML file to disk. You are responsible  
1723 - for providing and closing the FILE*.  
1724 -  
1725 - Returns XML_SUCCESS (0) on success, or  
1726 - an errorID.  
1727 - */  
1728 - XMLError SaveFile( FILE* fp, bool compact = false );  
1729 -  
1730 - bool ProcessEntities() const {  
1731 - return _processEntities;  
1732 - }  
1733 - Whitespace WhitespaceMode() const {  
1734 - return _whitespaceMode;  
1735 - }  
1736 -  
1737 - /**  
1738 - Returns true if this document has a leading Byte Order Mark of UTF8.  
1739 - */  
1740 - bool HasBOM() const {  
1741 - return _writeBOM;  
1742 - }  
1743 - /** Sets whether to write the BOM when writing the file.  
1744 - */  
1745 - void SetBOM( bool useBOM ) {  
1746 - _writeBOM = useBOM;  
1747 - }  
1748 -  
1749 - /** Return the root element of DOM. Equivalent to FirstChildElement().  
1750 - To get the first node, use FirstChild().  
1751 - */  
1752 - XMLElement* RootElement() {  
1753 - return FirstChildElement();  
1754 - }  
1755 - const XMLElement* RootElement() const {  
1756 - return FirstChildElement();  
1757 - }  
1758 -  
1759 - /** Print the Document. If the Printer is not provided, it will  
1760 - print to stdout. If you provide Printer, this can print to a file:  
1761 - @verbatim  
1762 - XMLPrinter printer( fp );  
1763 - doc.Print( &printer );  
1764 - @endverbatim  
1765 -  
1766 - Or you can use a printer to print to memory:  
1767 - @verbatim  
1768 - XMLPrinter printer;  
1769 - doc.Print( &printer );  
1770 - // printer.CStr() has a const char* to the XML  
1771 - @endverbatim  
1772 - */  
1773 - void Print( XMLPrinter* streamer=0 ) const;  
1774 - virtual bool Accept( XMLVisitor* visitor ) const;  
1775 -  
1776 - /**  
1777 - Create a new Element associated with  
1778 - this Document. The memory for the Element  
1779 - is managed by the Document.  
1780 - */  
1781 - XMLElement* NewElement( const char* name );  
1782 - /**  
1783 - Create a new Comment associated with  
1784 - this Document. The memory for the Comment  
1785 - is managed by the Document.  
1786 - */  
1787 - XMLComment* NewComment( const char* comment );  
1788 - /**  
1789 - Create a new Text associated with  
1790 - this Document. The memory for the Text  
1791 - is managed by the Document.  
1792 - */  
1793 - XMLText* NewText( const char* text );  
1794 - /**  
1795 - Create a new Declaration associated with  
1796 - this Document. The memory for the object  
1797 - is managed by the Document.  
1798 -  
1799 - If the 'text' param is null, the standard  
1800 - declaration is used.:  
1801 - @verbatim  
1802 - <?xml version="1.0" encoding="UTF-8"?>  
1803 - @endverbatim  
1804 - */  
1805 - XMLDeclaration* NewDeclaration( const char* text=0 );  
1806 - /**  
1807 - Create a new Unknown associated with  
1808 - this Document. The memory for the object  
1809 - is managed by the Document.  
1810 - */  
1811 - XMLUnknown* NewUnknown( const char* text );  
1812 -  
1813 - /**  
1814 - Delete a node associated with this document.  
1815 - It will be unlinked from the DOM.  
1816 - */  
1817 - void DeleteNode( XMLNode* node );  
1818 -  
1819 - void ClearError() {  
1820 - SetError(XML_SUCCESS, 0, 0);  
1821 - }  
1822 -  
1823 - /// Return true if there was an error parsing the document.  
1824 - bool Error() const {  
1825 - return _errorID != XML_SUCCESS;  
1826 - }  
1827 - /// Return the errorID.  
1828 - XMLError ErrorID() const {  
1829 - return _errorID;  
1830 - }  
1831 - const char* ErrorName() const;  
1832 - static const char* ErrorIDToName(XMLError errorID);  
1833 -  
1834 - /** Returns a "long form" error description. A hopefully helpful  
1835 - diagnostic with location, line number, and/or additional info.  
1836 - */  
1837 - const char* ErrorStr() const;  
1838 -  
1839 - /// A (trivial) utility function that prints the ErrorStr() to stdout.  
1840 - void PrintError() const;  
1841 -  
1842 - /// Return the line where the error occured, or zero if unknown.  
1843 - int ErrorLineNum() const  
1844 - {  
1845 - return _errorLineNum;  
1846 - }  
1847 -  
1848 - /// Clear the document, resetting it to the initial state.  
1849 - void Clear();  
1850 -  
1851 - /**  
1852 - Copies this document to a target document.  
1853 - The target will be completely cleared before the copy.  
1854 - If you want to copy a sub-tree, see XMLNode::DeepClone().  
1855 -  
1856 - NOTE: that the 'target' must be non-null.  
1857 - */  
1858 - void DeepCopy(XMLDocument* target) const;  
1859 -  
1860 - // internal  
1861 - char* Identify( char* p, XMLNode** node );  
1862 -  
1863 - // internal  
1864 - void MarkInUse(XMLNode*);  
1865 -  
1866 - virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {  
1867 - return 0;  
1868 - }  
1869 - virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {  
1870 - return false;  
1871 - }  
1872 -  
1873 -private:  
1874 - XMLDocument( const XMLDocument& ); // not supported  
1875 - void operator=( const XMLDocument& ); // not supported  
1876 -  
1877 - bool _writeBOM;  
1878 - bool _processEntities;  
1879 - XMLError _errorID;  
1880 - Whitespace _whitespaceMode;  
1881 - mutable StrPair _errorStr;  
1882 - int _errorLineNum;  
1883 - char* _charBuffer;  
1884 - int _parseCurLineNum;  
1885 - int _parsingDepth;  
1886 - // Memory tracking does add some overhead.  
1887 - // However, the code assumes that you don't  
1888 - // have a bunch of unlinked nodes around.  
1889 - // Therefore it takes less memory to track  
1890 - // in the document vs. a linked list in the XMLNode,  
1891 - // and the performance is the same.  
1892 - DynArray<XMLNode*, 10> _unlinked;  
1893 -  
1894 - MemPoolT< sizeof(XMLElement) > _elementPool;  
1895 - MemPoolT< sizeof(XMLAttribute) > _attributePool;  
1896 - MemPoolT< sizeof(XMLText) > _textPool;  
1897 - MemPoolT< sizeof(XMLComment) > _commentPool;  
1898 -  
1899 - static const char* _errorNames[XML_ERROR_COUNT];  
1900 -  
1901 - void Parse();  
1902 -  
1903 - void SetError( XMLError error, int lineNum, const char* format, ... );  
1904 -  
1905 - // Something of an obvious security hole, once it was discovered.  
1906 - // Either an ill-formed XML or an excessively deep one can overflow  
1907 - // the stack. Track stack depth, and error out if needed.  
1908 - class DepthTracker {  
1909 - public:  
1910 - DepthTracker(XMLDocument * document) {  
1911 - this->_document = document;  
1912 - document->PushDepth();  
1913 - }  
1914 - ~DepthTracker() {  
1915 - _document->PopDepth();  
1916 - }  
1917 - private:  
1918 - XMLDocument * _document;  
1919 - };  
1920 - void PushDepth();  
1921 - void PopDepth();  
1922 -  
1923 - template<class NodeType, int PoolElementSize>  
1924 - NodeType* CreateUnlinkedNode( MemPoolT<PoolElementSize>& pool );  
1925 -};  
1926 -  
1927 -template<class NodeType, int PoolElementSize>  
1928 -inline NodeType* XMLDocument::CreateUnlinkedNode( MemPoolT<PoolElementSize>& pool )  
1929 -{  
1930 - TIXMLASSERT( sizeof( NodeType ) == PoolElementSize );  
1931 - TIXMLASSERT( sizeof( NodeType ) == pool.ItemSize() );  
1932 - NodeType* returnNode = new (pool.Alloc()) NodeType( this );  
1933 - TIXMLASSERT( returnNode );  
1934 - returnNode->_memPool = &pool;  
1935 -  
1936 - _unlinked.Push(returnNode);  
1937 - return returnNode;  
1938 -}  
1939 -  
1940 -/**  
1941 - A XMLHandle is a class that wraps a node pointer with null checks; this is  
1942 - an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2  
1943 - DOM structure. It is a separate utility class.  
1944 -  
1945 - Take an example:  
1946 - @verbatim  
1947 - <Document>  
1948 - <Element attributeA = "valueA">  
1949 - <Child attributeB = "value1" />  
1950 - <Child attributeB = "value2" />  
1951 - </Element>  
1952 - </Document>  
1953 - @endverbatim  
1954 -  
1955 - Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very  
1956 - easy to write a *lot* of code that looks like:  
1957 -  
1958 - @verbatim  
1959 - XMLElement* root = document.FirstChildElement( "Document" );  
1960 - if ( root )  
1961 - {  
1962 - XMLElement* element = root->FirstChildElement( "Element" );  
1963 - if ( element )  
1964 - {  
1965 - XMLElement* child = element->FirstChildElement( "Child" );  
1966 - if ( child )  
1967 - {  
1968 - XMLElement* child2 = child->NextSiblingElement( "Child" );  
1969 - if ( child2 )  
1970 - {  
1971 - // Finally do something useful.  
1972 - @endverbatim  
1973 -  
1974 - And that doesn't even cover "else" cases. XMLHandle addresses the verbosity  
1975 - of such code. A XMLHandle checks for null pointers so it is perfectly safe  
1976 - and correct to use:  
1977 -  
1978 - @verbatim  
1979 - XMLHandle docHandle( &document );  
1980 - XMLElement* child2 = docHandle.FirstChildElement( "Document" ).FirstChildElement( "Element" ).FirstChildElement().NextSiblingElement();  
1981 - if ( child2 )  
1982 - {  
1983 - // do something useful  
1984 - @endverbatim  
1985 -  
1986 - Which is MUCH more concise and useful.  
1987 -  
1988 - It is also safe to copy handles - internally they are nothing more than node pointers.  
1989 - @verbatim  
1990 - XMLHandle handleCopy = handle;  
1991 - @endverbatim  
1992 -  
1993 - See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.  
1994 -*/  
1995 -class TINYXML2_LIB XMLHandle  
1996 -{  
1997 -public:  
1998 - /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.  
1999 - XMLHandle( XMLNode* node ) : _node( node ) {  
2000 - }  
2001 - /// Create a handle from a node.  
2002 - XMLHandle( XMLNode& node ) : _node( &node ) {  
2003 - }  
2004 - /// Copy constructor  
2005 - XMLHandle( const XMLHandle& ref ) : _node( ref._node ) {  
2006 - }  
2007 - /// Assignment  
2008 - XMLHandle& operator=( const XMLHandle& ref ) {  
2009 - _node = ref._node;  
2010 - return *this;  
2011 - }  
2012 -  
2013 - /// Get the first child of this handle.  
2014 - XMLHandle FirstChild() {  
2015 - return XMLHandle( _node ? _node->FirstChild() : 0 );  
2016 - }  
2017 - /// Get the first child element of this handle.  
2018 - XMLHandle FirstChildElement( const char* name = 0 ) {  
2019 - return XMLHandle( _node ? _node->FirstChildElement( name ) : 0 );  
2020 - }  
2021 - /// Get the last child of this handle.  
2022 - XMLHandle LastChild() {  
2023 - return XMLHandle( _node ? _node->LastChild() : 0 );  
2024 - }  
2025 - /// Get the last child element of this handle.  
2026 - XMLHandle LastChildElement( const char* name = 0 ) {  
2027 - return XMLHandle( _node ? _node->LastChildElement( name ) : 0 );  
2028 - }  
2029 - /// Get the previous sibling of this handle.  
2030 - XMLHandle PreviousSibling() {  
2031 - return XMLHandle( _node ? _node->PreviousSibling() : 0 );  
2032 - }  
2033 - /// Get the previous sibling element of this handle.  
2034 - XMLHandle PreviousSiblingElement( const char* name = 0 ) {  
2035 - return XMLHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );  
2036 - }  
2037 - /// Get the next sibling of this handle.  
2038 - XMLHandle NextSibling() {  
2039 - return XMLHandle( _node ? _node->NextSibling() : 0 );  
2040 - }  
2041 - /// Get the next sibling element of this handle.  
2042 - XMLHandle NextSiblingElement( const char* name = 0 ) {  
2043 - return XMLHandle( _node ? _node->NextSiblingElement( name ) : 0 );  
2044 - }  
2045 -  
2046 - /// Safe cast to XMLNode. This can return null.  
2047 - XMLNode* ToNode() {  
2048 - return _node;  
2049 - }  
2050 - /// Safe cast to XMLElement. This can return null.  
2051 - XMLElement* ToElement() {  
2052 - return ( _node ? _node->ToElement() : 0 );  
2053 - }  
2054 - /// Safe cast to XMLText. This can return null.  
2055 - XMLText* ToText() {  
2056 - return ( _node ? _node->ToText() : 0 );  
2057 - }  
2058 - /// Safe cast to XMLUnknown. This can return null.  
2059 - XMLUnknown* ToUnknown() {  
2060 - return ( _node ? _node->ToUnknown() : 0 );  
2061 - }  
2062 - /// Safe cast to XMLDeclaration. This can return null.  
2063 - XMLDeclaration* ToDeclaration() {  
2064 - return ( _node ? _node->ToDeclaration() : 0 );  
2065 - }  
2066 -  
2067 -private:  
2068 - XMLNode* _node;  
2069 -};  
2070 -  
2071 -  
2072 -/**  
2073 - A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the  
2074 - same in all regards, except for the 'const' qualifiers. See XMLHandle for API.  
2075 -*/  
2076 -class TINYXML2_LIB XMLConstHandle  
2077 -{  
2078 -public:  
2079 - XMLConstHandle( const XMLNode* node ) : _node( node ) {  
2080 - }  
2081 - XMLConstHandle( const XMLNode& node ) : _node( &node ) {  
2082 - }  
2083 - XMLConstHandle( const XMLConstHandle& ref ) : _node( ref._node ) {  
2084 - }  
2085 -  
2086 - XMLConstHandle& operator=( const XMLConstHandle& ref ) {  
2087 - _node = ref._node;  
2088 - return *this;  
2089 - }  
2090 -  
2091 - const XMLConstHandle FirstChild() const {  
2092 - return XMLConstHandle( _node ? _node->FirstChild() : 0 );  
2093 - }  
2094 - const XMLConstHandle FirstChildElement( const char* name = 0 ) const {  
2095 - return XMLConstHandle( _node ? _node->FirstChildElement( name ) : 0 );  
2096 - }  
2097 - const XMLConstHandle LastChild() const {  
2098 - return XMLConstHandle( _node ? _node->LastChild() : 0 );  
2099 - }  
2100 - const XMLConstHandle LastChildElement( const char* name = 0 ) const {  
2101 - return XMLConstHandle( _node ? _node->LastChildElement( name ) : 0 );  
2102 - }  
2103 - const XMLConstHandle PreviousSibling() const {  
2104 - return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );  
2105 - }  
2106 - const XMLConstHandle PreviousSiblingElement( const char* name = 0 ) const {  
2107 - return XMLConstHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );  
2108 - }  
2109 - const XMLConstHandle NextSibling() const {  
2110 - return XMLConstHandle( _node ? _node->NextSibling() : 0 );  
2111 - }  
2112 - const XMLConstHandle NextSiblingElement( const char* name = 0 ) const {  
2113 - return XMLConstHandle( _node ? _node->NextSiblingElement( name ) : 0 );  
2114 - }  
2115 -  
2116 -  
2117 - const XMLNode* ToNode() const {  
2118 - return _node;  
2119 - }  
2120 - const XMLElement* ToElement() const {  
2121 - return ( _node ? _node->ToElement() : 0 );  
2122 - }  
2123 - const XMLText* ToText() const {  
2124 - return ( _node ? _node->ToText() : 0 );  
2125 - }  
2126 - const XMLUnknown* ToUnknown() const {  
2127 - return ( _node ? _node->ToUnknown() : 0 );  
2128 - }  
2129 - const XMLDeclaration* ToDeclaration() const {  
2130 - return ( _node ? _node->ToDeclaration() : 0 );  
2131 - }  
2132 -  
2133 -private:  
2134 - const XMLNode* _node;  
2135 -};  
2136 -  
2137 -  
2138 -/**  
2139 - Printing functionality. The XMLPrinter gives you more  
2140 - options than the XMLDocument::Print() method.  
2141 -  
2142 - It can:  
2143 - -# Print to memory.  
2144 - -# Print to a file you provide.  
2145 - -# Print XML without a XMLDocument.  
2146 -  
2147 - Print to Memory  
2148 -  
2149 - @verbatim  
2150 - XMLPrinter printer;  
2151 - doc.Print( &printer );  
2152 - SomeFunction( printer.CStr() );  
2153 - @endverbatim  
2154 -  
2155 - Print to a File  
2156 -  
2157 - You provide the file pointer.  
2158 - @verbatim  
2159 - XMLPrinter printer( fp );  
2160 - doc.Print( &printer );  
2161 - @endverbatim  
2162 -  
2163 - Print without a XMLDocument  
2164 -  
2165 - When loading, an XML parser is very useful. However, sometimes  
2166 - when saving, it just gets in the way. The code is often set up  
2167 - for streaming, and constructing the DOM is just overhead.  
2168 -  
2169 - The Printer supports the streaming case. The following code  
2170 - prints out a trivially simple XML file without ever creating  
2171 - an XML document.  
2172 -  
2173 - @verbatim  
2174 - XMLPrinter printer( fp );  
2175 - printer.OpenElement( "foo" );  
2176 - printer.PushAttribute( "foo", "bar" );  
2177 - printer.CloseElement();  
2178 - @endverbatim  
2179 -*/  
2180 -class TINYXML2_LIB XMLPrinter : public XMLVisitor  
2181 -{  
2182 -public:  
2183 - /** Construct the printer. If the FILE* is specified,  
2184 - this will print to the FILE. Else it will print  
2185 - to memory, and the result is available in CStr().  
2186 - If 'compact' is set to true, then output is created  
2187 - with only required whitespace and newlines.  
2188 - */  
2189 - XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 );  
2190 - virtual ~XMLPrinter() {}  
2191 -  
2192 - /** If streaming, write the BOM and declaration. */  
2193 - void PushHeader( bool writeBOM, bool writeDeclaration );  
2194 - /** If streaming, start writing an element.  
2195 - The element must be closed with CloseElement()  
2196 - */  
2197 - void OpenElement( const char* name, bool compactMode=false );  
2198 - /// If streaming, add an attribute to an open element.  
2199 - void PushAttribute( const char* name, const char* value );  
2200 - void PushAttribute( const char* name, int value );  
2201 - void PushAttribute( const char* name, unsigned value );  
2202 - void PushAttribute(const char* name, int64_t value);  
2203 - void PushAttribute( const char* name, bool value );  
2204 - void PushAttribute( const char* name, double value );  
2205 - /// If streaming, close the Element.  
2206 - virtual void CloseElement( bool compactMode=false );  
2207 -  
2208 - /// Add a text node.  
2209 - void PushText( const char* text, bool cdata=false );  
2210 - /// Add a text node from an integer.  
2211 - void PushText( int value );  
2212 - /// Add a text node from an unsigned.  
2213 - void PushText( unsigned value );  
2214 - /// Add a text node from an unsigned.  
2215 - void PushText(int64_t value);  
2216 - /// Add a text node from a bool.  
2217 - void PushText( bool value );  
2218 - /// Add a text node from a float.  
2219 - void PushText( float value );  
2220 - /// Add a text node from a double.  
2221 - void PushText( double value );  
2222 -  
2223 - /// Add a comment  
2224 - void PushComment( const char* comment );  
2225 -  
2226 - void PushDeclaration( const char* value );  
2227 - void PushUnknown( const char* value );  
2228 -  
2229 - virtual bool VisitEnter( const XMLDocument& /*doc*/ );  
2230 - virtual bool VisitExit( const XMLDocument& /*doc*/ ) {  
2231 - return true;  
2232 - }  
2233 -  
2234 - virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );  
2235 - virtual bool VisitExit( const XMLElement& element );  
2236 -  
2237 - virtual bool Visit( const XMLText& text );  
2238 - virtual bool Visit( const XMLComment& comment );  
2239 - virtual bool Visit( const XMLDeclaration& declaration );  
2240 - virtual bool Visit( const XMLUnknown& unknown );  
2241 -  
2242 - /**  
2243 - If in print to memory mode, return a pointer to  
2244 - the XML file in memory.  
2245 - */  
2246 - const char* CStr() const {  
2247 - return _buffer.Mem();  
2248 - }  
2249 - /**  
2250 - If in print to memory mode, return the size  
2251 - of the XML file in memory. (Note the size returned  
2252 - includes the terminating null.)  
2253 - */  
2254 - int CStrSize() const {  
2255 - return _buffer.Size();  
2256 - }  
2257 - /**  
2258 - If in print to memory mode, reset the buffer to the  
2259 - beginning.  
2260 - */  
2261 - void ClearBuffer() {  
2262 - _buffer.Clear();  
2263 - _buffer.Push(0);  
2264 - _firstElement = true;  
2265 - }  
2266 -  
2267 -protected:  
2268 - virtual bool CompactMode( const XMLElement& ) { return _compactMode; }  
2269 -  
2270 - /** Prints out the space before an element. You may override to change  
2271 - the space and tabs used. A PrintSpace() override should call Print().  
2272 - */  
2273 - virtual void PrintSpace( int depth );  
2274 - void Print( const char* format, ... );  
2275 - void Write( const char* data, size_t size );  
2276 - inline void Write( const char* data ) { Write( data, strlen( data ) ); }  
2277 - void Putc( char ch );  
2278 -  
2279 - void SealElementIfJustOpened();  
2280 - bool _elementJustOpened;  
2281 - DynArray< const char*, 10 > _stack;  
2282 -  
2283 -private:  
2284 - void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.  
2285 -  
2286 - bool _firstElement;  
2287 - FILE* _fp;  
2288 - int _depth;  
2289 - int _textDepth;  
2290 - bool _processEntities;  
2291 - bool _compactMode;  
2292 -  
2293 - enum {  
2294 - ENTITY_RANGE = 64,  
2295 - BUF_SIZE = 200  
2296 - };  
2297 - bool _entityFlag[ENTITY_RANGE];  
2298 - bool _restrictedEntityFlag[ENTITY_RANGE];  
2299 -  
2300 - DynArray< char, 20 > _buffer;  
2301 -  
2302 - // Prohibit cloning, intentionally not implemented  
2303 - XMLPrinter( const XMLPrinter& );  
2304 - XMLPrinter& operator=( const XMLPrinter& );  
2305 -};  
2306 -  
2307 -  
2308 -} // tinyxml2  
2309 -  
2310 -#if defined(_MSC_VER)  
2311 -# pragma warning(pop)  
2312 -#endif  
2313 -  
2314 -#endif // TINYXML2_INCLUDED  
src/decoder/test_28181.cpp
@@ -3,7 +3,6 @@ @@ -3,7 +3,6 @@
3 #include <thread> 3 #include <thread>
4 #include <chrono> 4 #include <chrono>
5 #include "../common/logger.hpp" 5 #include "../common/logger.hpp"
6 -#include "./gb28181/sip/SipServer.h"  
7 6
8 using namespace std; 7 using namespace std;
9 8
@@ -142,10 +141,6 @@ int main(){ @@ -142,10 +141,6 @@ int main(){
142 141
143 printf("start... \n"); 142 printf("start... \n");
144 143
145 - SipServer* pSipServer = SipServer::getInstance();  
146 - pSipServer->Init(nullptr);  
147 -  
148 -  
149 DecoderManager* pDecManager = DecoderManager::getInstance(); 144 DecoderManager* pDecManager = DecoderManager::getInstance();
150 145
151 146
src/demo/demo.cpp
@@ -914,7 +914,7 @@ string createTask(void *handle, std::vector&lt;algorithm_type_t&gt; algor_vec, int gi, @@ -914,7 +914,7 @@ string createTask(void *handle, std::vector&lt;algorithm_type_t&gt; algor_vec, int gi,
914 914
915 switch(gi){ 915 switch(gi){
916 case 0: 916 case 0:
917 - tparam.ipc_url = "rtsp://admin:ad123456@192.168.60.165:554/cam/realmonitor?channel=1&subtype=0"; 917 + tparam.ipc_url = "rtsp://admin:admin@123456@192.168.60.176:554/cam/realmonitor?channel=1&subtype=0";
918 break; 918 break;
919 case 1: 919 case 1:
920 tparam.ipc_url = "rtsp://122.97.218.170:8604/openUrl/V5nXRHa?params=eyJwcm90b2NhbCI6InJ0c3AiLCJjbGllbnRUeXBlIjoib3Blbl9hcGkiLCJleHByaWVUaW1lIjotMSwicHJvdG9jb2wiOiJydHNwIiwiZXhwaXJlVGltZSI6MzAwLCJlbmFibGVNR0MiOnRydWUsImV4cGFuZCI6InN0YW5kYXJkPXJ0c3Amc3RyZWFtZm9ybT1ydHAiLCJhIjoiMTBjZjM4N2JjY2Y5NDg3YzhjNWYzNjE2M2ViMWUyNTJ8MXwwfDEiLCJ0IjoxfQ=="; 920 tparam.ipc_url = "rtsp://122.97.218.170:8604/openUrl/V5nXRHa?params=eyJwcm90b2NhbCI6InJ0c3AiLCJjbGllbnRUeXBlIjoib3Blbl9hcGkiLCJleHByaWVUaW1lIjotMSwicHJvdG9jb2wiOiJydHNwIiwiZXhwaXJlVGltZSI6MzAwLCJlbmFibGVNR0MiOnRydWUsImV4cGFuZCI6InN0YW5kYXJkPXJ0c3Amc3RyZWFtZm9ybT1ydHAiLCJhIjoiMTBjZjM4N2JjY2Y5NDg3YzhjNWYzNjE2M2ViMWUyNTJ8MXwwfDEiLCJ0IjoxfQ==";
@@ -1059,8 +1059,6 @@ string createTask(void *handle, std::vector&lt;algorithm_type_t&gt; algor_vec, int gi, @@ -1059,8 +1059,6 @@ string createTask(void *handle, std::vector&lt;algorithm_type_t&gt; algor_vec, int gi,
1059 } 1059 }
1060 delete[] tparam.algor_config_params; 1060 delete[] tparam.algor_config_params;
1061 1061
1062 -  
1063 -  
1064 return task_id_str; 1062 return task_id_str;
1065 } 1063 }
1066 1064
@@ -1078,6 +1076,15 @@ string createTask_dvpp28181(void *handle, std::vector&lt;algorithm_type_t&gt; algor_ve @@ -1078,6 +1076,15 @@ string createTask_dvpp28181(void *handle, std::vector&lt;algorithm_type_t&gt; algor_ve
1078 case 2: 1076 case 2:
1079 tparam.ipc_url = "34020000001310000201"; 1077 tparam.ipc_url = "34020000001310000201";
1080 break; 1078 break;
  1079 + case 3:
  1080 + tparam.ipc_url = "32120200002160000077";
  1081 + break;
  1082 + case 4:
  1083 + tparam.ipc_url = "34020000001320000207";
  1084 + break;
  1085 + case 5:
  1086 + tparam.ipc_url = "34020000001310000176";
  1087 + break;
1081 default: 1088 default:
1082 tparam.ipc_url = "34020000001310004065"; 1089 tparam.ipc_url = "34020000001310004065";
1083 break; 1090 break;
@@ -1280,6 +1287,7 @@ void test_gpu(int gpuID){ @@ -1280,6 +1287,7 @@ void test_gpu(int gpuID){
1280 void test_dvpp28181(int gpuID) { 1287 void test_dvpp28181(int gpuID) {
1281 tsl_aiplatform_param vptParam; 1288 tsl_aiplatform_param vptParam;
1282 vptParam.gpuid = gpuID; 1289 vptParam.gpuid = gpuID;
  1290 + vptParam.sip_server_port = 15080;
1283 vptParam.trt_serialize_file = ""; 1291 vptParam.trt_serialize_file = "";
1284 vptParam.models_dir = "."; 1292 vptParam.models_dir = ".";
1285 1293
@@ -1334,6 +1342,21 @@ while (ch != &#39;q&#39;) { @@ -1334,6 +1342,21 @@ while (ch != &#39;q&#39;) {
1334 case '2': 1342 case '2':
1335 createTask_dvpp28181(handle, algor_vec, 2, false); 1343 createTask_dvpp28181(handle, algor_vec, 2, false);
1336 break; 1344 break;
  1345 + case '3':
  1346 + createTask_dvpp28181(handle, algor_vec, 3, false);
  1347 + break;
  1348 + case '4':
  1349 + createTask_dvpp28181(handle, algor_vec, 4, false);
  1350 + break;
  1351 + case '5':
  1352 + createTask_dvpp28181(handle, algor_vec, 5, false);
  1353 + break;
  1354 + case '6':
  1355 + createTask(handle, algor_vec2, 2, false);
  1356 + break;
  1357 + case '7':
  1358 + createTask(handle, algor_vec2, 0, false);
  1359 + break;
1337 case 'c': 1360 case 'c':
1338 close_all_task(handle); 1361 close_all_task(handle);
1339 break; 1362 break;
src/tsl_aiplatform_jni/AiEngineNativeInterface.cpp
@@ -53,6 +53,7 @@ JNIEXPORT jint JNICALL Java_com_objecteye_nativeinterface_TSLAiEngineNativeInter @@ -53,6 +53,7 @@ JNIEXPORT jint JNICALL Java_com_objecteye_nativeinterface_TSLAiEngineNativeInter
53 // getFieldID 53 // getFieldID
54 jclass cls_aiEngineParam = env->GetObjectClass(aiEngineParam); 54 jclass cls_aiEngineParam = env->GetObjectClass(aiEngineParam);
55 jfieldID fid_aiEngineParam_gpuid = env->GetFieldID(cls_aiEngineParam, "gpuID", "I"); 55 jfieldID fid_aiEngineParam_gpuid = env->GetFieldID(cls_aiEngineParam, "gpuID", "I");
  56 + jfieldID fid_aiEngineParam_sipServerPort = env->GetFieldID(cls_aiEngineParam, "sipServerPort", "I");
56 jfieldID fid_aiEngineParam_trtSerializeFileFolder = env->GetFieldID(cls_aiEngineParam, "trtSerializeFileFolder", "Ljava/lang/String;"); 57 jfieldID fid_aiEngineParam_trtSerializeFileFolder = env->GetFieldID(cls_aiEngineParam, "trtSerializeFileFolder", "Ljava/lang/String;");
57 jfieldID fid_aiEngineParam_modelsDir = env->GetFieldID(cls_aiEngineParam, "modelsDir", "Ljava/lang/String;"); 58 jfieldID fid_aiEngineParam_modelsDir = env->GetFieldID(cls_aiEngineParam, "modelsDir", "Ljava/lang/String;");
58 jfieldID fid_aiEngineParam_logLevel = env->GetFieldID(cls_aiEngineParam, "logLevel", "I"); 59 jfieldID fid_aiEngineParam_logLevel = env->GetFieldID(cls_aiEngineParam, "logLevel", "I");
@@ -63,6 +64,7 @@ JNIEXPORT jint JNICALL Java_com_objecteye_nativeinterface_TSLAiEngineNativeInter @@ -63,6 +64,7 @@ JNIEXPORT jint JNICALL Java_com_objecteye_nativeinterface_TSLAiEngineNativeInter
63 64
64 // getObjectField 65 // getObjectField
65 jint aiEngineParam_gpuid = env->GetIntField(aiEngineParam, fid_aiEngineParam_gpuid); 66 jint aiEngineParam_gpuid = env->GetIntField(aiEngineParam, fid_aiEngineParam_gpuid);
  67 + jint aiEngineParam_sipServerPort = env->GetIntField(aiEngineParam, fid_aiEngineParam_sipServerPort);
66 jstring str_aiEngineParam_trtSerializeFileFolder = 68 jstring str_aiEngineParam_trtSerializeFileFolder =
67 (jstring)env->GetObjectField(aiEngineParam, fid_aiEngineParam_trtSerializeFileFolder); 69 (jstring)env->GetObjectField(aiEngineParam, fid_aiEngineParam_trtSerializeFileFolder);
68 const char *aiEngineParam_trtSerializeFileFolder = 70 const char *aiEngineParam_trtSerializeFileFolder =
@@ -85,6 +87,7 @@ JNIEXPORT jint JNICALL Java_com_objecteye_nativeinterface_TSLAiEngineNativeInter @@ -85,6 +87,7 @@ JNIEXPORT jint JNICALL Java_com_objecteye_nativeinterface_TSLAiEngineNativeInter
85 87
86 tsl_aiplatform_param mAiEngineParam; 88 tsl_aiplatform_param mAiEngineParam;
87 mAiEngineParam.gpuid = aiEngineParam_gpuid; 89 mAiEngineParam.gpuid = aiEngineParam_gpuid;
  90 + mAiEngineParam.sip_server_port= aiEngineParam_sipServerPort;
88 mAiEngineParam.trt_serialize_file = (char *)aiEngineParam_trtSerializeFileFolder; 91 mAiEngineParam.trt_serialize_file = (char *)aiEngineParam_trtSerializeFileFolder;
89 mAiEngineParam.models_dir = (char *)aiEngineParam_modelsDir; 92 mAiEngineParam.models_dir = (char *)aiEngineParam_modelsDir;
90 93
@@ -94,6 +97,7 @@ JNIEXPORT jint JNICALL Java_com_objecteye_nativeinterface_TSLAiEngineNativeInter @@ -94,6 +97,7 @@ JNIEXPORT jint JNICALL Java_com_objecteye_nativeinterface_TSLAiEngineNativeInter
94 mAiEngineParam.log_mem = aiEngineParam_logMem; 97 mAiEngineParam.log_mem = aiEngineParam_logMem;
95 98
96 printf("-- *************** Summary **********************.\n"); 99 printf("-- *************** Summary **********************.\n");
  100 + printf("-- sip server port:%d \n", (int)aiEngineParam_sipServerPort);
97 printf("-- [logger]\n"); 101 printf("-- [logger]\n");
98 printf("-- level :%d(int)\n", (int)aiEngineParam_logLevel); 102 printf("-- level :%d(int)\n", (int)aiEngineParam_logLevel);
99 printf("-- path :%s(str)\n", (char *)aiEngineParam_logPath); 103 printf("-- path :%s(str)\n", (char *)aiEngineParam_logPath);
src/tsl_aiplatform_jni/Makefile
@@ -6,7 +6,7 @@ AR = ar @@ -6,7 +6,7 @@ AR = ar
6 DEFS=-DPOST_USE_RABBITMQ 6 DEFS=-DPOST_USE_RABBITMQ
7 7
8 8
9 -PROJECT_ROOT= /data/shzhao/vpt_ascend 9 +PROJECT_ROOT= /home/cmhu/vpt_ascend_arm
10 10
11 DEPEND_DIR = $(PROJECT_ROOT)/bin 11 DEPEND_DIR = $(PROJECT_ROOT)/bin
12 SRC_ROOT = $(PROJECT_ROOT)/src/tsl_aiplatform_jni 12 SRC_ROOT = $(PROJECT_ROOT)/src/tsl_aiplatform_jni