Commit 69ee81f39f940c6f12def7ba798b63dceab25352

Authored by Hu Chunming
1 parent 16819232

提交websocket client完整版功能代码

src/ai_platform/MultiSourceProcess.cpp
... ... @@ -22,7 +22,7 @@
22 22  
23 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 27 // #define VEHICLE_MULTI_BOXES
28 28  
... ... @@ -90,17 +90,17 @@ int CMultiSourceProcess::InitAlgorthim(tsl_aiplatform_param vptParam){
90 90 set_default_logger(LogLevel(vptParam.log_level), "multi_source_process", vptParam.log_path, vptParam.log_mem, vptParam.log_mem);
91 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 105 SourceSingleton::getInstance();
106 106  
... ... @@ -216,7 +216,15 @@ int CMultiSourceProcess::InitAlgorthim(tsl_aiplatform_param vptParam){
216 216 }
217 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 226 m_task_param_manager = task_param_manager::getInstance();
  227 +
220 228 m_snapshot_reprocessing = new snapshot_reprocessing(m_devId);
221 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 235 VPCUtil* pVpcUtil = VPCUtil::getInstance();
228 236 pVpcUtil->init(m_devId);
229 237  
230   - // 初始化SIP服务器
231   - SipServer* pSipServer = SipServer::getInstance();
232   - pSipServer->Init(nullptr);
233   -
234 238 m_pAlgorthimThread = new thread([](void* arg) {
235 239 CMultiSourceProcess* process = (CMultiSourceProcess*)arg ;
236 240 process->algorthim_process_thread();
... ... @@ -694,21 +698,21 @@ int CMultiSourceProcess::algorthim_process_thread(){
694 698 ACL_CALL(aclrtCreateContext(&ctx, m_devId), ACL_SUCCESS, 1);
695 699  
696 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 716 if(m_bfinish){
713 717 break;
714 718 }
... ... @@ -731,7 +735,7 @@ int CMultiSourceProcess::algorthim_process_thread(){
731 735 if (algor_map != nullptr) {
732 736 int input_image_width = gpuMem->getWidth();
733 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 740 /* 如果开启了行人 机动车非法闯入功能 生成闯入区域mask */
737 741 if (algor_map->find(algorithm_type_t::PEDESTRIAN_TRESPASS) != algor_map->end()) {
... ... @@ -771,11 +775,36 @@ int CMultiSourceProcess::algorthim_process_thread(){
771 775 algorthim_vpt(vec_gpuMem);
772 776 auto vptprocess2 = std::chrono::system_clock::now();
773 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 780 #ifdef WITH_FACE_DET_SS
777 781 algorthim_face_detect(vec_gpuMem);
778 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 808 // auto record_t2 = std::chrono::system_clock::now();
780 809 // auto record_time = std::chrono::duration_cast<std::chrono::milliseconds>(record_t2 - record_t1).count();
781 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 2208 nYear = info->tm_year + 1900;
2180 2209 nMonth = info->tm_mon + 1;
2181 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 2213 return true;
2185 2214 }
... ...
src/ai_platform/header.h
... ... @@ -589,6 +589,7 @@ typedef struct rabbitmq_conn_params_t
589 589 #define __TSL_AIPLATFORM_PARAM__
590 590 typedef struct tsl_aiplatform_param {
591 591 int gpuid; //指定显卡id
  592 + int sip_server_port; // sip服务端端口
592 593 char *trt_serialize_file; //缓存文件保存路径
593 594 char *models_dir; // 模型文件目录
594 595  
... ...
src/decoder/dvpp/DvppDecoder.cpp
... ... @@ -484,7 +484,11 @@ void DvppDecoder::read_thread() {
484 484  
485 485 do {
486 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 493 vdecChannelDesc = aclvdecCreateChannelDesc();
490 494 if (vdecChannelDesc == nullptr) {
... ... @@ -528,6 +532,8 @@ void DvppDecoder::read_thread() {
528 532 }
529 533 }
530 534  
  535 + // LOG_DEBUG("[{}]- read in", m_dec_name);
  536 +
531 537 int result = av_read_frame(fmt_ctx, pkt);
532 538 if (result == AVERROR_EOF || result < 0){
533 539 av_packet_unref(pkt);
... ... @@ -535,6 +541,8 @@ void DvppDecoder::read_thread() {
535 541 break;
536 542 }
537 543  
  544 + // LOG_DEBUG("[{}]- read out", m_dec_name);
  545 +
538 546 if (m_bReal && m_DvppCacheCounter.load() > 20){
539 547 // 解码器解码不过来。实时流在此处的处理会导致花屏,这是由于解码器性能问题导致,无法避免
540 548 // 实时流在这里处理是为了避免长时间不读取数据导致数据中断
... ... @@ -549,6 +557,8 @@ void DvppDecoder::read_thread() {
549 557  
550 558 if (video_index == pkt->stream_index){
551 559  
  560 + LOG_DEBUG("[{}]- av_bsf_send_packet", m_dec_name);
  561 +
552 562 ret = av_bsf_send_packet(h264bsfc, pkt);
553 563 if(ret < 0) {
554 564 LOG_ERROR("[{}]- av_bsf_send_packet error!", m_dec_name);
... ... @@ -565,7 +575,7 @@ void DvppDecoder::read_thread() {
565 575  
566 576 frame_nb++;
567 577 #ifdef USE_VILLAGE
568   - m_recoderManager.cache_pkt(pkt, frame_nb);
  578 + m_recoderManager.cache_pkt(pkt, frame_nb, m_dec_name);
569 579 #endif
570 580 nSended = sendPkt(vdecChannelDesc, pkt, frame_nb);
571 581  
... ... @@ -595,25 +605,31 @@ void DvppDecoder::read_thread() {
595 605  
596 606 } while (0);
597 607  
  608 + LOG_DEBUG("[{}]- 1", m_dec_name);
  609 +
598 610 if (vdecChannelDesc) {
599 611 CHECK_NOT_RETURN(aclvdecDestroyChannel(vdecChannelDesc), "aclvdecDestroyChannel failed");
600 612 CHECK_NOT_RETURN(aclvdecDestroyChannelDesc(vdecChannelDesc), "aclvdecDestroyChannelDesc failed");
601 613 vdecChannelDesc = nullptr;
602 614 }
603 615  
  616 + LOG_DEBUG("[{}]- 2", m_dec_name);
  617 +
604 618 m_bRunning=false;
605 619  
606 620 m_bExitReportThd = true;
607 621 CHECK_NOT_RETURN(pthread_join(report_thread, nullptr), "report_thread join failed");
608 622  
  623 + LOG_DEBUG("[{}]- 3", m_dec_name);
  624 +
609 625 m_bExitDisplayThd = true;
610 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 630 m_recoderManager.close();
  631 +
  632 + LOG_DEBUG("[{}]- 5", m_dec_name);
617 633  
618 634 release_ffmpeg();
619 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 401 return -3;
402 402 }
403 403  
404   - int ret = aclrtSetCurrentContext(m_context);
  404 + int ret = aclrtSetCurrentContext(m_context);
405 405 if(ret != ACL_ERROR_NONE){
406 406 LOG_ERROR("[{}]- aclrtSetCurrentContext failed", m_dec_name);
407 407 return -2;
... ... @@ -480,7 +480,7 @@ int DvppStreamDecoder::SendData(int videoType, char* data, int len, int isKey, u
480 480 m_frame_nb++;
481 481  
482 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 484 #endif
485 485  
486 486 // dvpp 解码
... ... @@ -636,8 +636,16 @@ void DvppStreamDecoder::release_channeldesc() {
636 636 void DvppStreamDecoder::Close() {
637 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 650 if(h264bsfc){
643 651 av_bsf_free(&h264bsfc);
... ... @@ -648,6 +656,7 @@ void DvppStreamDecoder::Close() {
648 656  
649 657 if(decode_finished_cbk) {
650 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 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 47 bool FFRecoderTaskManager::init2(int w, int h, int fps, int bit_rate) {
71 48 m_width = w;
72 49 m_height = h;
... ... @@ -108,7 +85,7 @@ static AVPacket* packet_clone(AVPacket* pkt) {
108 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 89 if(m_bExit) {
113 90 // 任务退出了就不再缓存数据了
114 91 return;
... ... @@ -126,10 +103,17 @@ void FFRecoderTaskManager::cache_pkt(AVPacket* pkt, long long frame_nb){
126 103 if(is_key_frame(pkt)){
127 104 // 越来越大的值
128 105 newDataPkt->isKeyFrame = true;
129   - LOG_INFO("key frame_nb: {}", frame_nb);
  106 + LOG_INFO("[{}] - key frame_nb: {}", dec_name, frame_nb);
130 107 } else {
131 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 118 std::lock_guard<std::mutex> l_info(m_pkt_list_short_mtx);
135 119 m_pkt_list_short.push_back(newDataPkt);
... ... @@ -154,7 +138,6 @@ void FFRecoderTaskManager::save_intask_recoderinfo(RecoderInfo info) {
154 138 }
155 139  
156 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 142 auto it_first = m_pkt_list.begin();
160 143  
... ... @@ -185,101 +168,6 @@ void FFRecoderTaskManager::create_recode_task(RecoderInfo&amp; recoderInfo) {
185 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 171 void FFRecoderTaskManager::pkt_cache_thread() {
284 172 LOG_INFO("pkt_cache_thread start...");
285 173  
... ... @@ -311,7 +199,6 @@ void FFRecoderTaskManager::pkt_cache_thread() {
311 199 }
312 200 m_pkt_list_mtx.unlock();
313 201 m_pkt_list_short_mtx.unlock();
314   -
315 202  
316 203 std::lock_guard<std::mutex> l_info(m_recoderinfo_list_mtx);
317 204 if(m_recoderinfo_list.size() <= 0){
... ... @@ -366,15 +253,25 @@ void FFRecoderTaskManager::recode_thread2() {
366 253  
367 254 do
368 255 {
  256 + std::lock_guard<std::mutex> l_long(m_pkt_list_mtx);
  257 +
369 258 auto it_data = getStartIterator(recoderinfo.frame_nb);
370 259 if(it_data == m_pkt_list.end()) {
  260 + LOG_WARN("待保存信息已无相关数据包");
371 261 std::this_thread::sleep_for(std::chrono::milliseconds(3));
372 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 276 string file_name = recoderinfo.recoderPath;
380 277  
... ...
src/decoder/dvpp/FFRecoderTaskManager.h
1   -#include "FFRecoder.h"
2 1 #include "FFRecoder2.h"
3 2  
4 3 #include "../../ai_platform/common_header.h"
... ... @@ -26,9 +25,8 @@ public:
26 25 FFRecoderTaskManager();
27 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 30 bool init2(int w, int h, int fps, int bit_rate);
33 31 void create_recode_task(RecoderInfo& recoderInfo);
34 32  
... ... @@ -37,7 +35,6 @@ public:
37 35 void set_mq_callback(mq_callback_t cb);
38 36  
39 37 public:
40   - void recode_thread();
41 38 void recode_thread2();
42 39 void pkt_cache_thread();
43 40  
... ...
src/decoder/dvpp/depend_headers.h
... ... @@ -46,6 +46,7 @@ struct DataPacket {
46 46  
47 47 ~DataPacket(){
48 48 if(pkt != nullptr) {
  49 + // LOG_INFO("free frame_nb:{}", frame_nb);
49 50 av_packet_free(&pkt);
50 51 pkt = nullptr;
51 52 }
... ...
src/decoder/gb28181/DvppGB28181Decoder.cpp
... ... @@ -56,7 +56,8 @@ DvppGB28181Decoder::~DvppGB28181Decoder()
56 56 }
57 57  
58 58 void DvppGB28181Decoder::close(){
59   - if (m_status == ECLOSED || m_status == ECLOSING) return ;
  59 +
  60 + if (m_status == ECLOSED) return;
60 61  
61 62 m_status = ECLOSING;
62 63  
... ... @@ -76,6 +77,7 @@ void DvppGB28181Decoder::close(){
76 77  
77 78 if (m_post_decode_thread != 0) {
78 79 pthread_join(m_post_decode_thread,0);
  80 + m_post_decode_thread = 0;
79 81 }
80 82  
81 83 streamDecoder.Close();
... ... @@ -304,6 +306,8 @@ void DvppGB28181Decoder::stream_end_callback()
304 306 {
305 307 LOG_INFO("[{}] - send_video_eof", m_dec_name);
306 308  
  309 + m_status == ECLOSING;
  310 +
307 311 decode_finished_cbk(m_finishedDecArg);
308 312  
309 313 return;
... ...
src/decoder/gb28181/common_header.h
... ... @@ -4,5 +4,6 @@
4 4  
5 5 #include "../interface/logger.hpp"
6 6 #include "../interface/utiltools.hpp"
  7 +#include "../../util/StringTools.hpp"
7 8  
8 9 #endif
9 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 0 \ No newline at end of file
src/decoder/gb28181/rtp/RTPReceiver.cpp
... ... @@ -3,7 +3,7 @@
3 3 #include <thread>
4 4  
5 5 #include "../common_header.h"
6   -#include "../sip/SipServer.h"
  6 +#include "../websocket/WebsocketClient.h"
7 7  
8 8 #ifdef __linux__
9 9 #include "arpa/inet.h"
... ... @@ -52,6 +52,11 @@ RTPReceiver::~RTPReceiver(){
52 52 if(recvTmpBuf != nullptr){
53 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 62 void RTPReceiver::SetOutputCallback(CallBack_Stream cb, void* param)
... ... @@ -79,7 +84,7 @@ int RTPReceiver::InitPS(){
79 84 return -1;
80 85 }
81 86  
82   - LOG_INFO("[{}] InitPS finished", m_SipChannelId);
  87 + LOG_INFO("[{}] InitPS successed", m_SipChannelId);
83 88  
84 89 return 0;
85 90 }
... ... @@ -310,7 +315,7 @@ int RTPReceiver::ParsePacket(RTPPacket* packet){
310 315  
311 316 int RTPReceiver::allocRtpPort() {
312 317  
313   - SipServer* pServer = SipServer::getInstance();
  318 + WebsocketClient* pServer = WebsocketClient::getInstance();
314 319 int MIN_RTP_PORT = pServer->GetMinRtpPort() ;
315 320 int MAX_RTP_PORT = pServer->GetMaxRtpPort();
316 321  
... ... @@ -330,7 +335,7 @@ int RTPReceiver::allocRtpPort() {
330 335 s_rtpPort = MIN_RTP_PORT;
331 336 count ++;
332 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 367 }
363 368  
364 369 return s_rtpPort;
  370 +}
  371 +
  372 +void RTPReceiver::RequestStreamFailed() {
  373 + m_bRtpExit = true;
365 374 }
366 375 \ No newline at end of file
... ...
src/decoder/gb28181/rtp/RTPReceiver.h
... ... @@ -90,6 +90,7 @@ public:
90 90 virtual bool Open(string channel_id) = 0;
91 91 virtual bool IsOpened() = 0;
92 92 virtual void Close() = 0;
  93 + virtual bool RequestStream() = 0;
93 94  
94 95 void SetVodEndCallback(CallBack_VodFileEnd cb, void* param);
95 96  
... ... @@ -101,6 +102,8 @@ public:
101 102  
102 103 int allocRtpPort();
103 104  
  105 + void RequestStreamFailed();
  106 +
104 107 public:
105 108 void OnPsDemux(unsigned char streamId, BYTE *data, int len, bool key, uint64_t pts, uint64_t localPts);
106 109 int OnPsProcess();
... ... @@ -130,7 +133,8 @@ public:
130 133 int m_rtp_port{-1};
131 134  
132 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 139 uint32_t lastPts{0};
136 140 uint64_t last_recv_ts{0};
... ... @@ -138,7 +142,7 @@ public:
138 142 int mark{0};
139 143 BYTE* recvTmpBuf{nullptr};
140 144  
141   - std::thread* m_psThreadPtr; // PS解包线程
  145 + std::thread* m_psThreadPtr{nullptr}; // PS解包线程
142 146  
143 147 CallBack_VodFileEnd m_hVodEndFunc; // 录像流结束回调
144 148 CallBack_Request_Stream m_callback_request_stream; //请求流回调
... ...
src/decoder/gb28181/rtp/RTPTcpReceiver.cpp
1 1 #include"RTPTcpReceiver.h"
2 2  
3 3 #include "../common_header.h"
4   -#include "../sip/SipServer.h"
  4 +#include "../websocket/WebsocketClient.h"
5 5  
6 6  
7 7 // class TcpRTPSession : public RTPSession
... ... @@ -96,14 +96,14 @@ static int listen_finish_thread_(void* param)
96 96 }
97 97  
98 98 RTPTcpReceiver::RTPTcpReceiver()
99   -: m_bRtpExit(false)
100   -, m_bOpened(false)
  99 +: m_bOpened(false)
101 100 , m_idleCount(-1)
102 101 , m_noDataCount(-1)
103 102 , m_nListener(-1)
104 103 , m_bAccepted(false)
105 104 , m_bClosing(false)
106 105 {
  106 + m_bRtpExit = false;
107 107 m_rtpSessionPtr = new RTPSession();
108 108 m_pSessparams = new RTPSessionParams();
109 109 m_pTrans = new MyTCPTransmitter();
... ... @@ -132,13 +132,11 @@ RTPTcpReceiver::~RTPTcpReceiver(){
132 132 bool RTPTcpReceiver::Open(string channel_id){
133 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 137 return false;
138 138 }
139 139  
140   - m_rtp_port = rtpPort;
141   -
142 140 if(0 != initSession(m_rtp_port)){
143 141 return false;
144 142 }
... ... @@ -158,6 +156,11 @@ bool RTPTcpReceiver::IsOpened(){
158 156 void RTPTcpReceiver::Close(){
159 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 164 if(m_listenFinishThread.joinable()){
162 165 m_listenFinishThread.join();
163 166 }
... ... @@ -370,11 +373,12 @@ bool RTPTcpReceiver::ReConnect(){
370 373 }
371 374  
372 375 bool RTPTcpReceiver::RequestStream(){
373   - SipServer* pServer = SipServer::getInstance();
374   - int ret = -1;
  376 + WebsocketClient* pServer = WebsocketClient::getInstance();
375 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 385 \ No newline at end of file
... ...
src/decoder/gb28181/rtp/RTPTcpReceiver.h
... ... @@ -26,17 +26,6 @@
26 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 29 using namespace jrtplib;
41 30 using namespace std;
42 31  
... ... @@ -51,15 +40,15 @@ public:
51 40 RTPTcpReceiver();
52 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 48 public:
59 49 int OnRtpRecv();
60 50 bool ReConnect();
61 51 int ListenFinish();
62   - bool RequestStream();
63 52 bool isClosing();
64 53  
65 54 private:
... ... @@ -67,9 +56,6 @@ private:
67 56 void close_task();
68 57  
69 58 private:
70   -
71   - std::atomic_bool m_bRtpExit; // 标识RTP收包线程闭
72   -
73 59 std::atomic_bool m_bOpened;
74 60 std::atomic_bool m_bAccepted;
75 61 std::atomic_bool m_bClosing;
... ...
src/decoder/gb28181/rtp/RTPUdpReceiver.cpp
... ... @@ -7,7 +7,7 @@
7 7 #include <chrono>
8 8  
9 9 #include "../common_header.h"
10   -#include "../sip/SipServer.h"
  10 +#include "../websocket/WebsocketClient.h"
11 11  
12 12  
13 13 using namespace std;
... ... @@ -55,12 +55,22 @@ static int rtp_revc_thread_(void* param)
55 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 68 RTPUdpReceiver::RTPUdpReceiver()
59   -: m_bRtpExit(false)
60   -, m_bOpened(false)
  69 +:m_bOpened(false)
61 70 , m_idleCount(-1)
62 71 ,m_noDataCount(-1)
63 72 {
  73 + m_bRtpExit = false;
64 74 m_sessparamsPtr = new RTPSessionParams();
65 75 m_transparamsPtr = new RTPUDPv4TransmissionParams();
66 76 m_rtpSessionPtr = new UdpRTPSession();
... ... @@ -68,8 +78,7 @@ RTPUdpReceiver::RTPUdpReceiver()
68 78  
69 79 RTPUdpReceiver::~RTPUdpReceiver()
70 80 {
71   - if (IsOpened())
72   - Close();
  81 + m_bRtpExit = true;
73 82  
74 83 if(nullptr != m_sessparamsPtr){
75 84 delete m_sessparamsPtr;
... ... @@ -81,6 +90,12 @@ RTPUdpReceiver::~RTPUdpReceiver()
81 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 99 if(nullptr != m_rtpSessionPtr){
85 100 delete m_rtpSessionPtr;
86 101 m_rtpSessionPtr = nullptr;
... ... @@ -91,11 +106,10 @@ bool RTPUdpReceiver::Open(string channel_id)
91 106 {
92 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 111 return false;
97 112 }
98   - m_rtp_port = rtpPort;
99 113  
100 114 m_sessparamsPtr->SetUsePollThread(true);
101 115 m_sessparamsPtr->SetMinimumRTCPTransmissionInterval(10);
... ... @@ -123,29 +137,27 @@ bool RTPUdpReceiver::Open(string channel_id)
123 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 147 bool bReq = RequestStream();
127 148 if (!bReq) {
128 149 LOG_INFO("[{}] RequestStream failed !", m_SipChannelId);
129 150 Close();
130 151 return false;
131 152 }
132   -
  153 +
133 154 m_bOpened = true;
  155 + m_bNoData = false;
134 156 LOG_INFO("[{}] Open ok", m_SipChannelId);
135 157  
136 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 161 bool RTPUdpReceiver::IsOpened()
150 162 {
151 163 return m_bOpened;
... ... @@ -154,21 +166,6 @@ bool RTPUdpReceiver::IsOpened()
154 166 void RTPUdpReceiver::Close()
155 167 {
156 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 171 // 收RTP包线程
... ... @@ -197,6 +194,7 @@ int RTPUdpReceiver::OnRtpRecv()
197 194 RTPPacket* packet;
198 195 while ((packet = m_rtpSessionPtr->GetNextPacket()) != NULL)
199 196 {
  197 + m_bNoData = false;
200 198 // LOG_INFO("OnRtpRecv GetNextPacket --{}", m_SipChannelId);
201 199 int ret = ParsePacket(packet);
202 200 m_rtpSessionPtr->DeletePacket(packet);
... ... @@ -342,4 +340,87 @@ int RTPUdpReceiver::OnRtpRecv()
342 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 427 \ No newline at end of file
... ...
src/decoder/gb28181/rtp/RTPUdpReceiver.h
... ... @@ -14,17 +14,6 @@
14 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 17 using namespace jrtplib;
29 18 using namespace std;
30 19  
... ... @@ -40,28 +29,33 @@ public:
40 29 virtual bool Open(string channel_id);
41 30 virtual bool IsOpened() ;
42 31 virtual void Close() ;
43   -
44   - bool RequestStream();
  32 + virtual bool RequestStream();
45 33  
46 34 public:
47 35 int OnRtpRecv();
  36 + int IsConnecting();
48 37  
49 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 48 std::atomic_bool m_bOpened;
57 49  
58 50 int64_t m_idleCount;
59 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 56 string m_sip_channel_id;
  57 +
  58 + std::atomic_bool m_bNoData{false};
65 59 };
66 60  
67 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 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 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 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 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 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 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 3 #include <thread>
4 4 #include <chrono>
5 5 #include "../common/logger.hpp"
6   -#include "./gb28181/sip/SipServer.h"
7 6  
8 7 using namespace std;
9 8  
... ... @@ -142,10 +141,6 @@ int main(){
142 141  
143 142 printf("start... \n");
144 143  
145   - SipServer* pSipServer = SipServer::getInstance();
146   - pSipServer->Init(nullptr);
147   -
148   -
149 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 914  
915 915 switch(gi){
916 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 918 break;
919 919 case 1:
920 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 1059 }
1060 1060 delete[] tparam.algor_config_params;
1061 1061  
1062   -
1063   -
1064 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 1076 case 2:
1079 1077 tparam.ipc_url = "34020000001310000201";
1080 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 1088 default:
1082 1089 tparam.ipc_url = "34020000001310004065";
1083 1090 break;
... ... @@ -1280,6 +1287,7 @@ void test_gpu(int gpuID){
1280 1287 void test_dvpp28181(int gpuID) {
1281 1288 tsl_aiplatform_param vptParam;
1282 1289 vptParam.gpuid = gpuID;
  1290 + vptParam.sip_server_port = 15080;
1283 1291 vptParam.trt_serialize_file = "";
1284 1292 vptParam.models_dir = ".";
1285 1293  
... ... @@ -1334,6 +1342,21 @@ while (ch != &#39;q&#39;) {
1334 1342 case '2':
1335 1343 createTask_dvpp28181(handle, algor_vec, 2, false);
1336 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 1360 case 'c':
1338 1361 close_all_task(handle);
1339 1362 break;
... ...
src/tsl_aiplatform_jni/AiEngineNativeInterface.cpp
... ... @@ -53,6 +53,7 @@ JNIEXPORT jint JNICALL Java_com_objecteye_nativeinterface_TSLAiEngineNativeInter
53 53 // getFieldID
54 54 jclass cls_aiEngineParam = env->GetObjectClass(aiEngineParam);
55 55 jfieldID fid_aiEngineParam_gpuid = env->GetFieldID(cls_aiEngineParam, "gpuID", "I");
  56 + jfieldID fid_aiEngineParam_sipServerPort = env->GetFieldID(cls_aiEngineParam, "sipServerPort", "I");
56 57 jfieldID fid_aiEngineParam_trtSerializeFileFolder = env->GetFieldID(cls_aiEngineParam, "trtSerializeFileFolder", "Ljava/lang/String;");
57 58 jfieldID fid_aiEngineParam_modelsDir = env->GetFieldID(cls_aiEngineParam, "modelsDir", "Ljava/lang/String;");
58 59 jfieldID fid_aiEngineParam_logLevel = env->GetFieldID(cls_aiEngineParam, "logLevel", "I");
... ... @@ -63,6 +64,7 @@ JNIEXPORT jint JNICALL Java_com_objecteye_nativeinterface_TSLAiEngineNativeInter
63 64  
64 65 // getObjectField
65 66 jint aiEngineParam_gpuid = env->GetIntField(aiEngineParam, fid_aiEngineParam_gpuid);
  67 + jint aiEngineParam_sipServerPort = env->GetIntField(aiEngineParam, fid_aiEngineParam_sipServerPort);
66 68 jstring str_aiEngineParam_trtSerializeFileFolder =
67 69 (jstring)env->GetObjectField(aiEngineParam, fid_aiEngineParam_trtSerializeFileFolder);
68 70 const char *aiEngineParam_trtSerializeFileFolder =
... ... @@ -85,6 +87,7 @@ JNIEXPORT jint JNICALL Java_com_objecteye_nativeinterface_TSLAiEngineNativeInter
85 87  
86 88 tsl_aiplatform_param mAiEngineParam;
87 89 mAiEngineParam.gpuid = aiEngineParam_gpuid;
  90 + mAiEngineParam.sip_server_port= aiEngineParam_sipServerPort;
88 91 mAiEngineParam.trt_serialize_file = (char *)aiEngineParam_trtSerializeFileFolder;
89 92 mAiEngineParam.models_dir = (char *)aiEngineParam_modelsDir;
90 93  
... ... @@ -94,6 +97,7 @@ JNIEXPORT jint JNICALL Java_com_objecteye_nativeinterface_TSLAiEngineNativeInter
94 97 mAiEngineParam.log_mem = aiEngineParam_logMem;
95 98  
96 99 printf("-- *************** Summary **********************.\n");
  100 + printf("-- sip server port:%d \n", (int)aiEngineParam_sipServerPort);
97 101 printf("-- [logger]\n");
98 102 printf("-- level :%d(int)\n", (int)aiEngineParam_logLevel);
99 103 printf("-- path :%s(str)\n", (char *)aiEngineParam_logPath);
... ...
src/tsl_aiplatform_jni/Makefile
... ... @@ -6,7 +6,7 @@ AR = ar
6 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 11 DEPEND_DIR = $(PROJECT_ROOT)/bin
12 12 SRC_ROOT = $(PROJECT_ROOT)/src/tsl_aiplatform_jni
... ...