Commit 5b86d7710ad0db2b70cdc9bc75123f657949122b

Authored by Hu Chunming
1 parent 74d1e6a8

实现GB28181 UDP 基于dvpp的解码

build/decoder/Makefile
@@ -6,7 +6,7 @@ PROJECT_ROOT= /home/cmhu/vpt_ascend_arm @@ -6,7 +6,7 @@ PROJECT_ROOT= /home/cmhu/vpt_ascend_arm
6 DEPEND_DIR = $(PROJECT_ROOT)/bin 6 DEPEND_DIR = $(PROJECT_ROOT)/bin
7 SRC_ROOT = $(PROJECT_ROOT)/src 7 SRC_ROOT = $(PROJECT_ROOT)/src
8 8
9 -TARGET= $(PROJECT_ROOT)/bin/test_dec 9 +TARGET= $(PROJECT_ROOT)/bin/test_28181
10 10
11 THIRDPARTY_ROOT = $(PROJECT_ROOT)/3rdparty 11 THIRDPARTY_ROOT = $(PROJECT_ROOT)/3rdparty
12 SPDLOG_ROOT = $(THIRDPARTY_ROOT)/spdlog-1.9.2/release 12 SPDLOG_ROOT = $(THIRDPARTY_ROOT)/spdlog-1.9.2/release
@@ -14,7 +14,11 @@ OPENCV_ROOT = $(THIRDPARTY_ROOT)/opencv_4_1 @@ -14,7 +14,11 @@ OPENCV_ROOT = $(THIRDPARTY_ROOT)/opencv_4_1
14 JSON_ROOT = $(THIRDPARTY_ROOT)/jsoncpp-1.9.5/release 14 JSON_ROOT = $(THIRDPARTY_ROOT)/jsoncpp-1.9.5/release
15 FFMPEG_ROOT = $(THIRDPARTY_ROOT)/ffmpeg-4.4.4/release 15 FFMPEG_ROOT = $(THIRDPARTY_ROOT)/ffmpeg-4.4.4/release
16 16
17 -DEFS = -DENABLE_DVPP_INTERFACE 17 +GB28181_SDK = /home/cmhu/vpt_ascend_arm/3rdparty/gb28181_3rd
  18 +JRTP_ROOT = $(GB28181_SDK)/jrtp_export
  19 +SIP_SDK = $(GB28181_SDK)/release
  20 +
  21 +DEFS = -DENABLE_DVPP_INTERFACE -DUSE_DVPP
18 22
19 include_dir=-I/usr/local/Ascend/ascend-toolkit/6.3.RC1/aarch64-linux/include \ 23 include_dir=-I/usr/local/Ascend/ascend-toolkit/6.3.RC1/aarch64-linux/include \
20 -I $(SPDLOG_ROOT)/include \ 24 -I $(SPDLOG_ROOT)/include \
@@ -22,6 +26,11 @@ include_dir=-I/usr/local/Ascend/ascend-toolkit/6.3.RC1/aarch64-linux/include \ @@ -22,6 +26,11 @@ include_dir=-I/usr/local/Ascend/ascend-toolkit/6.3.RC1/aarch64-linux/include \
22 -I $(OPENCV_ROOT)/include \ 26 -I $(OPENCV_ROOT)/include \
23 -I $(JSON_ROOT)/include \ 27 -I $(JSON_ROOT)/include \
24 -I $(FFMPEG_ROOT)/include \ 28 -I $(FFMPEG_ROOT)/include \
  29 + -I $(JRTP_ROOT)/jrtplib/include/jrtplib3 \
  30 + -I $(SIP_SDK)/include \
  31 + -I $(SRC_ROOT)/decoder/gb28181/rtp \
  32 + -I $(SRC_ROOT)/decoder/gb28181/sip \
  33 + -I $(SRC_ROOT)/decoder/gb28181 \
25 34
26 lib_dir=-L/usr/local/Ascend/ascend-toolkit/6.3.RC1/runtime/lib64 \ 35 lib_dir=-L/usr/local/Ascend/ascend-toolkit/6.3.RC1/runtime/lib64 \
27 -L/usr/local/Ascend/ascend-toolkit/latest/lib64 \ 36 -L/usr/local/Ascend/ascend-toolkit/latest/lib64 \
@@ -33,13 +42,21 @@ lib=-lacl_dvpp -lascendcl -lacl_dvpp_mpi -lruntime -lascendalog -lc_sec -lmsprof @@ -33,13 +42,21 @@ lib=-lacl_dvpp -lascendcl -lacl_dvpp_mpi -lruntime -lascendalog -lc_sec -lmsprof
33 -lplatform -lqos_manager 42 -lplatform -lqos_manager
34 43
35 LIBS= -L $(FFMPEG_ROOT)/lib -lavformat -lavcodec -lswscale -lavutil -lavfilter -lswresample -lavdevice \ 44 LIBS= -L $(FFMPEG_ROOT)/lib -lavformat -lavcodec -lswscale -lavutil -lavfilter -lswresample -lavdevice \
  45 + -L $(JRTP_ROOT)/jrtplib/lib -l:libjrtp.a \
  46 + -L $(SIP_SDK)/lib -l:libeXosip2.a -l:libosipparser2.a -l:libosip2.a -lcares\
36 47
37 CXXFLAGS= -g -O0 -fPIC $(include_dir) $(lib_dir) $(lib) $(LIBS) $(DEFS) -lpthread -lrt -lz -fexceptions -std=c++11 -D_GLIBCXX_USE_CXX11_ABI=0 -fvisibility=hidden -Wall -Wno-deprecated -Wdeprecated-declarations -Wl,-Bsymbolic -ldl 48 CXXFLAGS= -g -O0 -fPIC $(include_dir) $(lib_dir) $(lib) $(LIBS) $(DEFS) -lpthread -lrt -lz -fexceptions -std=c++11 -D_GLIBCXX_USE_CXX11_ABI=0 -fvisibility=hidden -Wall -Wno-deprecated -Wdeprecated-declarations -Wl,-Bsymbolic -ldl
38 49
39 50
40 51
41 SRCS:=$(wildcard $(SRC_ROOT)/decoder/interface/*.cpp) \ 52 SRCS:=$(wildcard $(SRC_ROOT)/decoder/interface/*.cpp) \
42 - $(wildcard $(SRC_ROOT)/decoder/dvpp/*.cpp) \ 53 + $(wildcard $(SRC_ROOT)/decoder/dvpp/*.cpp) \
  54 + $(wildcard $(SRC_ROOT)/decoder/gb28181/*.cpp) \
  55 + $(wildcard $(SRC_ROOT)/decoder/gb28181/rtp/*.cpp) \
  56 + $(wildcard $(SRC_ROOT)/decoder/gb28181/sip/*.cpp) \
  57 + $(wildcard $(SRC_ROOT)/decoder/gb28181/sip/Message/*.cpp) \
  58 + $(wildcard $(SRC_ROOT)/decoder/gb28181/sip/tinyxml2/*.cpp) \
  59 + $(wildcard $(SRC_ROOT)/decoder/gb28181/sip/Utils/*.cpp) \
43 $(wildcard $(SRC_ROOT)/decoder/*.cpp) \ 60 $(wildcard $(SRC_ROOT)/decoder/*.cpp) \
44 61
45 OBJS = $(patsubst %.cpp, %.o, $(notdir $(SRCS))) 62 OBJS = $(patsubst %.cpp, %.o, $(notdir $(SRCS)))
@@ -53,6 +70,24 @@ $(TARGET):$(OBJS) @@ -53,6 +70,24 @@ $(TARGET):$(OBJS)
53 %.o:$(SRC_ROOT)/decoder/dvpp/%.cpp 70 %.o:$(SRC_ROOT)/decoder/dvpp/%.cpp
54 $(XX) $(CXXFLAGS) -c $< 71 $(XX) $(CXXFLAGS) -c $<
55 72
  73 +%.o:$(SRC_ROOT)/decoder/gb28181/%.cpp
  74 + $(XX) $(CXXFLAGS) -c $<
  75 +
  76 +%.o:$(SRC_ROOT)/decoder/gb28181/rtp/%.cpp
  77 + $(XX) $(CXXFLAGS) -c $<
  78 +
  79 +%.o:$(SRC_ROOT)/decoder/gb28181/sip/%.cpp
  80 + $(XX) $(CXXFLAGS) -c $<
  81 +
  82 +%.o:$(SRC_ROOT)/decoder/gb28181/sip/Message/%.cpp
  83 + $(XX) $(CXXFLAGS) -c $<
  84 +
  85 +%.o:$(SRC_ROOT)/decoder/gb28181/sip/tinyxml2/%.cpp
  86 + $(XX) $(CXXFLAGS) -c $<
  87 +
  88 +%.o:$(SRC_ROOT)/decoder/gb28181/sip/Utils/%.cpp
  89 + $(XX) $(CXXFLAGS) -c $<
  90 +
56 %.o:$(SRC_ROOT)/decoder/interface/%.cpp 91 %.o:$(SRC_ROOT)/decoder/interface/%.cpp
57 $(XX) $(CXXFLAGS) -c $< 92 $(XX) $(CXXFLAGS) -c $<
58 93
build/decoder/Makefile.dvpp 0 → 100644
  1 +XX = g++
  2 +
  3 +
  4 +PROJECT_ROOT= /home/cmhu/vpt_ascend_arm
  5 +
  6 +DEPEND_DIR = $(PROJECT_ROOT)/bin
  7 +SRC_ROOT = $(PROJECT_ROOT)/src
  8 +
  9 +TARGET= $(PROJECT_ROOT)/bin/test_dec
  10 +
  11 +THIRDPARTY_ROOT = $(PROJECT_ROOT)/3rdparty
  12 +SPDLOG_ROOT = $(THIRDPARTY_ROOT)/spdlog-1.9.2/release
  13 +OPENCV_ROOT = $(THIRDPARTY_ROOT)/opencv_4_1
  14 +JSON_ROOT = $(THIRDPARTY_ROOT)/jsoncpp-1.9.5/release
  15 +FFMPEG_ROOT = $(THIRDPARTY_ROOT)/ffmpeg-4.4.4/release
  16 +
  17 +DEFS = -DENABLE_DVPP_INTERFACE
  18 +
  19 +include_dir=-I/usr/local/Ascend/ascend-toolkit/6.3.RC1/aarch64-linux/include \
  20 + -I $(SPDLOG_ROOT)/include \
  21 + -I $(SRC_ROOT)/common \
  22 + -I $(OPENCV_ROOT)/include \
  23 + -I $(JSON_ROOT)/include \
  24 + -I $(FFMPEG_ROOT)/include \
  25 +
  26 +lib_dir=-L/usr/local/Ascend/ascend-toolkit/6.3.RC1/runtime/lib64 \
  27 + -L/usr/local/Ascend/ascend-toolkit/latest/lib64 \
  28 + -L/usr/local/Ascend/ascend-toolkit/latest/runtime/lib64 \
  29 + -L/usr/local/Ascend/ascend-toolkit/latest/acllib/lib64 \
  30 + -L/usr/local/Ascend/ascend-toolkit/6.3.RC1/runtime/lib64/stub \
  31 +
  32 +lib=-lacl_dvpp -lascendcl -lacl_dvpp_mpi -lruntime -lascendalog -lc_sec -lmsprofiler -lgert -lmmpa -lascend_hal -lexe_graph -lge_executor -lgraph -lprofapi -lascend_protobuf -lerror_manager -lregister -lge_common \
  33 + -lplatform -lqos_manager
  34 +
  35 +LIBS= -L $(FFMPEG_ROOT)/lib -lavformat -lavcodec -lswscale -lavutil -lavfilter -lswresample -lavdevice \
  36 +
  37 +CXXFLAGS= -g -O0 -fPIC $(include_dir) $(lib_dir) $(lib) $(LIBS) $(DEFS) -lpthread -lrt -lz -fexceptions -std=c++11 -D_GLIBCXX_USE_CXX11_ABI=0 -fvisibility=hidden -Wall -Wno-deprecated -Wdeprecated-declarations -Wl,-Bsymbolic -ldl
  38 +
  39 +
  40 +
  41 +SRCS:=$(wildcard $(SRC_ROOT)/decoder/interface/*.cpp) \
  42 + $(wildcard $(SRC_ROOT)/decoder/dvpp/*.cpp) \
  43 + $(wildcard $(SRC_ROOT)/decoder/*.cpp) \
  44 +
  45 +OBJS = $(patsubst %.cpp, %.o, $(notdir $(SRCS)))
  46 +
  47 +
  48 +$(TARGET):$(OBJS)
  49 + rm -f $(TARGET)
  50 + $(XX) -o $@ $^ $(CXXFLAGS)
  51 + rm -f *.o
  52 +
  53 +%.o:$(SRC_ROOT)/decoder/dvpp/%.cpp
  54 + $(XX) $(CXXFLAGS) -c $<
  55 +
  56 +%.o:$(SRC_ROOT)/decoder/interface/%.cpp
  57 + $(XX) $(CXXFLAGS) -c $<
  58 +
  59 +%.o:$(SRC_ROOT)/decoder/%.cpp
  60 + $(XX) $(CXXFLAGS) -c $<
  61 +
  62 +clean:
  63 + rm -f *.o $(TARGET)
build/gb28181/Makefile
@@ -15,8 +15,7 @@ SPDLOG_ROOT = $(THIRDPARTY_ROOT)/spdlog-1.9.2/release @@ -15,8 +15,7 @@ SPDLOG_ROOT = $(THIRDPARTY_ROOT)/spdlog-1.9.2/release
15 15
16 GB28181_ROOT = /home/cmhu/vpt_ascend_arm/3rdparty/gb28181_3rd 16 GB28181_ROOT = /home/cmhu/vpt_ascend_arm/3rdparty/gb28181_3rd
17 JRTP_ROOT = $(GB28181_ROOT)/jrtp_export 17 JRTP_ROOT = $(GB28181_ROOT)/jrtp_export
18 -  
19 -SIP_SDK = /home/cmhu/vpt_ascend_arm/3rdparty/gb28181_3rd/release 18 +SIP_SDK = $(GB28181_ROOT)/release
20 19
21 20
22 SRC_ROOT = /home/cmhu/vpt_ascend_arm/src/decoder/gb28181 21 SRC_ROOT = /home/cmhu/vpt_ascend_arm/src/decoder/gb28181
src/decoder/dvpp/DvppDecoder.cpp
@@ -90,7 +90,7 @@ bool DvppDecoder::init(FFDecConfig cfg){ @@ -90,7 +90,7 @@ bool DvppDecoder::init(FFDecConfig cfg){
90 return false; 90 return false;
91 } 91 }
92 92
93 - bool bRet = init_vdpp(cfg, avctx); 93 + bool bRet = init_dvpp(cfg);
94 if(!bRet){ 94 if(!bRet){
95 return false; 95 return false;
96 } 96 }
@@ -238,7 +238,6 @@ void DvppDecoder::calcOutResolution(int width, int height) { @@ -238,7 +238,6 @@ void DvppDecoder::calcOutResolution(int width, int height) {
238 out_frame_width = width; 238 out_frame_width = width;
239 out_frame_height = height; 239 out_frame_height = height;
240 } 240 }
241 -  
242 } 241 }
243 242
244 int DvppDecoder::getVdecType(int videoType, int profile) 243 int DvppDecoder::getVdecType(int videoType, int profile)
@@ -281,7 +280,7 @@ int DvppDecoder::getVdecType(int videoType, int profile) @@ -281,7 +280,7 @@ int DvppDecoder::getVdecType(int videoType, int profile)
281 return streamFormat; 280 return streamFormat;
282 } 281 }
283 282
284 - bool DvppDecoder::init_vdpp(FFDecConfig cfg) { 283 + bool DvppDecoder::init_dvpp(FFDecConfig cfg) {
285 284
286 LOG_INFO("[{}]- Init device start...", m_dec_name); 285 LOG_INFO("[{}]- Init device start...", m_dec_name);
287 286
src/decoder/dvpp/DvppDecoder.h
@@ -68,7 +68,7 @@ public: @@ -68,7 +68,7 @@ public:
68 68
69 private: 69 private:
70 AVCodecContext* init_FFmpeg(FFDecConfig config); 70 AVCodecContext* init_FFmpeg(FFDecConfig config);
71 - bool init_vdpp(FFDecConfig cfg); 71 + bool init_dvpp(FFDecConfig cfg);
72 void release_ffmpeg(); 72 void release_ffmpeg();
73 void read_thread(); 73 void read_thread();
74 74
src/decoder/dvpp/DvppStreamDecoder.cpp
1 #include "DvppStreamDecoder.h" 1 #include "DvppStreamDecoder.h"
  2 +#include "DvppSourceManager.h"
2 3
3 4
  5 +#define CHECK_AND_RETURN(ret, message) \
  6 + if(ret != 0) {LOG_ERROR("[{}]- {}", m_dec_name, message); return ret;}
  7 +#define CHECK_NOT_RETURN(ret, message) \
  8 + if(ret != 0) {LOG_ERROR("[{}]- {}", m_dec_name, message);}
  9 +#define CHECK_AND_RETURN_NOVALUE(ret, message) \
  10 + if(ret != 0) {LOG_ERROR("[{}]- {}", m_dec_name, message); return;}
  11 +#define CHECK_AND_BREAK(ret, message) \
  12 + if(ret != 0) {LOG_ERROR("[{}]- {}", m_dec_name, message); break;}
  13 +
4 14
5 struct Vdec_CallBack_UserData { 15 struct Vdec_CallBack_UserData {
6 uint64_t frameId; 16 uint64_t frameId;
7 uint64_t frame_nb; 17 uint64_t frame_nb;
8 long startTime; 18 long startTime;
9 long sendTime; 19 long sendTime;
10 - DvppDecoder* self; 20 + DvppStreamDecoder* self;
11 21
12 Vdec_CallBack_UserData() { 22 Vdec_CallBack_UserData() {
13 frameId = 0; 23 frameId = 0;
@@ -44,6 +54,8 @@ DvppStreamDecoder::DvppStreamDecoder(/* args */) @@ -44,6 +54,8 @@ DvppStreamDecoder::DvppStreamDecoder(/* args */)
44 DvppStreamDecoder::~DvppStreamDecoder() 54 DvppStreamDecoder::~DvppStreamDecoder()
45 { 55 {
46 Close(); 56 Close();
  57 +
  58 + LOG_DEBUG("[{}]- ~DvppDecoder() in_count:{} out_count:{}", m_dec_name, m_in_count, m_out_count);
47 } 59 }
48 60
49 bool DvppStreamDecoder::Init(FFDecConfig cfg) { 61 bool DvppStreamDecoder::Init(FFDecConfig cfg) {
@@ -75,6 +87,8 @@ bool DvppStreamDecoder::Init(FFDecConfig cfg) { @@ -75,6 +87,8 @@ bool DvppStreamDecoder::Init(FFDecConfig cfg) {
75 return false; 87 return false;
76 } 88 }
77 89
  90 + m_bResize = cfg.resize;
  91 +
78 m_vpcUtils.init(m_deviceId); 92 m_vpcUtils.init(m_deviceId);
79 93
80 decode_finished_cbk = cfg.decode_finished_cbk; 94 decode_finished_cbk = cfg.decode_finished_cbk;
@@ -89,6 +103,7 @@ bool DvppStreamDecoder::Init(FFDecConfig cfg) { @@ -89,6 +103,7 @@ bool DvppStreamDecoder::Init(FFDecConfig cfg) {
89 } 103 }
90 104
91 void DvppStreamDecoder::release_dvpp(){ 105 void DvppStreamDecoder::release_dvpp(){
  106 +
92 if(m_context){ 107 if(m_context){
93 aclError ret = aclrtDestroyContext(m_context); 108 aclError ret = aclrtDestroyContext(m_context);
94 if(ret != ACL_ERROR_NONE){ 109 if(ret != ACL_ERROR_NONE){
@@ -123,7 +138,7 @@ int DvppStreamDecoder::getVdecType(int videoType) @@ -123,7 +138,7 @@ int DvppStreamDecoder::getVdecType(int videoType)
123 138
124 void DvppStreamDecoder::doProcessReport(){ 139 void DvppStreamDecoder::doProcessReport(){
125 140
126 - aclError ret = aclrtSetDevice(m_dvpp_deviceId); 141 + aclError ret = aclrtSetDevice(m_deviceId);
127 if(ret != ACL_ERROR_NONE){ 142 if(ret != ACL_ERROR_NONE){
128 // cout << "aclrtSetDevice failed" << endl; 143 // cout << "aclrtSetDevice failed" << endl;
129 LOG_ERROR("aclrtSetDevice failed !"); 144 LOG_ERROR("aclrtSetDevice failed !");
@@ -131,7 +146,7 @@ void DvppStreamDecoder::doProcessReport(){ @@ -131,7 +146,7 @@ void DvppStreamDecoder::doProcessReport(){
131 } 146 }
132 147
133 aclrtContext ctx; 148 aclrtContext ctx;
134 - ret = aclrtCreateContext(&ctx, m_dvpp_deviceId); 149 + ret = aclrtCreateContext(&ctx, m_deviceId);
135 if (ret != ACL_ERROR_NONE) { 150 if (ret != ACL_ERROR_NONE) {
136 // cout << "aclrtCreateContext failed " << endl; 151 // cout << "aclrtCreateContext failed " << endl;
137 LOG_ERROR("aclrtCreateContext failed !"); 152 LOG_ERROR("aclrtCreateContext failed !");
@@ -187,20 +202,6 @@ void DvppStreamDecoder::doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicD @@ -187,20 +202,6 @@ void DvppStreamDecoder::doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicD
187 202
188 bool bCached = false; 203 bool bCached = false;
189 if(width > 0 && height > 0 && outputSize > 0){ 204 if(width > 0 && height > 0 && outputSize > 0){
190 -  
191 - if (!m_bReal) {  
192 - while(!m_bExitReportThd) {  
193 - // 非实时流,即为文件情形,因为不存在花屏问题,为保证不丢帧,这里做个循环等待  
194 - m_decoded_data_queue_mtx.lock();  
195 - if(m_decoded_data_queue.size() >= 5){  
196 - m_decoded_data_queue_mtx.unlock();  
197 - std::this_thread::sleep_for(std::chrono::milliseconds(5));  
198 - continue;  
199 - }  
200 - m_decoded_data_queue_mtx.unlock();  
201 - break;  
202 - }  
203 - }  
204 205
205 // cout << m_dec_name << " 解码时间间隔: " << get_cur_time_ms() - last_ts << endl; 206 // cout << m_dec_name << " 解码时间间隔: " << get_cur_time_ms() - last_ts << endl;
206 // last_ts = get_cur_time_ms(); 207 // last_ts = get_cur_time_ms();
@@ -225,18 +226,23 @@ void DvppStreamDecoder::doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicD @@ -225,18 +226,23 @@ void DvppStreamDecoder::doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicD
225 outWidth += 1; 226 outWidth += 1;
226 } 227 }
227 } 228 }
  229 +
  230 + out_frame_width = outWidth;
  231 + out_frame_height = outHeight;
228 232
229 mem = m_vpcUtils.resize(output, outWidth, outHeight); 233 mem = m_vpcUtils.resize(output, outWidth, outHeight);
230 if (mem) { 234 if (mem) {
231 acldvppFree(outputDataDev); 235 acldvppFree(outputDataDev);
232 outputDataDev = nullptr; 236 outputDataDev = nullptr;
233 237
234 - mem->setDeviceId(to_string(m_dvpp_deviceId)); 238 + mem->setDeviceId(to_string(m_deviceId));
235 mem->setId(m_dec_name); 239 mem->setId(m_dec_name);
236 mem->setFrameNb(frame_nb); 240 mem->setFrameNb(frame_nb);
237 } 241 }
238 } else { 242 } else {
239 - mem = new DvppDataMemory(width, width_stride, height, height_stride, outputSize, m_dec_name, to_string(m_dvpp_deviceId), false, frame_nb, (unsigned char *)outputDataDev); 243 + mem = new DvppDataMemory(width, width_stride, height, height_stride, outputSize, m_dec_name, to_string(m_deviceId), false, frame_nb, (unsigned char *)outputDataDev);
  244 + out_frame_width = width;
  245 + out_frame_height = height;
240 } 246 }
241 247
242 if(mem){ 248 if(mem){
@@ -408,22 +414,38 @@ int DvppStreamDecoder::SendData(int videoType, char* data, int len, int isKey, u @@ -408,22 +414,38 @@ int DvppStreamDecoder::SendData(int videoType, char* data, int len, int isKey, u
408 return -2; 414 return -2;
409 } 415 }
410 416
411 - int ret = pthread_create(&report_thread, nullptr, ReportThd, (void *)this);  
412 - if(ret != 0){  
413 - LOG_ERROR("[{}]- pthread_create failed", m_dec_name);  
414 - return -2;  
415 - } 417 + do
  418 + {
  419 + ret = -2;
416 420
417 - acldvppStreamFormat enType = getVdecType(videoType); 421 + ret = pthread_create(&report_thread, nullptr, ReportThd, (void *)this);
  422 + if(ret != 0){
  423 + LOG_ERROR("[{}]- pthread_create failed", m_dec_name);
  424 + break;
  425 + }
  426 +
  427 + int iType = getVdecType(videoType);
  428 + if(-1 == iType) {
  429 + break;
  430 + }
  431 + acldvppStreamFormat enType = static_cast<acldvppStreamFormat>(iType);
  432 +
  433 + // 通道ID在dvpp层面为0~31
  434 + CHECK_AND_BREAK(aclvdecSetChannelDescChannelId(vdecChannelDesc, m_dvpp_channel), "aclvdecSetChannelDescChannelId failed");
  435 + CHECK_AND_BREAK(aclvdecSetChannelDescThreadId(vdecChannelDesc, report_thread), "aclvdecSetChannelDescThreadId failed");
  436 + CHECK_AND_BREAK(aclvdecSetChannelDescCallback(vdecChannelDesc, VdecCallback), "aclvdecSetChannelDescCallback failed");
  437 + CHECK_AND_BREAK(aclvdecSetChannelDescEnType(vdecChannelDesc, enType), "aclvdecSetChannelDescEnType failed");
  438 + CHECK_AND_BREAK(aclvdecSetChannelDescOutPicFormat(vdecChannelDesc, PIXEL_FORMAT_YUV_SEMIPLANAR_420), "aclvdecSetChannelDescOutPicFormat failed");
  439 + CHECK_AND_BREAK(aclvdecCreateChannel(vdecChannelDesc), "aclvdecCreateChannel failed");
  440 +
  441 + ret = 0;
  442 + } while (0);
418 443
419 - // 创建 channel dec结构体  
420 - // 通道ID在dvpp层面为0~31  
421 - CHECK_AND_BREAK(aclvdecSetChannelDescChannelId(vdecChannelDesc, m_dvpp_channel), "aclvdecSetChannelDescChannelId failed");  
422 - CHECK_AND_BREAK(aclvdecSetChannelDescThreadId(vdecChannelDesc, report_thread), "aclvdecSetChannelDescThreadId failed");  
423 - CHECK_AND_BREAK(aclvdecSetChannelDescCallback(vdecChannelDesc, VdecCallback), "aclvdecSetChannelDescCallback failed");  
424 - CHECK_AND_BREAK(aclvdecSetChannelDescEnType(vdecChannelDesc, enType), "aclvdecSetChannelDescEnType failed");  
425 - CHECK_AND_BREAK(aclvdecSetChannelDescOutPicFormat(vdecChannelDesc, PIXEL_FORMAT_YUV_SEMIPLANAR_420), "aclvdecSetChannelDescOutPicFormat failed");  
426 - CHECK_AND_BREAK(aclvdecCreateChannel(vdecChannelDesc), "aclvdecCreateChannel failed"); 444 + if (ret < 0) {
  445 + release_channeldesc();
  446 + LOG_ERROR("[{}]- Set Channel Desc failed", m_dec_name);
  447 + return ret;
  448 + }
427 } 449 }
428 450
429 AVPacket* pkt = av_packet_alloc(); 451 AVPacket* pkt = av_packet_alloc();
@@ -432,8 +454,6 @@ int DvppStreamDecoder::SendData(int videoType, char* data, int len, int isKey, u @@ -432,8 +454,6 @@ int DvppStreamDecoder::SendData(int videoType, char* data, int len, int isKey, u
432 pkt->size = len; 454 pkt->size = len;
433 pkt->data = (uint8_t*)data; 455 pkt->data = (uint8_t*)data;
434 456
435 - int ret = -2;  
436 -  
437 do 457 do
438 { 458 {
439 int vdec_out_size = parse_stream_info(videoType, pkt); 459 int vdec_out_size = parse_stream_info(videoType, pkt);
@@ -453,7 +473,7 @@ int DvppStreamDecoder::SendData(int videoType, char* data, int len, int isKey, u @@ -453,7 +473,7 @@ int DvppStreamDecoder::SendData(int videoType, char* data, int len, int isKey, u
453 473
454 int nSended = -1; 474 int nSended = -1;
455 while ((ret = av_bsf_receive_packet(h264bsfc, pkt)) == 0) { 475 while ((ret = av_bsf_receive_packet(h264bsfc, pkt)) == 0) {
456 - if(!m_bExit){ 476 + if(m_bExit){
457 break; 477 break;
458 } 478 }
459 479
@@ -529,9 +549,9 @@ int DvppStreamDecoder::parse_stream_info(int videoType, AVPacket* pkt) { @@ -529,9 +549,9 @@ int DvppStreamDecoder::parse_stream_info(int videoType, AVPacket* pkt) {
529 } 549 }
530 550
531 const AVBitStreamFilter * filter = nullptr; 551 const AVBitStreamFilter * filter = nullptr;
532 - if(VIDEO_TYPE_H264 == videoType){ 552 + if(0 == videoType){
533 filter = av_bsf_get_by_name("h264_mp4toannexb"); 553 filter = av_bsf_get_by_name("h264_mp4toannexb");
534 - }else if(VIDEO_TYPE_H265 == videoType){ 554 + }else if(1 == videoType){
535 filter = av_bsf_get_by_name("hevc_mp4toannexb"); 555 filter = av_bsf_get_by_name("hevc_mp4toannexb");
536 }else { 556 }else {
537 LOG_ERROR("[{}]- codec_id is not supported!", m_dec_name); 557 LOG_ERROR("[{}]- codec_id is not supported!", m_dec_name);
@@ -585,9 +605,7 @@ int DvppStreamDecoder::parse_stream_info(int videoType, AVPacket* pkt) { @@ -585,9 +605,7 @@ int DvppStreamDecoder::parse_stream_info(int videoType, AVPacket* pkt) {
585 return m_vdec_out_size; 605 return m_vdec_out_size;
586 } 606 }
587 607
588 -void DvppStreamDecoder::Close() {  
589 - m_bExit = true;  
590 - 608 +void DvppStreamDecoder::release_channeldesc() {
591 if (vdecChannelDesc) { 609 if (vdecChannelDesc) {
592 sendVdecEos(vdecChannelDesc); 610 sendVdecEos(vdecChannelDesc);
593 611
@@ -598,7 +616,12 @@ void DvppStreamDecoder::Close() { @@ -598,7 +616,12 @@ void DvppStreamDecoder::Close() {
598 m_bExitReportThd = true; 616 m_bExitReportThd = true;
599 CHECK_NOT_RETURN(pthread_join(report_thread, nullptr), "report_thread join failed"); 617 CHECK_NOT_RETURN(pthread_join(report_thread, nullptr), "report_thread join failed");
600 } 618 }
  619 +}
  620 +
  621 +void DvppStreamDecoder::Close() {
  622 + m_bExit = true;
601 623
  624 + release_channeldesc();
602 release_dvpp(); 625 release_dvpp();
603 626
604 if(h264bsfc){ 627 if(h264bsfc){
src/decoder/dvpp/DvppStreamDecoder.h
@@ -32,6 +32,10 @@ private: @@ -32,6 +32,10 @@ private:
32 32
33 int parse_stream_info(int videoType, AVPacket* pkt); 33 int parse_stream_info(int videoType, AVPacket* pkt);
34 34
  35 + void release_dvpp();
  36 + void release_channeldesc();
  37 + int getVdecType(int videoType);
  38 +
35 private: 39 private:
36 string m_dec_name {""}; 40 string m_dec_name {""};
37 int m_deviceId {-1}; 41 int m_deviceId {-1};
@@ -47,6 +51,8 @@ private: @@ -47,6 +51,8 @@ private:
47 int m_fps {-1}; 51 int m_fps {-1};
48 int frameW {-1}; 52 int frameW {-1};
49 int frameH {-1}; 53 int frameH {-1};
  54 + int out_frame_width{0};
  55 + int out_frame_height{0};
50 56
51 VpcUtils m_vpcUtils; 57 VpcUtils m_vpcUtils;
52 58
@@ -62,6 +68,11 @@ private: @@ -62,6 +68,11 @@ private:
62 DECODE_FINISHED_CALLBACK decode_finished_cbk {nullptr}; 68 DECODE_FINISHED_CALLBACK decode_finished_cbk {nullptr};
63 69
64 AVBSFContext * h264bsfc{nullptr}; 70 AVBSFContext * h264bsfc{nullptr};
  71 +
  72 + uint64_t m_in_count {0};
  73 + uint64_t m_out_count {0};
  74 +
  75 + bool m_bResize {false};
65 }; 76 };
66 77
67 78
src/decoder/gb28181/DvppGB28181Decoder.cpp
@@ -2,8 +2,6 @@ @@ -2,8 +2,6 @@
2 #include <iostream> 2 #include <iostream>
3 #include "DvppGB28181Decoder.h" 3 #include "DvppGB28181Decoder.h"
4 4
5 -  
6 -  
7 extern "C" { 5 extern "C" {
8 #include "libavutil/avstring.h" 6 #include "libavutil/avstring.h"
9 #include "libavformat/avformat.h" 7 #include "libavformat/avformat.h"
@@ -13,8 +11,6 @@ extern &quot;C&quot; { @@ -13,8 +11,6 @@ extern &quot;C&quot; {
13 #include"RTPTcpReceiver.h" 11 #include"RTPTcpReceiver.h"
14 #include"RTPUdpReceiver.h" 12 #include"RTPUdpReceiver.h"
15 13
16 -#include <cuda_runtime.h>  
17 -  
18 #include "common_header.h" 14 #include "common_header.h"
19 15
20 // #include "../nvdec/FFCuContextManager.h" 16 // #include "../nvdec/FFCuContextManager.h"
@@ -25,6 +21,7 @@ extern &quot;C&quot; { @@ -25,6 +21,7 @@ extern &quot;C&quot; {
25 #define ECLOSING 1 21 #define ECLOSING 1
26 #define ERUNNING 2 22 #define ERUNNING 2
27 #define EPAUSE 3 23 #define EPAUSE 3
  24 +#define EINITED 4
28 25
29 static void RTP_Stream_CallBack(void* userdata, int videoType, char* data, int len, int isKey, uint64_t pts, uint64_t localPts) 26 static void RTP_Stream_CallBack(void* userdata, int videoType, char* data, int len, int isKey, uint64_t pts, uint64_t localPts)
30 { 27 {
@@ -48,10 +45,10 @@ DvppGB28181Decoder::~DvppGB28181Decoder() @@ -48,10 +45,10 @@ DvppGB28181Decoder::~DvppGB28181Decoder()
48 { 45 {
49 close(); 46 close();
50 47
51 - if (m_pAVCodecCtx) {  
52 - avcodec_close(m_pAVCodecCtx);  
53 - avcodec_free_context(&m_pAVCodecCtx);  
54 - } 48 + // if (m_pAVCodecCtx) {
  49 + // avcodec_close(m_pAVCodecCtx);
  50 + // avcodec_free_context(&m_pAVCodecCtx);
  51 + // }
55 52
56 m_dec_keyframe = false; 53 m_dec_keyframe = false;
57 54
@@ -75,19 +72,13 @@ void DvppGB28181Decoder::close(){ @@ -75,19 +72,13 @@ void DvppGB28181Decoder::close(){
75 m_rtpPtr = nullptr; 72 m_rtpPtr = nullptr;
76 } 73 }
77 74
78 - if (gpu_options) av_dict_free(&gpu_options); 75 + // if (gpu_options) av_dict_free(&gpu_options);
79 76
80 if (m_post_decode_thread != 0) 77 if (m_post_decode_thread != 0)
81 { 78 {
82 pthread_join(m_post_decode_thread,0); 79 pthread_join(m_post_decode_thread,0);
83 } 80 }
84 81
85 - while(mFrameQueue.size() > 0){  
86 - AVFrame * gpuFrame = mFrameQueue.front();  
87 - av_frame_free(&gpuFrame);  
88 - mFrameQueue.pop();  
89 - }  
90 -  
91 m_status = ECLOSED; 82 m_status = ECLOSED;
92 83
93 LOG_INFO("解码器关闭成功 --{}", m_dec_name); 84 LOG_INFO("解码器关闭成功 --{}", m_dec_name);
@@ -123,6 +114,8 @@ bool DvppGB28181Decoder::init(FFDecConfig&amp; cfg){ @@ -123,6 +114,8 @@ bool DvppGB28181Decoder::init(FFDecConfig&amp; cfg){
123 114
124 LOG_INFO("init - {} ", m_dec_name); 115 LOG_INFO("init - {} ", m_dec_name);
125 116
  117 + m_status = EINITED;
  118 +
126 return true; 119 return true;
127 } 120 }
128 121
@@ -140,6 +133,8 @@ bool DvppGB28181Decoder::start() { @@ -140,6 +133,8 @@ bool DvppGB28181Decoder::start() {
140 return (void*)0; 133 return (void*)0;
141 } 134 }
142 ,this); 135 ,this);
  136 +
  137 + return true;
143 } 138 }
144 139
145 LOG_ERROR("[{}] - rtp receiver open failed !", m_dec_name); 140 LOG_ERROR("[{}] - rtp receiver open failed !", m_dec_name);
@@ -185,95 +180,95 @@ void DvppGB28181Decoder::stream_callback(int videoType, char* data, int len, int @@ -185,95 +180,95 @@ void DvppGB28181Decoder::stream_callback(int videoType, char* data, int len, int
185 180
186 int DvppGB28181Decoder::ff_decode(int videoType, AVPacket* pkt) { 181 int DvppGB28181Decoder::ff_decode(int videoType, AVPacket* pkt) {
187 182
188 - if (m_pAVCodecCtx == nullptr) {  
189 - LOG_INFO("frame data is zero --{}", m_dec_name);  
190 - if (VIDEO_TYPE_H264 == videoType) {  
191 - if (m_gpuid >= 0){  
192 - m_pAVCodec = avcodec_find_decoder_by_name("h264_cuvid");  
193 - }  
194 - else{  
195 - m_pAVCodec = avcodec_find_decoder(AV_CODEC_ID_H264);  
196 - }  
197 - LOG_INFO("m_avCodecName is H264");  
198 - }  
199 - else if (VIDEO_TYPE_H265 == videoType)  
200 - {  
201 - if (m_gpuid >= 0){  
202 - m_pAVCodec = avcodec_find_decoder_by_name("hevc_cuvid");  
203 - }  
204 - else{  
205 - m_pAVCodec = avcodec_find_decoder(AV_CODEC_ID_H265);  
206 - }  
207 - LOG_INFO("m_avCodecName is H265");  
208 - }  
209 - else{  
210 - LOG_INFO("m_avCodecName is unknown, videoType is {}", videoType);  
211 - }  
212 -  
213 - if (!m_pAVCodec)  
214 - {  
215 - LOG_ERROR("frameCallback frame decode error, ERROR_DECODER_NOT_FOUND");  
216 - return;  
217 - }  
218 -  
219 - m_pAVCodecCtx = avcodec_alloc_context3(m_pAVCodec);  
220 -  
221 - if (m_gpuid >= 0) {  
222 - char gpui[8] = { 0 };  
223 - sprintf(gpui, "%d", m_gpuid);  
224 - av_dict_set(&gpu_options, "gpu", gpui, 0);  
225 -  
226 - m_pAVCodecCtx->get_format = get_hw_format;  
227 -  
228 - FFCuContextManager* pCtxMgr = FFCuContextManager::getInstance();  
229 - m_pAVCodecCtx->hw_device_ctx = av_buffer_ref(pCtxMgr->getCuCtx(gpui));  
230 - if (nullptr == m_pAVCodecCtx->hw_device_ctx){  
231 - // TODO 这里应该抛出错误  
232 - return ;  
233 - }  
234 - }  
235 -  
236 - if (avcodec_open2(m_pAVCodecCtx, m_pAVCodec, &gpu_options) < 0)  
237 - return;  
238 - }  
239 -  
240 - //开始解码  
241 - int ret = avcodec_send_packet(m_pAVCodecCtx, pkt);  
242 - if (ret < 0) {  
243 - //send_exception(RunMessageType::E2002, e_msg);  
244 - LOG_ERROR("Real stream视频解码失败,请检查视频设备{}: avcodec_send_packet failed. ret={}", m_dec_name, ret);  
245 - return;  
246 - } 183 + // if (m_pAVCodecCtx == nullptr) {
  184 + // LOG_INFO("frame data is zero --{}", m_dec_name);
  185 + // if (VIDEO_TYPE_H264 == videoType) {
  186 + // if (m_gpuid >= 0){
  187 + // m_pAVCodec = avcodec_find_decoder_by_name("h264_cuvid");
  188 + // }
  189 + // else{
  190 + // m_pAVCodec = avcodec_find_decoder(AV_CODEC_ID_H264);
  191 + // }
  192 + // LOG_INFO("m_avCodecName is H264");
  193 + // }
  194 + // else if (VIDEO_TYPE_H265 == videoType)
  195 + // {
  196 + // if (m_gpuid >= 0){
  197 + // m_pAVCodec = avcodec_find_decoder_by_name("hevc_cuvid");
  198 + // }
  199 + // else{
  200 + // m_pAVCodec = avcodec_find_decoder(AV_CODEC_ID_H265);
  201 + // }
  202 + // LOG_INFO("m_avCodecName is H265");
  203 + // }
  204 + // else{
  205 + // LOG_INFO("m_avCodecName is unknown, videoType is {}", videoType);
  206 + // }
  207 +
  208 + // if (!m_pAVCodec)
  209 + // {
  210 + // LOG_ERROR("frameCallback frame decode error, ERROR_DECODER_NOT_FOUND");
  211 + // return;
  212 + // }
  213 +
  214 + // m_pAVCodecCtx = avcodec_alloc_context3(m_pAVCodec);
  215 +
  216 + // if (m_gpuid >= 0) {
  217 + // char gpui[8] = { 0 };
  218 + // sprintf(gpui, "%d", m_gpuid);
  219 + // av_dict_set(&gpu_options, "gpu", gpui, 0);
  220 +
  221 + // m_pAVCodecCtx->get_format = get_hw_format;
  222 +
  223 + // FFCuContextManager* pCtxMgr = FFCuContextManager::getInstance();
  224 + // m_pAVCodecCtx->hw_device_ctx = av_buffer_ref(pCtxMgr->getCuCtx(gpui));
  225 + // if (nullptr == m_pAVCodecCtx->hw_device_ctx){
  226 + // // TODO 这里应该抛出错误
  227 + // return ;
  228 + // }
  229 + // }
  230 +
  231 + // if (avcodec_open2(m_pAVCodecCtx, m_pAVCodec, &gpu_options) < 0)
  232 + // return;
  233 + // }
  234 +
  235 + // //开始解码
  236 + // int ret = avcodec_send_packet(m_pAVCodecCtx, pkt);
  237 + // if (ret < 0) {
  238 + // //send_exception(RunMessageType::E2002, e_msg);
  239 + // LOG_ERROR("Real stream视频解码失败,请检查视频设备{}: avcodec_send_packet failed. ret={}", m_dec_name, ret);
  240 + // return;
  241 + // }
247 242
248 - if (frameW < 1) {  
249 - frameW = m_pAVCodecCtx->width;  
250 - frameH = m_pAVCodecCtx->height;  
251 - if (frameW <= 0 || frameH <= 0) {  
252 - LOG_ERROR("[{}] frame W or H is error! ({},{})", m_dec_name, frameW, frameH);  
253 - return;  
254 - }  
255 - }  
256 -  
257 - m_fps = av_q2d(m_pAVCodecCtx->framerate);  
258 -  
259 - AVFrame* gpuFrame = av_frame_alloc();  
260 - ret = avcodec_receive_frame(m_pAVCodecCtx, gpuFrame);  
261 - if ((ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) || ret < 0){  
262 - LOG_ERROR("{} - Failed to receive frame: {}", m_dec_name, ret);  
263 - av_frame_free(&gpuFrame);  
264 - gpuFrame = nullptr;  
265 - return;  
266 - } 243 + // if (frameW < 1) {
  244 + // frameW = m_pAVCodecCtx->width;
  245 + // frameH = m_pAVCodecCtx->height;
  246 + // if (frameW <= 0 || frameH <= 0) {
  247 + // LOG_ERROR("[{}] - frame W or H is error! ({},{})", m_dec_name, frameW, frameH);
  248 + // return;
  249 + // }
  250 + // }
  251 +
  252 + // m_fps = av_q2d(m_pAVCodecCtx->framerate);
  253 +
  254 + // AVFrame* gpuFrame = av_frame_alloc();
  255 + // ret = avcodec_receive_frame(m_pAVCodecCtx, gpuFrame);
  256 + // if ((ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) || ret < 0){
  257 + // LOG_ERROR("[{}] - Failed to receive frame: {}", m_dec_name, ret);
  258 + // av_frame_free(&gpuFrame);
  259 + // gpuFrame = nullptr;
  260 + // return;
  261 + // }
267 262
268 - if (gpuFrame->width != frameW || gpuFrame->height != frameH){  
269 - LOG_INFO("AVFrame is inconsistent: width is {}, height is {}; original frameW is {}, frameH is {}--{}", gpuFrame->width, gpuFrame->height, frameW, frameH , m_dec_name);  
270 - av_frame_free(&gpuFrame);  
271 - gpuFrame = nullptr;  
272 - return;  
273 - }  
274 -  
275 - av_frame_free(&gpuFrame);  
276 - gpuFrame = nullptr; 263 + // if (gpuFrame->width != frameW || gpuFrame->height != frameH){
  264 + // LOG_INFO("[{}] - AVFrame is inconsistent: width is {}, height is {}; original frameW is {}, frameH is {}--{}", m_dec_name, gpuFrame->width, gpuFrame->height, frameW, frameH);
  265 + // av_frame_free(&gpuFrame);
  266 + // gpuFrame = nullptr;
  267 + // return;
  268 + // }
  269 +
  270 + // av_frame_free(&gpuFrame);
  271 + // gpuFrame = nullptr;
277 } 272 }
278 273
279 void DvppGB28181Decoder::display_thread(){ 274 void DvppGB28181Decoder::display_thread(){
@@ -285,26 +280,26 @@ void DvppGB28181Decoder::display_thread(){ @@ -285,26 +280,26 @@ void DvppGB28181Decoder::display_thread(){
285 if(mem) { 280 if(mem) {
286 if ((m_frameSkip == 1 || index % m_frameSkip == 0) && post_decoded_cbk){ 281 if ((m_frameSkip == 1 || index % m_frameSkip == 0) && post_decoded_cbk){
287 post_decoded_cbk(m_postDecArg, mem); 282 post_decoded_cbk(m_postDecArg, mem);
  283 + } else {
  284 + delete mem;
  285 + mem = nullptr;
288 } 286 }
289 287
290 index++; 288 index++;
291 if(index >= 100000){ 289 if(index >= 100000){
292 index = 0; 290 index = 0;
293 } 291 }
294 - } else {  
295 - delete mem;  
296 - mem = nullptr;  
297 - } 292 + }
298 293
299 std::this_thread::sleep_for(std::chrono::milliseconds(10)); 294 std::this_thread::sleep_for(std::chrono::milliseconds(10));
300 } 295 }
301 296
302 - LOG_INFO("display thread exited."); 297 + LOG_INFO("[{}] - display thread exited.", m_dec_name);
303 } 298 }
304 299
305 void DvppGB28181Decoder::stream_end_callback() 300 void DvppGB28181Decoder::stream_end_callback()
306 { 301 {
307 - LOG_INFO("send_video_eof--{}", m_dec_name); 302 + LOG_INFO("[{}] - send_video_eof", m_dec_name);
308 303
309 decode_finished_cbk(m_finishedDecArg); 304 decode_finished_cbk(m_finishedDecArg);
310 305
@@ -321,12 +316,12 @@ void DvppGB28181Decoder::setFinishedDecArg(const void* finishedDecArg){ @@ -321,12 +316,12 @@ void DvppGB28181Decoder::setFinishedDecArg(const void* finishedDecArg){
321 316
322 void DvppGB28181Decoder::pause() { 317 void DvppGB28181Decoder::pause() {
323 m_status = EPAUSE; 318 m_status = EPAUSE;
324 - LOG_INFO("pause --{}", m_dec_name); 319 + LOG_INFO("[{}] - pause", m_dec_name);
325 } 320 }
326 321
327 void DvppGB28181Decoder::resume() { 322 void DvppGB28181Decoder::resume() {
328 m_status = ERUNNING; 323 m_status = ERUNNING;
329 - LOG_INFO("resume --{}", m_dec_name); 324 + LOG_INFO("[{}] - resume", m_dec_name);
330 } 325 }
331 326
332 bool DvppGB28181Decoder::isRunning(){ 327 bool DvppGB28181Decoder::isRunning(){
@@ -356,6 +351,12 @@ bool DvppGB28181Decoder::getResolution( int &amp;width, int &amp;height ){ @@ -356,6 +351,12 @@ bool DvppGB28181Decoder::getResolution( int &amp;width, int &amp;height ){
356 return true; 351 return true;
357 } 352 }
358 353
  354 +bool DvppGB28181Decoder::getOutResolution( int &width, int &height ) {
  355 + width = frameW;
  356 + height = frameH;
  357 + return true;
  358 +}
  359 +
359 float DvppGB28181Decoder::fps() { 360 float DvppGB28181Decoder::fps() {
360 return m_fps; 361 return m_fps;
361 } 362 }
@@ -367,4 +368,16 @@ bool DvppGB28181Decoder::isSurport(FFDecConfig&amp; cfg){ @@ -367,4 +368,16 @@ bool DvppGB28181Decoder::isSurport(FFDecConfig&amp; cfg){
367 368
368 int DvppGB28181Decoder::getCachedQueueLength(){ 369 int DvppGB28181Decoder::getCachedQueueLength(){
369 return m_rtpPtr->GetPsFrameListSize(); 370 return m_rtpPtr->GetPsFrameListSize();
  371 +}
  372 +
  373 +DeviceMemory* DvppGB28181Decoder::snapshot() {
  374 + return nullptr;
  375 +}
  376 +
  377 +void DvppGB28181Decoder::doRecode(RecoderInfo& recoderInfo) {
  378 +
  379 +}
  380 +
  381 +void DvppGB28181Decoder::set_mq_callback(std::function<bool(const char *msg)> mq_publish) {
  382 +
370 } 383 }
371 \ No newline at end of file 384 \ No newline at end of file
src/decoder/gb28181/DvppGB28181Decoder.h
@@ -38,6 +38,7 @@ public: @@ -38,6 +38,7 @@ public:
38 bool isFinished(); 38 bool isFinished();
39 bool isPausing(); 39 bool isPausing();
40 bool getResolution( int &width, int &height ); 40 bool getResolution( int &width, int &height );
  41 + bool getOutResolution( int &width, int &height );
41 42
42 bool isSurport(FFDecConfig& cfg); 43 bool isSurport(FFDecConfig& cfg);
43 44
@@ -45,7 +46,9 @@ public: @@ -45,7 +46,9 @@ public:
45 46
46 float fps(); 47 float fps();
47 48
48 - DECODER_TYPE getDecoderType(){ return DECODER_TYPE_GB28181; } 49 + DECODER_TYPE getDecoderType(){ return DECODER_TYPE_DVPP_GB28181; }
  50 +
  51 + DeviceMemory* snapshot();
49 52
50 void setName(string nm){ 53 void setName(string nm){
51 m_dec_name = nm; 54 m_dec_name = nm;
@@ -58,6 +61,10 @@ public: @@ -58,6 +61,10 @@ public:
58 void setPostDecArg(const void* postDecArg); 61 void setPostDecArg(const void* postDecArg);
59 void setFinishedDecArg(const void* finishedDecArg); 62 void setFinishedDecArg(const void* finishedDecArg);
60 63
  64 + void doRecode(RecoderInfo& recoderInfo);
  65 +
  66 + void set_mq_callback(std::function<bool(const char *msg)> mq_publish);
  67 +
61 public: 68 public:
62 void stream_callback(int videoType, char* data, int len, int isKey, uint64_t pts, uint64_t localPts); 69 void stream_callback(int videoType, char* data, int len, int isKey, uint64_t pts, uint64_t localPts);
63 void stream_end_callback(); 70 void stream_end_callback();
src/decoder/gb28181/main.cpp renamed to src/decoder/gb28181/main.cpp.28181
src/decoder/gb28181/rtp/RTPReceiver.cpp
@@ -163,8 +163,18 @@ void RTPReceiver::OnPsDemux(unsigned char streamId, BYTE *data, int len, bool ke @@ -163,8 +163,18 @@ void RTPReceiver::OnPsDemux(unsigned char streamId, BYTE *data, int len, bool ke
163 163
164 if (m_LastPTS != pts) 164 if (m_LastPTS != pts)
165 { 165 {
  166 + int stream_type = 0;
  167 + if (VIDEO_TYPE_H264 == streamId) {
  168 + stream_type = 0;
  169 + } else if(VIDEO_TYPE_H265 == streamId) {
  170 + stream_type = 1;
  171 + } else {
  172 + LOG_ERROR("[{}] - video type not support!", m_SipChannelId);
  173 + }
  174 +
  175 +
166 m_notToDecodCount = 0; 176 m_notToDecodCount = 0;
167 - m_h264DataFunc(m_usrParam, streamId, (char *)m_SliceBuf.head(), m_SliceBuf.len(), m_LastIsKeyFrame, m_LastPTS, localPts); 177 + m_h264DataFunc(m_usrParam, stream_type, (char *)m_SliceBuf.head(), m_SliceBuf.len(), m_LastIsKeyFrame, m_LastPTS, localPts);
168 178
169 m_SliceBuf.reset(); 179 m_SliceBuf.reset();
170 180
@@ -310,11 +320,20 @@ int RTPReceiver::allocRtpPort() { @@ -310,11 +320,20 @@ int RTPReceiver::allocRtpPort() {
310 if (s_rtpPort % 2) 320 if (s_rtpPort % 2)
311 ++s_rtpPort; 321 ++s_rtpPort;
312 322
  323 + int count = 0;
  324 +
313 while (true) 325 while (true)
314 { 326 {
315 - s_rtpPort = s_rtpPort >= MAX_RTP_PORT ? MIN_RTP_PORT : s_rtpPort; 327 + if (s_rtpPort >= MAX_RTP_PORT) {
  328 + s_rtpPort = MIN_RTP_PORT;
  329 + count ++;
  330 + if (count > 1) {
  331 + LOG_ERROR("[{}] - 10000 到 60000 没有可用的port", m_SipChannelId);
  332 + }
  333 + }
316 334
317 - for (int i = 0; i < 2; i++) { 335 + int i = 0;
  336 + for (; i < 2; i++) {
318 sockaddr_in sRecvAddr; 337 sockaddr_in sRecvAddr;
319 int s = socket(AF_INET, SOCK_DGRAM, 0); 338 int s = socket(AF_INET, SOCK_DGRAM, 0);
320 339
@@ -330,10 +349,13 @@ int RTPReceiver::allocRtpPort() { @@ -330,10 +349,13 @@ int RTPReceiver::allocRtpPort() {
330 nResult = close(s); 349 nResult = close(s);
331 if (nResult != 0) { 350 if (nResult != 0) {
332 LOG_ERROR("[{}] - closesocket failed : {}", m_SipChannelId, nResult); 351 LOG_ERROR("[{}] - closesocket failed : {}", m_SipChannelId, nResult);
333 - return -1; 352 + break;
334 } 353 }
335 } 354 }
336 355
  356 + if (i == 2)
  357 + break;
  358 +
337 s_rtpPort += 2; 359 s_rtpPort += 2;
338 } 360 }
339 361
src/decoder/gb28181/rtp/RTPTcpReceiver.cpp
@@ -373,7 +373,7 @@ bool RTPTcpReceiver::RequestStream(){ @@ -373,7 +373,7 @@ bool RTPTcpReceiver::RequestStream(){
373 SipServer* pServer = SipServer::getInstance(); 373 SipServer* pServer = SipServer::getInstance();
374 int ret = -1; 374 int ret = -1;
375 if (pServer){ 375 if (pServer){
376 - ret = pServer->RequestInvite_UDP(m_SipChannelId.c_str(), m_rtp_port); 376 + ret = pServer->RequestInvite_TCP_a(m_SipChannelId.c_str(), m_rtp_port);
377 } 377 }
378 378
379 return (ret > 0) ; 379 return (ret > 0) ;
src/decoder/gb28181/rtp/RTPUdpReceiver.cpp
@@ -123,6 +123,8 @@ bool RTPUdpReceiver::Open(string channel_id) @@ -123,6 +123,8 @@ bool RTPUdpReceiver::Open(string channel_id)
123 return false; 123 return false;
124 } 124 }
125 125
  126 + RequestStream();
  127 +
126 m_bOpened = true; 128 m_bOpened = true;
127 LOG_INFO("[{}] Open ok", m_SipChannelId); 129 LOG_INFO("[{}] Open ok", m_SipChannelId);
128 130
src/decoder/gb28181/sip/SipServer.cpp
@@ -270,6 +270,8 @@ void SipServer::response_register(eXosip_event_t *evtp) { @@ -270,6 +270,8 @@ void SipServer::response_register(eXosip_event_t *evtp) {
270 mClientMap.insert(std::make_pair(client->getDevice(),client)); 270 mClientMap.insert(std::make_pair(client->getDevice(),client));
271 271
272 //this->request_invite(client); 272 //this->request_invite(client);
  273 + // NVR注册成功,立即请求设备目录
  274 + RequestCatalog(client);
273 275
274 } else { 276 } else {
275 this->response_message_answer(evtp,401); 277 this->response_message_answer(evtp,401);
@@ -389,15 +391,31 @@ int SipServer::RequestInvite_UDP(const char* dst_channel, int rtpPort) { @@ -389,15 +391,31 @@ int SipServer::RequestInvite_UDP(const char* dst_channel, int rtpPort) {
389 391
390 sprintf(from, "sip:%s@%s:%d", mInfo.getSipId().c_str(), mInfo.getIp().c_str(), mInfo.getPort()); 392 sprintf(from, "sip:%s@%s:%d", mInfo.getSipId().c_str(), mInfo.getIp().c_str(), mInfo.getPort());
391 sprintf(to, "sip:%s@%s:%d", dst_channel, client->getIp().c_str(), client->getPort()); 393 sprintf(to, "sip:%s@%s:%d", dst_channel, client->getIp().c_str(), client->getPort());
392 - snprintf(sdp, 2048, 394 + // snprintf(sdp, 2048,
  395 + // "v=0\r\n"
  396 + // "o=%s 0 0 IN IP4 %s\r\n"
  397 + // "s=Play\r\n"
  398 + // "c=IN IP4 %s\r\n"
  399 + // "t=0 0\r\n"
  400 + // "m=video %d RTP/AVP 96 98 97\r\n"
  401 + // "a=recvonly\r\n"
  402 + // "a=rtpmap:96 PS/90000\r\n"
  403 + // "a=rtpmap:98 H264/90000\r\n"
  404 + // "a=rtpmap:97 MPEG4/90000\r\n"
  405 + // "a=setup:passive\r\n"
  406 + // "a=connection:new\r\n"
  407 + // "y=0100000001\r\n"
  408 + // "f=\r\n", mInfo.getSipId().c_str(), mInfo.getIp().c_str(), mInfo.getIp().c_str(), rtpPort);
  409 +
  410 + snprintf(sdp, 2048,
393 "v=0\r\n" 411 "v=0\r\n"
394 "o=%s 0 0 IN IP4 %s\r\n" 412 "o=%s 0 0 IN IP4 %s\r\n"
395 "s=Play\r\n" 413 "s=Play\r\n"
396 "c=IN IP4 %s\r\n" 414 "c=IN IP4 %s\r\n"
397 "t=0 0\r\n" 415 "t=0 0\r\n"
398 - "m=video %d RTP/AVP 96 98 97\r\n" 416 + "m=video %d RTP/AVP 98 97\r\n"
399 "a=recvonly\r\n" 417 "a=recvonly\r\n"
400 - "a=rtpmap:96 PS/90000\r\n" 418 + // "a=rtpmap:96 PS/90000\r\n"
401 "a=rtpmap:98 H264/90000\r\n" 419 "a=rtpmap:98 H264/90000\r\n"
402 "a=rtpmap:97 MPEG4/90000\r\n" 420 "a=rtpmap:97 MPEG4/90000\r\n"
403 "a=setup:passive\r\n" 421 "a=setup:passive\r\n"
src/decoder/interface/DecoderManager.cpp
@@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
7 7
8 #ifdef USE_DVPP 8 #ifdef USE_DVPP
9 #include "../dvpp/DvppDecoderApi.h" 9 #include "../dvpp/DvppDecoderApi.h"
  10 +#include "../gb28181/DvppGB28181Decoder.h"
10 #endif 11 #endif
11 12
12 #include "logger.hpp" 13 #include "logger.hpp"
@@ -49,9 +50,7 @@ AbstractDecoder* DecoderManager::createDecoder(MgrDecConfig config){ @@ -49,9 +50,7 @@ AbstractDecoder* DecoderManager::createDecoder(MgrDecConfig config){
49 #ifdef USE_NVDEC 50 #ifdef USE_NVDEC
50 if(DECODER_TYPE_FFMPEG == config.dec_type){ 51 if(DECODER_TYPE_FFMPEG == config.dec_type){
51 dec = new FFNvDecoder(); 52 dec = new FFNvDecoder();
52 - }  
53 -  
54 - if(DECODER_TYPE_GB28181 == config.dec_type){ 53 + } else if(DECODER_TYPE_GB28181 == config.dec_type){
55 dec = new FFGB28181Decoder(); 54 dec = new FFGB28181Decoder();
56 } 55 }
57 #endif 56 #endif
@@ -59,6 +58,8 @@ AbstractDecoder* DecoderManager::createDecoder(MgrDecConfig config){ @@ -59,6 +58,8 @@ AbstractDecoder* DecoderManager::createDecoder(MgrDecConfig config){
59 #ifdef USE_DVPP 58 #ifdef USE_DVPP
60 if(DECODER_TYPE_DVPP == config.dec_type){ 59 if(DECODER_TYPE_DVPP == config.dec_type){
61 dec = new DvppDecoderApi(); 60 dec = new DvppDecoderApi();
  61 + } else if(DECODER_TYPE_DVPP_GB28181 == config.dec_type){
  62 + dec = new DvppGB28181Decoder();
62 } 63 }
63 #endif 64 #endif
64 65
src/decoder/interface/interface_headers.h
@@ -44,7 +44,8 @@ struct FFDecConfig{ @@ -44,7 +44,8 @@ struct FFDecConfig{
44 enum DECODER_TYPE{ 44 enum DECODER_TYPE{
45 DECODER_TYPE_GB28181, 45 DECODER_TYPE_GB28181,
46 DECODER_TYPE_FFMPEG, 46 DECODER_TYPE_FFMPEG,
47 - DECODER_TYPE_DVPP 47 + DECODER_TYPE_DVPP,
  48 + DECODER_TYPE_DVPP_GB28181
48 }; 49 };
49 50
50 #endif 51 #endif
51 \ No newline at end of file 52 \ No newline at end of file
src/decoder/sip/Makefile deleted
1 -XX = g++  
2 -  
3 -  
4 -PROJECT_ROOT= /home/cmhu/vpt_ascend_arm  
5 -  
6 -DEPEND_DIR = $(PROJECT_ROOT)/bin  
7 -SRC_ROOT = /home/cmhu/vpt_ascend_arm/src/decoder/sip  
8 -  
9 -TARGET= $(PROJECT_ROOT)/bin/test_sip  
10 -  
11 -THIRDPARTY_ROOT = $(PROJECT_ROOT)/3rdparty  
12 -SPDLOG_ROOT = $(THIRDPARTY_ROOT)/spdlog-1.9.2/release  
13 -SIP_ROOT = /home/cmhu/vpt_ascend_arm/3rdparty/gb28181_3rd/release  
14 -  
15 -DEFS = -DLinux  
16 -  
17 -INCLUDE=-I $(SPDLOG_ROOT)/include \  
18 - -I $(SIP_ROOT)/include \  
19 -  
20 -  
21 -LIBS= -L $(SPDLOG_ROOT)/lib -l:libspdlog.a \  
22 - -L $(SIP_ROOT)/lib -l:libeXosip2.a -l:libosipparser2.a -l:libosip2.a -lcares\  
23 -  
24 -  
25 -CXXFLAGS= -g -O0 -fPIC $(INCLUDE) $(LIBS) $(DEFS) -lpthread -lrt -lz -fexceptions -std=c++11 -D_GLIBCXX_USE_CXX11_ABI=0 -fvisibility=hidden -Wall -Wno-deprecated -Wdeprecated-declarations -Wl,-Bsymbolic -ldl  
26 -  
27 -  
28 -  
29 -SRCS:=$(wildcard $(SRC_ROOT)/Utils/*.cpp) \  
30 - $(wildcard $(SRC_ROOT)/Message/*.cpp) \  
31 - $(wildcard $(SRC_ROOT)/tinyxml2/*.cpp) \  
32 - $(wildcard $(SRC_ROOT)/src/*.cpp) \  
33 -  
34 -OBJS = $(patsubst %.cpp, %.o, $(notdir $(SRCS)))  
35 -  
36 -  
37 -$(TARGET):$(OBJS)  
38 - rm -f $(TARGET)  
39 - $(XX) -o $@ $^ $(CXXFLAGS)  
40 - rm -f *.o  
41 -  
42 -%.o:$(SRC_ROOT)/Utils/%.cpp  
43 - $(XX) $(CXXFLAGS) -c $<  
44 -  
45 -%.o:$(SRC_ROOT)/Message/%.cpp  
46 - $(XX) $(CXXFLAGS) -c $<  
47 -  
48 -%.o:$(SRC_ROOT)/tinyxml2/%.cpp  
49 - $(XX) $(CXXFLAGS) -c $<  
50 -  
51 -%.o:$(SRC_ROOT)/src/%.cpp  
52 - $(XX) $(CXXFLAGS) -c $<  
53 -  
54 -clean:  
55 - rm -f *.o $(TARGET)  
src/decoder/sip/Message/CatalogParser.cpp deleted
1 -#include "CatalogParser.h"  
2 -#include <sstream>  
3 -#include <list>  
4 -  
5 -#include "../Utils/logger.hpp"  
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( "����δ����IJ���:{}" , type );  
284 - continue;  
285 - }  
286 - }  
287 - }  
288 - else  
289 - {  
290 - LOG_DEBUG( "����δ����IJ���:{}" , 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( "����δ����IJ���:{}" , type );  
544 - }  
545 - }  
546 - }  
547 - else  
548 - {  
549 - LOG_DEBUG( "����δ����IJ���:{}" , 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::Decode_Catlog(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 - {  
609 - return cat_list;  
610 - }  
611 -  
612 - std::string deviceid = pDeviceID->Value();  
613 - if (deviceid.empty())  
614 - {  
615 - return cat_list;  
616 - }  
617 -  
618 - std::string msgType = pRoot->Value();  
619 - std::string cmdType = pCmd->Value();  
620 - if (msgType == "Response" && cmdType == "Catalog")  
621 - {  
622 - cat_list = Decode(nodes);  
623 - if (cat_list.empty())  
624 - {  
625 - LOG_ERROR("��Ϣ���������!");  
626 - }  
627 - }  
628 -  
629 -  
630 - return cat_list;  
631 -}  
632 \ No newline at end of file 0 \ No newline at end of file
src/decoder/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 -enum EEventType  
8 -{  
9 - EVENT_ON = 0, // 上线  
10 - EVENT_OFF, // 离线  
11 - EVENT_VLOST, // 视频丢失  
12 - EVENT_DEFECT, // 故障  
13 - EVENT_ADD, // 增加  
14 - EVENT_DEL, // 删除  
15 - EVENT_UPDATE, // 更新  
16 -  
17 - EVENT_UNKNOW,  
18 -};  
19 -  
20 -struct DeviceInfo  
21 -{  
22 - EEventType event;  
23 - std::string id;  
24 - std::string name;  
25 - std::string manufacturer;  
26 - std::string model;  
27 - std::string owner;  
28 - std::string civil;  
29 - std::string block;  
30 - std::string address;  
31 - std::string safetyway;  
32 - std::string registerway;  
33 - std::string certnum;  
34 - std::string certifiable;  
35 - std::string errcode;  
36 - std::string secrecy;  
37 - std::string parental;  
38 - std::string parentid;  
39 - std::string endtime;  
40 - std::string ip;  
41 - std::string port;  
42 - std::string password;  
43 - std::string status;  
44 - std::string longitude;  
45 - std::string latitude;  
46 - std::string ptz;  
47 - std::string position;  
48 - std::string room;  
49 - std::string use;  
50 - std::string supplylight;  
51 - std::string direction;  
52 - std::string resolution;  
53 - std::string businessgroup;  
54 -};  
55 -  
56 -//////////////////////////////////////////////////////////////////////////  
57 -class CCatalogParser : public CGBMessage  
58 -{  
59 -public:  
60 - CCatalogParser()  
61 - {  
62 - }  
63 -  
64 -public:  
65 - bool Encode( std::string &message );  
66 -  
67 - std::vector< DeviceInfo > Decode_Catlog(const char* body);  
68 -  
69 - static std::string GetStrName(EEventType eType)  
70 - {  
71 - switch (eType)  
72 - {  
73 - case EVENT_ON:  
74 - return "ON";  
75 - case EVENT_OFF:  
76 - return "OFF";  
77 - case EVENT_VLOST:  
78 - return "VLOST";  
79 - case EVENT_DEFECT:  
80 - return "DEFECT";  
81 - case EVENT_ADD:  
82 - return "ADD";  
83 - case EVENT_DEL:  
84 - return "DEL";  
85 - case EVENT_UPDATE:  
86 - return "UPDATE";  
87 - default: //EVENT_UNKNOW  
88 - return "UNKNOW";  
89 - }  
90 -  
91 - return "UNKNOW";  
92 - }  
93 -  
94 - EEventType GetEnumName(const std::string &sType)  
95 - {  
96 - if (sType == "ON")  
97 - return EVENT_ON;  
98 - if (sType == "OFF")  
99 - return EVENT_OFF;  
100 - if (sType == "VLOSE")  
101 - return EVENT_VLOST;  
102 - if (sType == "DEFECT")  
103 - return EVENT_DEFECT;  
104 - if (sType == "ADD")  
105 - return EVENT_ADD;  
106 - if (sType == "DEL")  
107 - return EVENT_DEL;  
108 - if (sType == "UPDATE")  
109 - return EVENT_UPDATE;  
110 -  
111 - return EVENT_UNKNOW;  
112 -  
113 - }  
114 -  
115 -  
116 -public:  
117 -  
118 - inline const std::string& GetSN() const  
119 - {  
120 - return m_sn;  
121 - }  
122 -  
123 - inline const std::string& GetDeviceID() const  
124 - {  
125 - return m_deviceid;  
126 - }  
127 -  
128 - inline void SetDeviceID( const std::string &deviceid )  
129 - {  
130 - m_deviceid = deviceid;  
131 - }  
132 -  
133 - inline void SetSN( const std::string &sn )  
134 - {  
135 - m_sn = sn;  
136 - }  
137 -  
138 - inline const std::string& GetStatus() const  
139 - {  
140 - return m_status;  
141 - }  
142 -  
143 - inline void SetStatus( const std::string &status )  
144 - {  
145 - m_status = status;  
146 - }  
147 -  
148 - inline int GetSum() const  
149 - {  
150 - return m_sum;  
151 - }  
152 -  
153 - inline void SetSum( int sum )  
154 - {  
155 - m_sum = sum;  
156 - }  
157 -  
158 - inline const std::vector< DeviceInfo >& GetDevices() const  
159 - {  
160 - return m_devices;  
161 - }  
162 -  
163 - inline void AddEvent(const std::string &id, EEventType eventType)  
164 - {  
165 - DeviceInfo catalog;  
166 - catalog.id = id;  
167 - catalog.event = eventType;  
168 - m_devices.push_back( catalog );  
169 - }  
170 -  
171 - inline void AddOnEvent( const std::string &id )  
172 - {  
173 - DeviceInfo catalog;  
174 - catalog.id = id;  
175 - catalog.event = EVENT_ON;  
176 - m_devices.push_back( catalog );  
177 - }  
178 -  
179 - inline void AddOffEvent( const std::string &id )  
180 - {  
181 - DeviceInfo catalog;  
182 - catalog.id = id;  
183 - catalog.event = EVENT_OFF;  
184 - m_devices.push_back( catalog );  
185 - }  
186 -  
187 - inline void AddVLostEvent( const std::string &id )  
188 - {  
189 - DeviceInfo catalog;  
190 - catalog.id = id;  
191 - catalog.event = EVENT_VLOST;  
192 - m_devices.push_back( catalog );  
193 - }  
194 -  
195 - inline void AddDefectEvent( const std::string &id )  
196 - {  
197 - DeviceInfo catalog;  
198 - catalog.id = id;  
199 - catalog.event = EVENT_DEFECT;  
200 - m_devices.push_back( catalog );  
201 - }  
202 -  
203 - inline void AddDelEvent( const std::string &id )  
204 - {  
205 - DeviceInfo catalog;  
206 - catalog.id = id;  
207 - catalog.event = EVENT_DEL;  
208 - m_devices.push_back( catalog );  
209 - }  
210 -  
211 - inline void AddAddEvent( const DeviceInfo &catalog )  
212 - {  
213 - if( catalog.event == EVENT_ADD )  
214 - {  
215 - m_devices.push_back( catalog );  
216 - }  
217 - }  
218 -  
219 - inline void AddUpdateEvent( const DeviceInfo &catalog )  
220 - {  
221 - if( catalog.event == EVENT_UPDATE )  
222 - {  
223 - m_devices.push_back( catalog );  
224 - }  
225 - }  
226 -  
227 -private:  
228 - std::vector< DeviceInfo > Decode(const std::vector< tinyxml2::XMLNode* >& nodes);  
229 -  
230 -private:  
231 - std::string m_sn;  
232 - std::string m_deviceid;  
233 - std::string m_status;  
234 - int m_sum;  
235 - std::vector< DeviceInfo > m_devices;  
236 -};  
237 -  
238 -#endif // MSG_NOTIFY_MSG_HPP_  
239 \ No newline at end of file 0 \ No newline at end of file
src/decoder/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/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/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/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/sip/Utils/Log.h deleted
1 -//  
2 -// Created bxc on 2022/11/25.  
3 -//  
4 -  
5 -#ifndef BXC_SIPSERVER_LOG_H  
6 -#define BXC_SIPSERVER_LOG_H  
7 -#include <time.h>  
8 -#include <string>  
9 -  
10 -static std::string getTime() {  
11 - const char* time_fmt = "%Y-%m-%d %H:%M:%S";  
12 - time_t t = time(nullptr);  
13 - char time_str[64];  
14 - strftime(time_str, sizeof(time_str), time_fmt, localtime(&t));  
15 -  
16 - return time_str;  
17 -}  
18 -// __FILE__ 获取源文件的相对路径和名字  
19 -// __LINE__ 获取该行代码在文件中的行号  
20 -// __func__ 或 __FUNCTION__ 获取函数名  
21 -  
22 -#define LOGI(format, ...) fprintf(stderr,"[INFO]%s [%s:%d %s()] " format "\n", getTime().data(),__FILE__,__LINE__,__func__ ,##__VA_ARGS__)  
23 -#define LOGE(format, ...) fprintf(stderr,"[ERROR]%s [%s:%d %s()] " format "\n",getTime().data(),__FILE__,__LINE__,__func__ ,##__VA_ARGS__)  
24 -  
25 -#endif //BXC_SIPSERVER_LOG_H  
26 \ No newline at end of file 0 \ No newline at end of file
src/decoder/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/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/sip/src/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 -#endif // !WIN32  
13 -  
14 -#pragma comment(lib, "ws2_32.lib")  
15 -  
16 -#include <cstring>  
17 -#include "../Utils/logger.hpp"  
18 -#include "../Utils/HTTPDigest.h"  
19 -  
20 -#include <sstream>  
21 -  
22 -using namespace std;  
23 -  
24 -static void event_loop_thread(void* arg) {  
25 - SipServer* _this = (SipServer*)arg;  
26 - if (_this != nullptr) {  
27 - _this->event_loop();  
28 - }  
29 - else {  
30 - LOG_ERROR("event_loop线程启动失败 !");  
31 - }  
32 -}  
33 -  
34 -static void dt_printSipMsg(osip_message_t* msg) {  
35 - osip_message_t* clone_event = NULL;  
36 - size_t length = 0;  
37 - char* message = NULL;  
38 - osip_message_clone(msg, &clone_event);  
39 - osip_message_to_str(clone_event, &message, &length);  
40 - LOG_INFO("{}", message);  
41 -}  
42 -  
43 -SipServer::SipServer():  
44 - mQuit(false),  
45 - mSipCtx(nullptr){  
46 -#ifdef WIN32  
47 - WSADATA wsaData;  
48 - if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)  
49 - {  
50 - LOG_ERROR("WSAStartup Error");  
51 - return;  
52 - }  
53 -#endif // WIN32  
54 -  
55 -}  
56 -SipServer::~SipServer() {  
57 - LOG_INFO("~SipServer");  
58 -  
59 - if (m_event_loop_thread)  
60 - {  
61 - mQuit = true;  
62 - m_event_loop_thread->join();  
63 -  
64 - delete m_event_loop_thread;  
65 - m_event_loop_thread = nullptr;  
66 - }  
67 -  
68 - this->clearClientMap();  
69 -#ifdef WIN32  
70 - WSACleanup();  
71 -#endif // WIN32  
72 -}  
73 -  
74 -bool SipServer::Init(ServerInfo info) {  
75 - mInfo = info;  
76 - LOG_INFO("{}:{}", mInfo.getIp(), mInfo.getPort());  
77 - return true;  
78 -}  
79 -  
80 -int SipServer::sip_event_handle(eXosip_event_t *evtp) {  
81 -  
82 - switch(evtp->type) {  
83 - case EXOSIP_CALL_MESSAGE_NEW://14  
84 - LOG_INFO("EXOSIP_CALL_MESSAGE_NEW type={}", evtp->type);  
85 - this->dump_request(evtp);  
86 - this->dump_response(evtp);  
87 - break;  
88 -  
89 - case EXOSIP_CALL_CLOSED://21  
90 - LOG_INFO("EXOSIP_CALL_CLOSED type={}",evtp->type);  
91 - this->dump_request(evtp);  
92 - this->dump_response(evtp);  
93 - break;  
94 -  
95 - case EXOSIP_CALL_RELEASED://22  
96 - LOG_INFO("EXOSIP_CALL_RELEASED type={}", evtp->type);  
97 - this->dump_request(evtp);  
98 - this->dump_response(evtp);  
99 -  
100 - this->clearClientMap();  
101 - break;  
102 - case EXOSIP_MESSAGE_NEW://23  
103 - LOG_INFO("EXOSIP_MESSAGE_NEW type={}",evtp->type);  
104 -  
105 - if (MSG_IS_REGISTER(evtp->request)) {  
106 - this->response_register(evtp);  
107 - }  
108 - else if (MSG_IS_MESSAGE(evtp->request)) {  
109 - this->response_message(evtp);  
110 - }  
111 - else if(MSG_IS_BYE(evtp->request)){  
112 - LOG_ERROR("unknown1");  
113 - }  
114 - else{  
115 - LOG_ERROR("unknown2");  
116 - }  
117 - break;  
118 - case EXOSIP_MESSAGE_ANSWERED:  
119 - this->dump_request(evtp);  
120 - break;  
121 - case EXOSIP_MESSAGE_REQUESTFAILURE:  
122 - LOG_INFO("EXOSIP_MESSAGE_REQUESTFAILURE type={}: Receive feedback on sending failure after actively sending a message", evtp->type);  
123 - this->dump_request(evtp);  
124 - this->dump_response(evtp);  
125 - break;  
126 - case EXOSIP_CALL_INVITE:  
127 - LOG_INFO("EXOSIP_CALL_INVITE type={}: The server receives the Invite request actively sent by the client", evtp->type);  
128 - break;  
129 - case EXOSIP_CALL_PROCEEDING://5  
130 - LOG_INFO("EXOSIP_CALL_PROCEEDING type={}: When the server receives the Invite (SDP) confirmation reply from the client", evtp->type);  
131 - this->dump_request(evtp);  
132 - this->dump_response(evtp);  
133 - break;  
134 - case EXOSIP_CALL_ANSWERED:// 7  
135 - LOG_INFO("EXOSIP_CALL_ANSWERED type={}: The server receives an invite (SDP) confirmation reply from the client", evtp->type);  
136 - this->dump_request(evtp);  
137 - this->dump_response(evtp);  
138 -  
139 - this->response_invite_ack(evtp);  
140 - break;  
141 - case EXOSIP_CALL_SERVERFAILURE:  
142 - LOG_INFO("EXOSIP_CALL_SERVERFAILURE type={}", evtp->type);  
143 - break;  
144 - case EXOSIP_IN_SUBSCRIPTION_NEW:  
145 - LOG_INFO("EXOSIP_IN_SUBSCRIPTION_NEW type={}", evtp->type);  
146 - break;  
147 - default:  
148 - LOG_INFO("type={} unknown", evtp->type);  
149 - break;  
150 - }  
151 -  
152 - return 0;  
153 -}  
154 -  
155 -int SipServer::init_sip_server() {  
156 - mSipCtx = eXosip_malloc();  
157 - if (!mSipCtx) {  
158 - LOG_ERROR("eXosip_malloc error");  
159 - return -1;  
160 - }  
161 - if (eXosip_init(mSipCtx)) {  
162 - LOG_ERROR("eXosip_init error");  
163 - return -1;  
164 - }  
165 - if (eXosip_listen_addr(mSipCtx, IPPROTO_UDP, nullptr, mInfo.getPort(), AF_INET, 0)) {  
166 - LOG_ERROR("eXosip_listen_addr error");  
167 - return -1;  
168 - }  
169 - eXosip_set_user_agent(mSipCtx, mInfo.getUa().c_str());  
170 - if (eXosip_add_authentication_info(mSipCtx, mInfo.getSipId().c_str(), mInfo.getSipId().c_str(), mInfo.getSipPass().c_str(), NULL, mInfo.getSipRealm().c_str())) {  
171 - LOG_ERROR("eXosip_add_authentication_info error");  
172 - return -1;  
173 - }  
174 -  
175 - return 0;  
176 -}  
177 -  
178 -void SipServer::Start() {  
179 - m_event_loop_thread = new std::thread(event_loop_thread, this);  
180 -}  
181 -  
182 -void SipServer::event_loop() {  
183 -  
184 - if(this->init_sip_server() !=0 ){  
185 - return;  
186 - }  
187 - while(!mQuit) {  
188 - eXosip_event_t *evtp = eXosip_event_wait(mSipCtx, 0, 20);  
189 - if (!evtp){  
190 - eXosip_automatic_action(mSipCtx);  
191 - osip_usleep(100000);  
192 - continue;  
193 - }  
194 - eXosip_automatic_action(mSipCtx);  
195 - this->sip_event_handle(evtp);  
196 - eXosip_event_free(evtp);  
197 - }  
198 -}  
199 -  
200 -void SipServer::response_message_answer(eXosip_event_t *evtp,int code){  
201 -  
202 - int returnCode = 0 ;  
203 - osip_message_t * pRegister = nullptr;  
204 - returnCode = eXosip_message_build_answer (mSipCtx,evtp->tid,code,&pRegister);  
205 - bool bRegister = false;  
206 - if(pRegister){  
207 - bRegister = true;  
208 - }  
209 - if (returnCode == 0 && bRegister)  
210 - {  
211 - eXosip_lock(mSipCtx);  
212 - eXosip_message_send_answer (mSipCtx,evtp->tid,code,pRegister);  
213 - eXosip_unlock(mSipCtx);  
214 - }  
215 - else{  
216 - LOG_ERROR("code={},returnCode={},bRegister={}",code,returnCode,bRegister);  
217 - }  
218 -  
219 -}  
220 -void SipServer::response_register(eXosip_event_t *evtp) {  
221 -  
222 -  
223 - osip_authorization_t * auth = nullptr;  
224 - osip_message_get_authorization(evtp->request, 0, &auth);  
225 -  
226 - if(auth && auth->username){  
227 -  
228 - char *method = NULL, // REGISTER  
229 - *algorithm = NULL, // MD5  
230 - *username = NULL,// 340200000013200000024  
231 - *realm = NULL, // sip服务器传给客户端,客户端携带并提交上来的sip服务域  
232 - *nonce = NULL, //sip服务器传给客户端,客户端携带并提交上来的nonce  
233 - *nonce_count = NULL,  
234 - *uri = NULL; // sip:34020000002000000001@3402000000  
235 -  
236 - osip_contact_t *contact = nullptr;  
237 - osip_message_get_contact (evtp->request, 0, &contact);  
238 -  
239 - method = evtp->request->sip_method;  
240 - char calc_response[HASHHEXLEN];  
241 - HASHHEX HA1, HA2 = "", Response;  
242 -  
243 -#define SIP_STRDUP(field) if (auth->field) (field) = osip_strdup_without_quote(auth->field)  
244 -  
245 - SIP_STRDUP(algorithm);  
246 - SIP_STRDUP(username);  
247 - SIP_STRDUP(realm);  
248 - SIP_STRDUP(nonce);  
249 - SIP_STRDUP(nonce_count);  
250 - SIP_STRDUP(uri);  
251 -  
252 - DigestCalcHA1(algorithm, username, realm, mInfo.getSipPass().c_str(), nonce, nonce_count, HA1);  
253 - DigestCalcResponse(HA1, nonce, nonce_count, auth->cnonce, auth->message_qop, 0, method, uri, HA2, Response);  
254 -  
255 - HASHHEX temp_HA1;  
256 - HASHHEX temp_response;  
257 - DigestCalcHA1("REGISTER", username, mInfo.getSipRealm().c_str(), mInfo.getSipPass().c_str(), mInfo.getNonce().c_str(), NULL, temp_HA1);  
258 - DigestCalcResponse(temp_HA1, mInfo.getNonce().c_str(), NULL, NULL, NULL, 0, method, uri, NULL, temp_response);  
259 - memcpy(calc_response, temp_response, HASHHEXLEN);  
260 -  
261 -  
262 -  
263 - if (!memcmp(calc_response, Response, HASHHEXLEN)) {  
264 - this->response_message_answer(evtp,200);  
265 -  
266 - Client* client = new Client(strdup(contact->url->host),  
267 - atoi(contact->url->port),  
268 - strdup(username));  
269 -  
270 - LOG_INFO("Camera registration succee,ip={},port={},device={}",client->getIp(),client->getPort(),client->getDevice());  
271 -  
272 - mClientMap.insert(std::make_pair(client->getDevice(),client));  
273 -  
274 - //this->request_invite(client);  
275 -  
276 - } else {  
277 - this->response_message_answer(evtp,401);  
278 - LOG_INFO("Camera registration error, p={},port={},device={}", strdup(contact->url->host), atoi(contact->url->port), strdup(username));  
279 - }  
280 -  
281 - osip_free(algorithm);  
282 - osip_free(username);  
283 - osip_free(realm);  
284 - osip_free(nonce);  
285 - osip_free(nonce_count);  
286 - osip_free(uri);  
287 - } else {  
288 - response_register_401unauthorized(evtp);  
289 - }  
290 -  
291 -}  
292 -  
293 -void SipServer::response_register_401unauthorized(eXosip_event_t *evtp) {  
294 -  
295 - char *dest = nullptr;  
296 - osip_message_t * reg = nullptr;  
297 - osip_www_authenticate_t * header = nullptr;  
298 -  
299 - osip_www_authenticate_init(&header);  
300 - osip_www_authenticate_set_auth_type (header, osip_strdup("Digest"));  
301 - osip_www_authenticate_set_realm(header,osip_enquote(mInfo.getSipRealm().c_str()));  
302 - osip_www_authenticate_set_nonce(header,osip_enquote(mInfo.getNonce().c_str()));  
303 - osip_www_authenticate_to_str(header, &dest);  
304 - int ret = eXosip_message_build_answer (mSipCtx, evtp->tid, 401, &reg);  
305 - if ( ret == 0 && reg != nullptr ) {  
306 - osip_message_set_www_authenticate(reg, dest);  
307 - osip_message_set_content_type(reg, "Application/MANSCDP+xml");  
308 - eXosip_lock(mSipCtx);  
309 - eXosip_message_send_answer (mSipCtx, evtp->tid,401, reg);  
310 - eXosip_unlock(mSipCtx);  
311 - LOG_INFO("response_register_401unauthorized success");  
312 - }else {  
313 - LOG_INFO("response_register_401unauthorized error");  
314 - }  
315 -  
316 - osip_www_authenticate_free(header);  
317 - osip_free(dest);  
318 -  
319 -}  
320 -  
321 -void SipServer::response_message(eXosip_event_t *evtp) {  
322 -  
323 - osip_body_t* body = nullptr;  
324 - char CmdType[64] = {0};  
325 - char DeviceID[64] = {0};  
326 - osip_message_get_body(evtp->request, 0, &body);  
327 - if(body){  
328 - parse_xml(body->body, "<CmdType>", false, "</CmdType>", false, CmdType);  
329 - parse_xml(body->body, "<DeviceID>", false, "</DeviceID>", false, DeviceID);  
330 - }  
331 -  
332 -// Client *client = getClientByDevice(DeviceID);  
333 -// if(client){  
334 -// LOG_INFO("response_message:{} 已注册",DeviceID);  
335 -// }else{  
336 -// LOG_ERROR("response_message:{} 未注册",DeviceID);  
337 -// }  
338 - LOG_INFO("CmdType={},DeviceID={}", CmdType, DeviceID);  
339 -  
340 - if(!strcmp(CmdType, "Catalog")) {  
341 - this->response_message_answer(evtp,200);  
342 - // 需要根据对方的Catelog请求,做一些相应的应答请求  
343 - CCatalogParser catPaser;  
344 - m_vec_device = catPaser.Decode_Catlog(body->body);  
345 - }  
346 - else if(!strcmp(CmdType, "Keepalive")){  
347 - this->response_message_answer(evtp,200);  
348 - }else{  
349 - this->response_message_answer(evtp,200);  
350 - }  
351 -  
352 -}  
353 -  
354 -void SipServer::response_invite_ack(eXosip_event_t *evtp){  
355 -  
356 - osip_message_t* msg = nullptr;  
357 - int ret = eXosip_call_build_ack(mSipCtx, evtp->did, &msg);  
358 - if (!ret && msg) {  
359 - eXosip_call_send_ack(mSipCtx, evtp->did, msg);  
360 - } else {  
361 - LOG_ERROR("eXosip_call_send_ack error={}", ret);  
362 - }  
363 -  
364 -}  
365 -int SipServer::request_bye(eXosip_event_t* evtp) {  
366 -  
367 - eXosip_lock(mSipCtx);  
368 - int ret = eXosip_call_terminate(mSipCtx, evtp->cid, evtp->did);  
369 - eXosip_unlock(mSipCtx);  
370 -  
371 - return ret;  
372 -}  
373 -  
374 -int SipServer::RequestInvite(Client* client, const DeviceInfo& device) {  
375 - LOG_INFO("INVITE");  
376 -  
377 - char session_exp[1024] = { 0 };  
378 - osip_message_t* msg = nullptr;  
379 - char from[1024] = { 0 };  
380 - char to[1024] = { 0 };  
381 - char sdp[2048] = { 0 };  
382 - char head[1024] = { 0 };  
383 -  
384 - const char* dest_channel = "34020000001320000001";  
385 - const char* nvr_ip = "192.168.60.82";  
386 - const char* nvr_port = "5060";  
387 -  
388 - sprintf(from, "sip:%s@%s:%d", mInfo.getSipId().c_str(), mInfo.getIp().c_str(), mInfo.getPort());  
389 - sprintf(to, "sip:%s@%s:%d", dest_channel, client->getIp().c_str(), client->getPort());  
390 - snprintf(sdp, 2048,  
391 - "v=0\r\n"  
392 - "o=%s 0 0 IN IP4 %s\r\n"  
393 - "s=Play\r\n"  
394 - "c=IN IP4 %s\r\n"  
395 - "t=0 0\r\n"  
396 - "m=video %d RTP/AVP 96 98 97\r\n"  
397 - "a=recvonly\r\n"  
398 - "a=rtpmap:96 PS/90000\r\n"  
399 - "a=rtpmap:98 H264/90000\r\n"  
400 - "a=rtpmap:97 MPEG4/90000\r\n"  
401 - "a=setup:passive\r\n"  
402 - "a=connection:new\r\n"  
403 - "y=0100000001\r\n"  
404 - "f=\r\n", mInfo.getSipId().c_str(), mInfo.getIp().c_str(), mInfo.getIp().c_str(), mInfo.getRtpPort());  
405 -  
406 - int ret = eXosip_call_build_initial_invite(mSipCtx, &msg, to, from, nullptr, nullptr);  
407 - if (ret) {  
408 - LOG_ERROR("eXosip_call_build_initial_invite error: {} {} ret:{}", from, to, ret);  
409 - return -1;  
410 - }  
411 -  
412 - osip_message_set_body(msg, sdp, strlen(sdp));  
413 - osip_message_set_content_type(msg, "application/sdp");  
414 - snprintf(session_exp, sizeof(session_exp) - 1, "%i;refresher=uac", mInfo.getTimeout());  
415 - osip_message_set_header(msg, "Session-Expires", session_exp);  
416 - osip_message_set_supported(msg, "timer");  
417 -  
418 - int call_id = eXosip_call_send_initial_invite(mSipCtx, msg);  
419 - if (call_id > 0) {  
420 - LOG_INFO("eXosip_call_send_initial_invite success: call_id={}", call_id);  
421 - }  
422 - else {  
423 - LOG_ERROR("eXosip_call_send_initial_invite error: call_id={}", call_id);  
424 - }  
425 - return ret;  
426 -}  
427 -  
428 -void SipServer::RequestCatlog(Client* client) {  
429 -  
430 - eXosip_lock(mSipCtx);  
431 -  
432 - osip_message_t* catlog_msg = NULL;  
433 - char to[100];/*sip:主叫用户名@被叫IP地址*/  
434 - char from[100];/*sip:被叫IP地址:被叫IP端口*/  
435 - char xml_body[4096];  
436 -  
437 - memset(to, 0, 100);  
438 - memset(from, 0, 100);  
439 - memset(xml_body, 0, 4096);  
440 -  
441 - sprintf(from, "sip:%s@%s:%d", mInfo.getSipId().c_str(), mInfo.getIp().c_str(), mInfo.getPort());  
442 - sprintf(to, "sip:%s@%s:%d", client->getDevice().c_str(), client->getIp().c_str(), client->getPort());  
443 - eXosip_message_build_request(mSipCtx, &catlog_msg, "MESSAGE", to, from, NULL);/*构建"MESSAGE"请求*/  
444 -  
445 - snprintf(xml_body, 4096,  
446 - "<?xml version=\"1.0\"?>"  
447 - "<Query>"  
448 - "<CmdType>Catalog</CmdType>"  
449 - "<SN>%d</SN>"  
450 - "<DeviceID>%s</DeviceID>"  
451 - "</Query>", rand() % (99999 - 10000 + 1) + 10000, client->getDevice().c_str());  
452 -  
453 - osip_message_set_body(catlog_msg, xml_body, strlen(xml_body));  
454 - osip_message_set_content_type(catlog_msg, "Application/MANSCDP+xml");  
455 - eXosip_message_send_request(mSipCtx, catlog_msg);  
456 -  
457 - eXosip_unlock(mSipCtx);  
458 -}  
459 -  
460 -int SipServer::clearClientMap(){  
461 - for (auto iter=mClientMap.begin(); iter!=mClientMap.end(); iter++) {  
462 - delete iter->second;  
463 - iter->second = nullptr;  
464 - }  
465 - mClientMap.clear();  
466 -  
467 - return 0;  
468 -}  
469 -  
470 -Client * SipServer::GetClientByDevice(string device) {  
471 - auto it = mClientMap.find(device);  
472 - if(it == mClientMap.end()){  
473 - return nullptr;  
474 - }  
475 - return it->second;  
476 -}  
477 -  
478 -void SipServer::DeleteClientByDevice(string device) {  
479 - auto it = mClientMap.find(device);  
480 - if (it == mClientMap.end()) {  
481 - return ;  
482 - }  
483 - delete it->second;  
484 - it->second = nullptr;  
485 - mClientMap.erase(it);  
486 -}  
487 -  
488 -std::map<std::string, Client*> SipServer::GetClientMap() {  
489 - return mClientMap;  
490 -}  
491 -  
492 -std::vector< DeviceInfo > SipServer::GetDeviceList() {  
493 - return m_vec_device;  
494 -}  
495 -  
496 -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) {  
497 - const char* satrt = strstr( data, s_mark );  
498 -  
499 - if(satrt != NULL) {  
500 - const char* end = strstr(satrt, e_mark);  
501 -  
502 - if(end != NULL){  
503 - int s_pos = with_s_make ? 0 : strlen(s_mark);  
504 - int e_pos = with_e_make ? strlen(e_mark) : 0;  
505 -  
506 - strncpy( dest, satrt+s_pos, (end+e_pos) - (satrt+s_pos) );  
507 - }  
508 - return 0;  
509 - }  
510 - return -1;  
511 -  
512 -}  
513 -void SipServer::dump_request(eXosip_event_t *evtp) {  
514 - char *s;  
515 - size_t len;  
516 - osip_message_to_str(evtp->request, &s, &len);  
517 - LOG_INFO("\nprint request start\ntype={}\n{}\nprint request end\n",evtp->type,s);  
518 -}  
519 -void SipServer::dump_response(eXosip_event_t *evtp) {  
520 - char *s;  
521 - size_t len;  
522 - osip_message_to_str(evtp->response, &s, &len);  
523 - LOG_INFO("\nprint response start\ntype={}\n{}\nprint response end\n",evtp->type,s);  
524 -}  
525 \ No newline at end of file 0 \ No newline at end of file
src/decoder/sip/src/SipServer.h deleted
1 -//  
2 -// Created bxc on 2022/11/25.  
3 -//  
4 -  
5 -#ifndef BXC_SIPSERVER_SIPSERVER_H  
6 -#define BXC_SIPSERVER_SIPSERVER_H  
7 -extern "C" {  
8 -#include <osip2/osip_mt.h>  
9 -#include <eXosip2/eXosip.h>  
10 -}  
11 -#include <map>  
12 -#include <string>  
13 -#include <thread>  
14 -#include <chrono>  
15 -  
16 -#include "../Message/CatalogParser.h"  
17 -  
18 -using namespace std;  
19 -  
20 -class ServerInfo {  
21 -public:  
22 - ServerInfo() {}  
23 -  
24 - ServerInfo(string ua,string nonce, string ip, int port, int rtpPort,  
25 - string sipId, string sipRealm, string sipPass, int sipTimeout, int sipExpiry):  
26 - mUa(ua),  
27 - mNonce(nonce),mIp(ip),mPort(port),mRtpPort(rtpPort),mSipId(sipId),  
28 - mSipRealm(sipRealm),mSipPass(sipPass),mSipTimeout(sipTimeout),  
29 - mSipExpiry(sipExpiry){}  
30 -  
31 - ~ServerInfo() = default;  
32 -public:  
33 - string getUa() const{  
34 - return mUa;  
35 - }  
36 - string getNonce() const{  
37 - return mNonce;  
38 - }  
39 - string getIp() const{  
40 - return mIp;  
41 - }  
42 - int getPort() const {  
43 - return mPort;  
44 - }  
45 - int getRtpPort() const {  
46 - return mRtpPort;  
47 - }  
48 - string getSipId() const{  
49 - return mSipId;  
50 - }  
51 - string getSipRealm() const{  
52 - return mSipRealm;  
53 - }  
54 - string getSipPass() const{  
55 - return mSipPass;  
56 - }  
57 - int getTimeout() const {  
58 - return mSipTimeout;  
59 - }  
60 - int getExpiry() const {  
61 - return mSipExpiry;  
62 - }  
63 -  
64 -private:  
65 - string mUa;  
66 - string mNonce;//SIP服务随机数值  
67 - string mIp;//SIP服务IP  
68 - int mPort;//SIP服务端口  
69 - string mSipId; //SIP服务器ID  
70 - string mSipRealm;//SIP服务器域  
71 - string mSipPass;//SIP password  
72 - int mSipTimeout; //SIP timeout  
73 - int mSipExpiry;// SIP到期  
74 - int mRtpPort; //SIP-RTP服务端口  
75 -};  
76 -  
77 -class Client {  
78 -public:  
79 - Client(string ip, int port, string device) :  
80 - mIp(ip),  
81 - mPort(port),  
82 - mRtpPort(0),  
83 - mDevice(device),  
84 - mIsReg(false){  
85 - }  
86 - ~Client() = default;  
87 -public:  
88 -  
89 - void setRtpPort(int rtpPort) {  
90 - mRtpPort = rtpPort;  
91 - }  
92 -  
93 - void setReg(bool isReg) {  
94 - mIsReg = isReg;  
95 - }  
96 - string getDevice() const{  
97 - return mDevice;  
98 - }  
99 - string getIp() const{  
100 - return mIp;  
101 - }  
102 - int getPort() const{  
103 - return mPort;  
104 - }  
105 -  
106 -private:  
107 - // step1  
108 - string mIp; // client ip  
109 - int mPort; // client port  
110 - string mDevice;// 340200000013200000024  
111 - // step2  
112 - bool mIsReg;  
113 - // step3  
114 - int mRtpPort{};  
115 -  
116 -};  
117 -  
118 -  
119 -class SipServer {  
120 -public:  
121 - SipServer();  
122 - ~SipServer();  
123 -public:  
124 - bool Init(ServerInfo info);  
125 - void Start();  
126 -  
127 - Client* GetClientByDevice(string device);  
128 - void DeleteClientByDevice(string device);  
129 -  
130 - std::vector< DeviceInfo > GetDeviceList();  
131 -  
132 - std::map<std::string, Client*> GetClientMap();  
133 -  
134 - int RequestInvite(Client* client, const DeviceInfo& device);  
135 -  
136 - void RequestCatlog(Client* client);  
137 -  
138 -public:  
139 - void event_loop();  
140 -  
141 -private:  
142 - int init_sip_server();  
143 - int sip_event_handle(eXosip_event_t *evtp);  
144 -  
145 - void response_message_answer(eXosip_event_t *evtp,int code);  
146 - void response_register(eXosip_event_t *evtp);  
147 - void response_register_401unauthorized(eXosip_event_t *evt);  
148 - void response_message(eXosip_event_t *evtp);  
149 - void response_invite_ack(eXosip_event_t *evtp);  
150 - int request_bye(eXosip_event_t* evtp);// 通知相机停止推流  
151 - int parse_xml(const char* data, const char* s_mark, bool with_s_make, const char* e_mark, bool with_e_make, char* dest);  
152 - void dump_request(eXosip_event_t *evtp);  
153 - void dump_response(eXosip_event_t *evtp);  
154 -  
155 - int clearClientMap();  
156 -  
157 -private:  
158 - bool mQuit{ false };  
159 - eXosip_t *mSipCtx;  
160 - ServerInfo mInfo;  
161 -  
162 - std::map<std::string, Client *> mClientMap;// <DeviceID,SipClient>  
163 -  
164 - std::vector< DeviceInfo > m_vec_device;  
165 -  
166 - thread* m_event_loop_thread;  
167 -};  
168 -  
169 -  
170 -#endif //BXC_SIPSERVER_SIPSERVER_H  
src/decoder/sip/src/main.cpp deleted
1 -//  
2 -// Created bxc on 2022/11/25.  
3 -//  
4 -  
5 -#include "SipServer.h"  
6 -  
7 -#include <thread>  
8 -#include <chrono>  
9 -#include <iostream>  
10 -  
11 -using namespace std;  
12 -  
13 -int main(int argc, char *argv[]) {  
14 -  
15 - ServerInfo info(  
16 - "SY_SipServer",  
17 - "12345678",  
18 - "192.168.60.179",  
19 - 15061,  
20 - 30026,  
21 - "34020000002000000002",  
22 - "3402000000",  
23 - "sy123456",  
24 - 1800,  
25 - 3600);  
26 -  
27 - SipServer sipServer;  
28 - sipServer.Init(info);  
29 - sipServer.Start();  
30 -  
31 - std::this_thread::sleep_for(std::chrono::seconds(5));  
32 -  
33 - std::map<std::string, Client*> client_map;  
34 - std::vector< DeviceInfo > vec_device;  
35 - char oper = 'g';  
36 - while (oper != 'q') {  
37 - oper = getchar();  
38 - switch (oper)  
39 - {  
40 - case 'g':  
41 - client_map = sipServer.GetClientMap();  
42 - if (client_map.size() <= 0)  
43 - {  
44 - cout << "no IPC" << endl;  
45 - }  
46 - else {  
47 - cout << "client size:" << client_map.size() << endl;  
48 - }  
49 - break;  
50 - case 'i':  
51 - vec_device = sipServer.GetDeviceList();  
52 - if (vec_device.size() <= 0)  
53 - {  
54 - cout << "no device" << endl;  
55 - break;  
56 - }  
57 -  
58 - if (client_map.size() <= 0)  
59 - {  
60 - cout << "no IPC" << endl;  
61 - }  
62 - else {  
63 - auto it = client_map.begin();  
64 - sipServer.RequestInvite(it->second, vec_device[0]);  
65 - }  
66 - break;  
67 - case 'b':  
68 - break;  
69 - case 'c':  
70 - if (client_map.size() <= 0)  
71 - {  
72 - cout << "no IPC" << endl;  
73 - }  
74 - else {  
75 - auto it = client_map.begin();  
76 - sipServer.RequestCatlog(it->second);  
77 - }  
78 - break;  
79 - default:  
80 - break;  
81 - }  
82 - }  
83 -  
84 - return 0;  
85 -}  
86 \ No newline at end of file 0 \ No newline at end of file
src/decoder/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/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/sip/udp_server deleted
No preview for this file type
src/decoder/sip/udp_server.cpp0 deleted
1 -#include <stdio.h>  
2 -#include <stdlib.h>  
3 -#include <sys/socket.h>  
4 -#include <sys/types.h>  
5 -#include <netdb.h>  
6 -#include <string.h>  
7 -#include <errno.h>  
8 -#include <netinet/in.h>  
9 -  
10 -  
11 -#define BUF_SIZE 1024  
12 -  
13 -  
14 -int main(int argc, char *argv[])  
15 -{  
16 - struct addrinfo hint, *result;  
17 - struct sockaddr_in client_addr;  
18 - int res, sfd, client_addr_len;  
19 - char buf[BUF_SIZE];  
20 -  
21 - struct sockaddr_in addr;  
22 - memset(&addr, 0, sizeof(struct sockaddr_in));  
23 -  
24 - unsigned short port = 30026;  
25 -  
26 - addr.sin_family = AF_INET;  
27 - addr.sin_port = htons(port);  
28 - addr.sin_addr.s_addr = INADDR_ANY;  
29 -  
30 - sfd = socket(AF_INET, SOCK_DGRAM, 0);  
31 - if (sfd == -1)  
32 - {  
33 - perror("socket error!\n");  
34 - exit(1);  
35 - }  
36 -  
37 - res = bind(sfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));  
38 - if (res == -1)  
39 - {  
40 - perror("bind error!\n");  
41 - exit(1);  
42 - }  
43 -  
44 - while (1)  
45 - {  
46 - printf("waiting for client ...\n");  
47 -  
48 - res = recv(sfd, buf, BUF_SIZE, 0);  
49 - if (res == -1)  
50 - {  
51 - perror("recvfrom error\n");  
52 - exit(1);  
53 - }  
54 - printf("revceived data : %s\n", buf);  
55 -  
56 - snprintf(buf, BUF_SIZE, "hello client! Total reveive : %d.", res);  
57 -// // res = sendto(sfd, buf, strlen(buf), 0, (struct sockaddr*)&client_addr, client_addr_len);  
58 -// res = send(sfd, buf, strlen(buf), 0);  
59 -// if (res != strlen(buf) )  
60 -// {  
61 -// perror("sendto error\n");  
62 -// exit(1);  
63 -// }  
64 -  
65 -// printf("send %d bytes to peer", res);  
66 -  
67 -// printf("send data < %s > to client\n\n", buf);  
68 - }  
69 -}  
70 \ No newline at end of file 0 \ No newline at end of file
src/decoder/test_28181.cpp 0 → 100644
  1 +#include "./interface/DecoderManager.h"
  2 +#include <mutex>
  3 +#include <thread>
  4 +#include <chrono>
  5 +#include "../common/logger.hpp"
  6 +#include "./gb28181/sip/SipServer.h"
  7 +
  8 +using namespace std;
  9 +
  10 +struct decode_cbk_userdata{
  11 + string task_id;
  12 + void* opaque;
  13 + void* opaque1;
  14 +};
  15 +
  16 +deque<DeviceMemory*> m_RgbDataList;
  17 +mutex m_DataListMtx;
  18 +
  19 +thread* m_pAlgorthimThread{nullptr};
  20 +
  21 +bool m_bfinish{false};
  22 +int m_devId = 0;
  23 +const char* task_id = "test0";
  24 +int skip_frame_ = 5;
  25 +int m_batch_size = 20;
  26 +
  27 +
  28 +void algorthim_process_thread();
  29 +
  30 +void snap_shot_thread();
  31 +
  32 +void post_decod_cbk(const void * userPtr, DeviceMemory* devFrame){
  33 + do{
  34 + if(m_bfinish){
  35 + break;
  36 + }
  37 + m_DataListMtx.lock();
  38 + if(m_RgbDataList.size() >= 30){
  39 + m_DataListMtx.unlock();
  40 + std::this_thread::sleep_for(std::chrono::milliseconds(3));
  41 + continue;
  42 + }
  43 + m_RgbDataList.push_back(devFrame);
  44 + m_DataListMtx.unlock();
  45 + break;
  46 + }while (true);
  47 +}
  48 +
  49 +void decode_finished_cbk(const void * userPtr){
  50 + decode_cbk_userdata* ptr = (decode_cbk_userdata*)userPtr;
  51 + if (ptr!= nullptr){
  52 + printf("task finished: %s \n", ptr->task_id.c_str());
  53 + delete ptr;
  54 + ptr = nullptr;
  55 + }
  56 +}
  57 +
  58 +bool create_task(string task_id) {
  59 +
  60 + // 创建解码任务
  61 + DecoderManager* pDecManager = DecoderManager::getInstance();
  62 +
  63 + MgrDecConfig config;
  64 + config.name = task_id;
  65 + config.cfg.uri = "/data/share/data/Street.uvf";
  66 + config.cfg.post_decoded_cbk = post_decod_cbk;
  67 + config.cfg.decode_finished_cbk = decode_finished_cbk;
  68 + config.cfg.force_tcp = true; // rtsp用tcp
  69 + config.cfg.gpuid = to_string(m_devId);
  70 + config.cfg.skip_frame = skip_frame_;
  71 +
  72 + config.dec_type = DECODER_TYPE_DVPP;
  73 +
  74 + AbstractDecoder* dec = pDecManager->createDecoder(config);
  75 + if (!dec){
  76 + printf("创建解码器失败 \n");
  77 + return false;
  78 + }
  79 +
  80 + // decode_cbk_userdata* userPtr = new decode_cbk_userdata;
  81 + // userPtr->task_id = string(task_id);
  82 + // pDecManager->setPostDecArg(config.name, userPtr);
  83 + // pDecManager->setFinishedDecArg(config.name, userPtr);
  84 +
  85 + dec->setSnapTimeInterval(1000);
  86 +
  87 +
  88 + int input_image_width = 0;
  89 + int input_image_height = 0;
  90 + pDecManager->getResolution(config.name, input_image_width, input_image_height);
  91 +
  92 + pDecManager->startDecodeByName(config.name);
  93 + // pDecManager->closeAllDecoder();
  94 +
  95 + return true;
  96 +}
  97 +
  98 +bool create_task_28181(string task_id) {
  99 +
  100 + // 创建解码任务
  101 + DecoderManager* pDecManager = DecoderManager::getInstance();
  102 +
  103 + MgrDecConfig config;
  104 + config.name = task_id;
  105 + config.cfg.uri = "34020000001310004065";
  106 + config.cfg.post_decoded_cbk = post_decod_cbk;
  107 + config.cfg.decode_finished_cbk = decode_finished_cbk;
  108 + config.cfg.force_tcp = false; // rtsp用tcp
  109 + config.cfg.gpuid = to_string(m_devId);
  110 + config.cfg.skip_frame = skip_frame_;
  111 +
  112 + config.dec_type = DECODER_TYPE_DVPP_GB28181;
  113 +
  114 + AbstractDecoder* dec = pDecManager->createDecoder(config);
  115 + if (!dec){
  116 + printf("创建解码器失败 \n");
  117 + return false;
  118 + }
  119 +
  120 + // decode_cbk_userdata* userPtr = new decode_cbk_userdata;
  121 + // userPtr->task_id = string(task_id);
  122 + // pDecManager->setPostDecArg(config.name, userPtr);
  123 + // pDecManager->setFinishedDecArg(config.name, userPtr);
  124 +
  125 + dec->setSnapTimeInterval(1000);
  126 +
  127 +
  128 + int input_image_width = 0;
  129 + int input_image_height = 0;
  130 + pDecManager->getResolution(config.name, input_image_width, input_image_height);
  131 +
  132 + pDecManager->startDecodeByName(config.name);
  133 + // pDecManager->closeAllDecoder();
  134 +
  135 + return true;
  136 +}
  137 +
  138 +int main(){
  139 +
  140 + set_default_logger(LogLevel(0), "test_decode","logs/main.log", 64 * 1024 * 1024, 64 * 1024 * 1024);
  141 + LOG_INFO("编译时间:{} {}", __DATE__, __TIME__);
  142 +
  143 + printf("start... \n");
  144 +
  145 + ServerInfo info(
  146 + "SY_Sip_Server",
  147 + "12345678",
  148 + "192.168.60.179",
  149 + 15060,
  150 + "34020000002000000002",
  151 + "3402000000",
  152 + "sy123456",
  153 + 1800,
  154 + 3600);
  155 +
  156 + SipServer* pSipServer = SipServer::getInstance();
  157 + pSipServer->Init(info);
  158 +
  159 +
  160 + DecoderManager* pDecManager = DecoderManager::getInstance();
  161 +
  162 +
  163 + // 创建算法线程
  164 + m_pAlgorthimThread = new thread([](void* arg) {
  165 + algorthim_process_thread();
  166 + return (void*)0;
  167 + }
  168 + , nullptr);
  169 +
  170 + thread snap_thread = thread([](void* arg) {
  171 + snap_shot_thread();
  172 + return (void*)0;
  173 + }
  174 + , nullptr);
  175 +
  176 +
  177 +
  178 + char ch = 'a';
  179 + int task_id = 1;
  180 +
  181 + while (ch != 'q') {
  182 + ch = getchar();
  183 + switch (ch)
  184 + {
  185 + case '4':
  186 + for (size_t i = 0; i < 4; i++)
  187 + {
  188 + create_task(to_string(task_id));
  189 + task_id++;
  190 + std::this_thread::sleep_for(std::chrono::seconds(1));
  191 + }
  192 + break;
  193 + case 'a':
  194 + create_task(to_string(task_id));
  195 + task_id++;
  196 + std::this_thread::sleep_for(std::chrono::seconds(1));
  197 + break;
  198 + case 'c':
  199 + pDecManager->closeAllDecoder();
  200 + break;
  201 + case 'g':
  202 + create_task_28181(to_string(task_id));
  203 + task_id++;
  204 + std::this_thread::sleep_for(std::chrono::seconds(1));
  205 + default:
  206 + break;
  207 + }
  208 + }
  209 +}
  210 +
  211 +void do_work(vector<DeviceMemory*> vec_gpuMem){
  212 + for(int i=0;i < vec_gpuMem.size(); i++){
  213 + DeviceMemory* mem = vec_gpuMem[i];
  214 + printf("task:%s width:%d height:%d ts:%lld \n", mem->getId().c_str(), mem->getWidth(), mem->getHeight(), mem->getTimesstamp());
  215 + }
  216 +}
  217 +
  218 +void algorthim_process_thread(){
  219 +
  220 + while (true){
  221 + if(m_bfinish){
  222 + break;
  223 + }
  224 +
  225 + vector<DeviceMemory*> vec_gpuMem;
  226 + m_DataListMtx.lock();
  227 + while (!m_RgbDataList.empty()){
  228 + DeviceMemory* gpuMem = m_RgbDataList.front();
  229 + if(gpuMem->getMem() == nullptr){
  230 + // 错误数据,直接删除
  231 + delete gpuMem;
  232 + gpuMem = nullptr;
  233 + printf("mem is null \n");
  234 + } else {
  235 + vec_gpuMem.push_back(gpuMem);
  236 + }
  237 + m_RgbDataList.pop_front();
  238 + if(vec_gpuMem.size() >= m_batch_size){
  239 + break;
  240 + }
  241 + }
  242 + m_DataListMtx.unlock();
  243 +
  244 + if(vec_gpuMem.size() <= 0){
  245 + std::this_thread::sleep_for(std::chrono::milliseconds(3));
  246 + continue;
  247 + }
  248 +
  249 + // do work
  250 + do_work(vec_gpuMem);
  251 +
  252 + for(int i=0;i < vec_gpuMem.size(); i++){
  253 + DeviceMemory* mem = vec_gpuMem[i];
  254 + if(mem->getSize() <= 0){
  255 + continue;
  256 + }
  257 + delete mem;
  258 + mem = nullptr;
  259 + }
  260 + // vec_gpuMem.clear();
  261 +
  262 + vector<DeviceMemory*>().swap(vec_gpuMem);
  263 +
  264 + }
  265 +
  266 + printf("algorthim_process_thread exit. \n");
  267 +}
  268 +
  269 +void snap_shot_thread(){
  270 + DecoderManager* pDecManager = DecoderManager::getInstance();
  271 + while (true){
  272 + if(m_bfinish){
  273 + break;
  274 + }
  275 +
  276 + vector<DeviceMemory*> vec_devMem = pDecManager->timing_snapshot_all();
  277 + for(auto devMem : vec_devMem){
  278 + delete devMem;
  279 + devMem = nullptr;
  280 + }
  281 + // vec_devMem.clear();
  282 +
  283 + vector<DeviceMemory*>().swap(vec_devMem);
  284 +
  285 + std::this_thread::sleep_for(std::chrono::milliseconds(600));
  286 +
  287 + }
  288 +}
0 \ No newline at end of file 289 \ No newline at end of file
src/decoder/test_decoder.cpp renamed to src/decoder/test_decoder.cpp.dvpp
src/demo/demo.cpp
@@ -1147,8 +1147,18 @@ void test_gpu(int gpuID){ @@ -1147,8 +1147,18 @@ void test_gpu(int gpuID){
1147 1147
1148 // } 1148 // }
1149 1149
1150 - createTask(handle, algor_vec2, 8, false);  
1151 - createTask(handle, algor_vec2, 27, false); 1150 + createTask(handle, algor_vec2, 0, false);
  1151 + createTask(handle, algor_vec2, 2, false);
  1152 + createTask(handle, algor_vec2, 0, false);
  1153 + createTask(handle, algor_vec2, 2, false);
  1154 + createTask(handle, algor_vec2, 0, false);
  1155 + createTask(handle, algor_vec2, 2, false);
  1156 + createTask(handle, algor_vec2, 0, false);
  1157 + createTask(handle, algor_vec2, 2, false);
  1158 + createTask(handle, algor_vec2, 0, false);
  1159 + createTask(handle, algor_vec2, 2, false);
  1160 + createTask(handle, algor_vec2, 0, false);
  1161 + createTask(handle, algor_vec2, 2, false);
1152 1162
1153 while (getchar() != 'q'); 1163 while (getchar() != 'q');
1154 1164