Commit 5b86d7710ad0db2b70cdc9bc75123f657949122b
1 parent
74d1e6a8
实现GB28181 UDP 基于dvpp的解码
Showing
36 changed files
with
667 additions
and
8256 deletions
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 "C" { | @@ -13,8 +11,6 @@ extern "C" { | ||
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 "C" { | @@ -25,6 +21,7 @@ extern "C" { | ||
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& cfg){ | @@ -123,6 +114,8 @@ bool DvppGB28181Decoder::init(FFDecConfig& 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 &width, int &height ){ | @@ -356,6 +351,12 @@ bool DvppGB28181Decoder::getResolution( int &width, int &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& cfg){ | @@ -367,4 +368,16 @@ bool DvppGB28181Decoder::isSurport(FFDecConfig& 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, ®); | ||
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 | - // 中 or 中 | ||
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 |