libzmq 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (300) hide show
  1. data/LICENSE +703 -0
  2. data/README.md +31 -0
  3. data/lib/libzmq.rb +17 -0
  4. data/lib/libzmq/ffi-rzmq.rb +3 -0
  5. data/libzmq/Makefile +5 -0
  6. data/libzmq/extconf.rb +24 -0
  7. data/libzmq/zeromq-2.1.7/AUTHORS +92 -0
  8. data/libzmq/zeromq-2.1.7/COPYING +674 -0
  9. data/libzmq/zeromq-2.1.7/COPYING.LESSER +206 -0
  10. data/libzmq/zeromq-2.1.7/ChangeLog +15620 -0
  11. data/libzmq/zeromq-2.1.7/INSTALL +237 -0
  12. data/libzmq/zeromq-2.1.7/MAINTAINERS +56 -0
  13. data/libzmq/zeromq-2.1.7/Makefile.am +42 -0
  14. data/libzmq/zeromq-2.1.7/Makefile.in +779 -0
  15. data/libzmq/zeromq-2.1.7/NEWS +275 -0
  16. data/libzmq/zeromq-2.1.7/README +39 -0
  17. data/libzmq/zeromq-2.1.7/acinclude.m4 +582 -0
  18. data/libzmq/zeromq-2.1.7/aclocal.m4 +1206 -0
  19. data/libzmq/zeromq-2.1.7/autogen.sh +45 -0
  20. data/libzmq/zeromq-2.1.7/builds/msvc/Makefile.am +8 -0
  21. data/libzmq/zeromq-2.1.7/builds/msvc/Makefile.in +390 -0
  22. data/libzmq/zeromq-2.1.7/builds/msvc/c_local_lat/c_local_lat.vcproj +176 -0
  23. data/libzmq/zeromq-2.1.7/builds/msvc/c_local_thr/c_local_thr.vcproj +176 -0
  24. data/libzmq/zeromq-2.1.7/builds/msvc/c_remote_lat/c_remote_lat.vcproj +176 -0
  25. data/libzmq/zeromq-2.1.7/builds/msvc/c_remote_thr/c_remote_thr.vcproj +176 -0
  26. data/libzmq/zeromq-2.1.7/builds/msvc/libzmq/libzmq.vcproj +783 -0
  27. data/libzmq/zeromq-2.1.7/builds/msvc/msvc.sln +89 -0
  28. data/libzmq/zeromq-2.1.7/builds/msvc/platform.hpp +32 -0
  29. data/libzmq/zeromq-2.1.7/builds/redhat/zeromq.spec.in +139 -0
  30. data/libzmq/zeromq-2.1.7/config/compile +143 -0
  31. data/libzmq/zeromq-2.1.7/config/config.guess +1502 -0
  32. data/libzmq/zeromq-2.1.7/config/config.sub +1714 -0
  33. data/libzmq/zeromq-2.1.7/config/depcomp +630 -0
  34. data/libzmq/zeromq-2.1.7/config/install-sh +520 -0
  35. data/libzmq/zeromq-2.1.7/config/libtool.m4 +7377 -0
  36. data/libzmq/zeromq-2.1.7/config/ltmain.sh +8413 -0
  37. data/libzmq/zeromq-2.1.7/config/ltoptions.m4 +368 -0
  38. data/libzmq/zeromq-2.1.7/config/ltsugar.m4 +123 -0
  39. data/libzmq/zeromq-2.1.7/config/ltversion.m4 +23 -0
  40. data/libzmq/zeromq-2.1.7/config/lt~obsolete.m4 +92 -0
  41. data/libzmq/zeromq-2.1.7/config/missing +376 -0
  42. data/libzmq/zeromq-2.1.7/configure +21645 -0
  43. data/libzmq/zeromq-2.1.7/configure.in +380 -0
  44. data/libzmq/zeromq-2.1.7/doc/Makefile.am +46 -0
  45. data/libzmq/zeromq-2.1.7/doc/Makefile.in +546 -0
  46. data/libzmq/zeromq-2.1.7/doc/asciidoc.conf +56 -0
  47. data/libzmq/zeromq-2.1.7/doc/zmq.7 +242 -0
  48. data/libzmq/zeromq-2.1.7/doc/zmq.html +846 -0
  49. data/libzmq/zeromq-2.1.7/doc/zmq.txt +218 -0
  50. data/libzmq/zeromq-2.1.7/doc/zmq_bind.3 +166 -0
  51. data/libzmq/zeromq-2.1.7/doc/zmq_bind.html +746 -0
  52. data/libzmq/zeromq-2.1.7/doc/zmq_bind.txt +91 -0
  53. data/libzmq/zeromq-2.1.7/doc/zmq_close.3 +81 -0
  54. data/libzmq/zeromq-2.1.7/doc/zmq_close.html +645 -0
  55. data/libzmq/zeromq-2.1.7/doc/zmq_close.txt +52 -0
  56. data/libzmq/zeromq-2.1.7/doc/zmq_connect.3 +161 -0
  57. data/libzmq/zeromq-2.1.7/doc/zmq_connect.html +732 -0
  58. data/libzmq/zeromq-2.1.7/doc/zmq_connect.txt +89 -0
  59. data/libzmq/zeromq-2.1.7/doc/zmq_cpp.7 +410 -0
  60. data/libzmq/zeromq-2.1.7/doc/zmq_cpp.html +765 -0
  61. data/libzmq/zeromq-2.1.7/doc/zmq_cpp.txt +212 -0
  62. data/libzmq/zeromq-2.1.7/doc/zmq_device.3 +140 -0
  63. data/libzmq/zeromq-2.1.7/doc/zmq_device.html +736 -0
  64. data/libzmq/zeromq-2.1.7/doc/zmq_device.txt +138 -0
  65. data/libzmq/zeromq-2.1.7/doc/zmq_epgm.7 +209 -0
  66. data/libzmq/zeromq-2.1.7/doc/zmq_epgm.html +749 -0
  67. data/libzmq/zeromq-2.1.7/doc/zmq_epgm.txt +162 -0
  68. data/libzmq/zeromq-2.1.7/doc/zmq_errno.3 +78 -0
  69. data/libzmq/zeromq-2.1.7/doc/zmq_errno.html +634 -0
  70. data/libzmq/zeromq-2.1.7/doc/zmq_errno.txt +50 -0
  71. data/libzmq/zeromq-2.1.7/doc/zmq_getsockopt.3 +944 -0
  72. data/libzmq/zeromq-2.1.7/doc/zmq_getsockopt.html +1713 -0
  73. data/libzmq/zeromq-2.1.7/doc/zmq_getsockopt.txt +407 -0
  74. data/libzmq/zeromq-2.1.7/doc/zmq_init.3 +71 -0
  75. data/libzmq/zeromq-2.1.7/doc/zmq_init.html +635 -0
  76. data/libzmq/zeromq-2.1.7/doc/zmq_init.txt +51 -0
  77. data/libzmq/zeromq-2.1.7/doc/zmq_inproc.7 +115 -0
  78. data/libzmq/zeromq-2.1.7/doc/zmq_inproc.html +669 -0
  79. data/libzmq/zeromq-2.1.7/doc/zmq_inproc.txt +89 -0
  80. data/libzmq/zeromq-2.1.7/doc/zmq_ipc.7 +109 -0
  81. data/libzmq/zeromq-2.1.7/doc/zmq_ipc.html +662 -0
  82. data/libzmq/zeromq-2.1.7/doc/zmq_ipc.txt +80 -0
  83. data/libzmq/zeromq-2.1.7/doc/zmq_msg_close.3 +81 -0
  84. data/libzmq/zeromq-2.1.7/doc/zmq_msg_close.html +647 -0
  85. data/libzmq/zeromq-2.1.7/doc/zmq_msg_close.txt +55 -0
  86. data/libzmq/zeromq-2.1.7/doc/zmq_msg_copy.3 +95 -0
  87. data/libzmq/zeromq-2.1.7/doc/zmq_msg_copy.html +656 -0
  88. data/libzmq/zeromq-2.1.7/doc/zmq_msg_copy.txt +57 -0
  89. data/libzmq/zeromq-2.1.7/doc/zmq_msg_data.3 +76 -0
  90. data/libzmq/zeromq-2.1.7/doc/zmq_msg_data.html +633 -0
  91. data/libzmq/zeromq-2.1.7/doc/zmq_msg_data.txt +48 -0
  92. data/libzmq/zeromq-2.1.7/doc/zmq_msg_init.3 +110 -0
  93. data/libzmq/zeromq-2.1.7/doc/zmq_msg_init.html +656 -0
  94. data/libzmq/zeromq-2.1.7/doc/zmq_msg_init.txt +65 -0
  95. data/libzmq/zeromq-2.1.7/doc/zmq_msg_init_data.3 +138 -0
  96. data/libzmq/zeromq-2.1.7/doc/zmq_msg_init_data.html +678 -0
  97. data/libzmq/zeromq-2.1.7/doc/zmq_msg_init_data.txt +83 -0
  98. data/libzmq/zeromq-2.1.7/doc/zmq_msg_init_size.3 +97 -0
  99. data/libzmq/zeromq-2.1.7/doc/zmq_msg_init_size.html +656 -0
  100. data/libzmq/zeromq-2.1.7/doc/zmq_msg_init_size.txt +58 -0
  101. data/libzmq/zeromq-2.1.7/doc/zmq_msg_move.3 +79 -0
  102. data/libzmq/zeromq-2.1.7/doc/zmq_msg_move.html +645 -0
  103. data/libzmq/zeromq-2.1.7/doc/zmq_msg_move.txt +52 -0
  104. data/libzmq/zeromq-2.1.7/doc/zmq_msg_size.3 +76 -0
  105. data/libzmq/zeromq-2.1.7/doc/zmq_msg_size.html +633 -0
  106. data/libzmq/zeromq-2.1.7/doc/zmq_msg_size.txt +48 -0
  107. data/libzmq/zeromq-2.1.7/doc/zmq_pgm.7 +209 -0
  108. data/libzmq/zeromq-2.1.7/doc/zmq_pgm.html +749 -0
  109. data/libzmq/zeromq-2.1.7/doc/zmq_pgm.txt +162 -0
  110. data/libzmq/zeromq-2.1.7/doc/zmq_poll.3 +204 -0
  111. data/libzmq/zeromq-2.1.7/doc/zmq_poll.html +755 -0
  112. data/libzmq/zeromq-2.1.7/doc/zmq_poll.txt +132 -0
  113. data/libzmq/zeromq-2.1.7/doc/zmq_recv.3 +172 -0
  114. data/libzmq/zeromq-2.1.7/doc/zmq_recv.html +746 -0
  115. data/libzmq/zeromq-2.1.7/doc/zmq_recv.txt +121 -0
  116. data/libzmq/zeromq-2.1.7/doc/zmq_send.3 +185 -0
  117. data/libzmq/zeromq-2.1.7/doc/zmq_send.html +755 -0
  118. data/libzmq/zeromq-2.1.7/doc/zmq_send.txt +120 -0
  119. data/libzmq/zeromq-2.1.7/doc/zmq_setsockopt.3 +878 -0
  120. data/libzmq/zeromq-2.1.7/doc/zmq_setsockopt.html +1603 -0
  121. data/libzmq/zeromq-2.1.7/doc/zmq_setsockopt.txt +382 -0
  122. data/libzmq/zeromq-2.1.7/doc/zmq_socket.3 +779 -0
  123. data/libzmq/zeromq-2.1.7/doc/zmq_socket.html +1424 -0
  124. data/libzmq/zeromq-2.1.7/doc/zmq_socket.txt +342 -0
  125. data/libzmq/zeromq-2.1.7/doc/zmq_strerror.3 +78 -0
  126. data/libzmq/zeromq-2.1.7/doc/zmq_strerror.html +634 -0
  127. data/libzmq/zeromq-2.1.7/doc/zmq_strerror.txt +55 -0
  128. data/libzmq/zeromq-2.1.7/doc/zmq_tcp.7 +244 -0
  129. data/libzmq/zeromq-2.1.7/doc/zmq_tcp.html +755 -0
  130. data/libzmq/zeromq-2.1.7/doc/zmq_tcp.txt +162 -0
  131. data/libzmq/zeromq-2.1.7/doc/zmq_term.3 +135 -0
  132. data/libzmq/zeromq-2.1.7/doc/zmq_term.html +672 -0
  133. data/libzmq/zeromq-2.1.7/doc/zmq_term.txt +65 -0
  134. data/libzmq/zeromq-2.1.7/doc/zmq_version.3 +78 -0
  135. data/libzmq/zeromq-2.1.7/doc/zmq_version.html +632 -0
  136. data/libzmq/zeromq-2.1.7/doc/zmq_version.txt +53 -0
  137. data/libzmq/zeromq-2.1.7/foreign/openpgm/Makefile.am +8 -0
  138. data/libzmq/zeromq-2.1.7/foreign/openpgm/Makefile.in +588 -0
  139. data/libzmq/zeromq-2.1.7/foreign/openpgm/libpgm-5.1.115~dfsg.tar.gz +0 -0
  140. data/libzmq/zeromq-2.1.7/foreign/xmlParser/xmlParser.cpp +2923 -0
  141. data/libzmq/zeromq-2.1.7/foreign/xmlParser/xmlParser.hpp +762 -0
  142. data/libzmq/zeromq-2.1.7/include/zmq.h +269 -0
  143. data/libzmq/zeromq-2.1.7/include/zmq.hpp +301 -0
  144. data/libzmq/zeromq-2.1.7/include/zmq_utils.h +64 -0
  145. data/libzmq/zeromq-2.1.7/perf/Makefile.am +21 -0
  146. data/libzmq/zeromq-2.1.7/perf/Makefile.in +566 -0
  147. data/libzmq/zeromq-2.1.7/perf/inproc_lat.cpp +232 -0
  148. data/libzmq/zeromq-2.1.7/perf/inproc_thr.cpp +246 -0
  149. data/libzmq/zeromq-2.1.7/perf/local_lat.cpp +108 -0
  150. data/libzmq/zeromq-2.1.7/perf/local_thr.cpp +138 -0
  151. data/libzmq/zeromq-2.1.7/perf/remote_lat.cpp +121 -0
  152. data/libzmq/zeromq-2.1.7/perf/remote_thr.cpp +104 -0
  153. data/libzmq/zeromq-2.1.7/src/Makefile.am +155 -0
  154. data/libzmq/zeromq-2.1.7/src/Makefile.in +1320 -0
  155. data/libzmq/zeromq-2.1.7/src/array.hpp +147 -0
  156. data/libzmq/zeromq-2.1.7/src/atomic_counter.hpp +164 -0
  157. data/libzmq/zeromq-2.1.7/src/atomic_ptr.hpp +159 -0
  158. data/libzmq/zeromq-2.1.7/src/blob.hpp +34 -0
  159. data/libzmq/zeromq-2.1.7/src/clock.cpp +118 -0
  160. data/libzmq/zeromq-2.1.7/src/clock.hpp +60 -0
  161. data/libzmq/zeromq-2.1.7/src/command.cpp +39 -0
  162. data/libzmq/zeromq-2.1.7/src/command.hpp +147 -0
  163. data/libzmq/zeromq-2.1.7/src/config.hpp +88 -0
  164. data/libzmq/zeromq-2.1.7/src/connect_session.cpp +119 -0
  165. data/libzmq/zeromq-2.1.7/src/connect_session.hpp +65 -0
  166. data/libzmq/zeromq-2.1.7/src/ctx.cpp +322 -0
  167. data/libzmq/zeromq-2.1.7/src/ctx.hpp +159 -0
  168. data/libzmq/zeromq-2.1.7/src/decoder.cpp +129 -0
  169. data/libzmq/zeromq-2.1.7/src/decoder.hpp +207 -0
  170. data/libzmq/zeromq-2.1.7/src/device.cpp +120 -0
  171. data/libzmq/zeromq-2.1.7/src/device.hpp +32 -0
  172. data/libzmq/zeromq-2.1.7/src/devpoll.cpp +190 -0
  173. data/libzmq/zeromq-2.1.7/src/devpoll.hpp +100 -0
  174. data/libzmq/zeromq-2.1.7/src/dist.cpp +200 -0
  175. data/libzmq/zeromq-2.1.7/src/dist.hpp +90 -0
  176. data/libzmq/zeromq-2.1.7/src/encoder.cpp +90 -0
  177. data/libzmq/zeromq-2.1.7/src/encoder.hpp +184 -0
  178. data/libzmq/zeromq-2.1.7/src/epoll.cpp +177 -0
  179. data/libzmq/zeromq-2.1.7/src/epoll.hpp +96 -0
  180. data/libzmq/zeromq-2.1.7/src/err.cpp +238 -0
  181. data/libzmq/zeromq-2.1.7/src/err.hpp +145 -0
  182. data/libzmq/zeromq-2.1.7/src/fd.hpp +45 -0
  183. data/libzmq/zeromq-2.1.7/src/fq.cpp +164 -0
  184. data/libzmq/zeromq-2.1.7/src/fq.hpp +80 -0
  185. data/libzmq/zeromq-2.1.7/src/i_engine.hpp +53 -0
  186. data/libzmq/zeromq-2.1.7/src/i_inout.hpp +50 -0
  187. data/libzmq/zeromq-2.1.7/src/i_poll_events.hpp +46 -0
  188. data/libzmq/zeromq-2.1.7/src/io_object.cpp +107 -0
  189. data/libzmq/zeromq-2.1.7/src/io_object.hpp +78 -0
  190. data/libzmq/zeromq-2.1.7/src/io_thread.cpp +109 -0
  191. data/libzmq/zeromq-2.1.7/src/io_thread.hpp +88 -0
  192. data/libzmq/zeromq-2.1.7/src/ip.cpp +339 -0
  193. data/libzmq/zeromq-2.1.7/src/ip.hpp +68 -0
  194. data/libzmq/zeromq-2.1.7/src/kqueue.cpp +194 -0
  195. data/libzmq/zeromq-2.1.7/src/kqueue.hpp +103 -0
  196. data/libzmq/zeromq-2.1.7/src/lb.cpp +174 -0
  197. data/libzmq/zeromq-2.1.7/src/lb.hpp +79 -0
  198. data/libzmq/zeromq-2.1.7/src/libzmq.pc.in +10 -0
  199. data/libzmq/zeromq-2.1.7/src/likely.hpp +33 -0
  200. data/libzmq/zeromq-2.1.7/src/mailbox.cpp +382 -0
  201. data/libzmq/zeromq-2.1.7/src/mailbox.hpp +62 -0
  202. data/libzmq/zeromq-2.1.7/src/msg_content.hpp +52 -0
  203. data/libzmq/zeromq-2.1.7/src/mutex.hpp +121 -0
  204. data/libzmq/zeromq-2.1.7/src/named_session.cpp +85 -0
  205. data/libzmq/zeromq-2.1.7/src/named_session.hpp +57 -0
  206. data/libzmq/zeromq-2.1.7/src/object.cpp +467 -0
  207. data/libzmq/zeromq-2.1.7/src/object.hpp +127 -0
  208. data/libzmq/zeromq-2.1.7/src/options.cpp +336 -0
  209. data/libzmq/zeromq-2.1.7/src/options.hpp +87 -0
  210. data/libzmq/zeromq-2.1.7/src/own.cpp +214 -0
  211. data/libzmq/zeromq-2.1.7/src/own.hpp +140 -0
  212. data/libzmq/zeromq-2.1.7/src/pair.cpp +180 -0
  213. data/libzmq/zeromq-2.1.7/src/pair.hpp +76 -0
  214. data/libzmq/zeromq-2.1.7/src/pgm_receiver.cpp +259 -0
  215. data/libzmq/zeromq-2.1.7/src/pgm_receiver.hpp +129 -0
  216. data/libzmq/zeromq-2.1.7/src/pgm_sender.cpp +215 -0
  217. data/libzmq/zeromq-2.1.7/src/pgm_sender.hpp +105 -0
  218. data/libzmq/zeromq-2.1.7/src/pgm_socket.cpp +705 -0
  219. data/libzmq/zeromq-2.1.7/src/pgm_socket.hpp +118 -0
  220. data/libzmq/zeromq-2.1.7/src/pipe.cpp +409 -0
  221. data/libzmq/zeromq-2.1.7/src/pipe.hpp +214 -0
  222. data/libzmq/zeromq-2.1.7/src/platform.hpp.in +228 -0
  223. data/libzmq/zeromq-2.1.7/src/poll.cpp +180 -0
  224. data/libzmq/zeromq-2.1.7/src/poll.hpp +104 -0
  225. data/libzmq/zeromq-2.1.7/src/poller.hpp +73 -0
  226. data/libzmq/zeromq-2.1.7/src/poller_base.cpp +99 -0
  227. data/libzmq/zeromq-2.1.7/src/poller_base.hpp +84 -0
  228. data/libzmq/zeromq-2.1.7/src/pub.cpp +31 -0
  229. data/libzmq/zeromq-2.1.7/src/pub.hpp +44 -0
  230. data/libzmq/zeromq-2.1.7/src/pull.cpp +61 -0
  231. data/libzmq/zeromq-2.1.7/src/pull.hpp +60 -0
  232. data/libzmq/zeromq-2.1.7/src/push.cpp +62 -0
  233. data/libzmq/zeromq-2.1.7/src/push.hpp +59 -0
  234. data/libzmq/zeromq-2.1.7/src/reaper.cpp +121 -0
  235. data/libzmq/zeromq-2.1.7/src/reaper.hpp +77 -0
  236. data/libzmq/zeromq-2.1.7/src/rep.cpp +131 -0
  237. data/libzmq/zeromq-2.1.7/src/rep.hpp +59 -0
  238. data/libzmq/zeromq-2.1.7/src/req.cpp +121 -0
  239. data/libzmq/zeromq-2.1.7/src/req.hpp +58 -0
  240. data/libzmq/zeromq-2.1.7/src/select.cpp +211 -0
  241. data/libzmq/zeromq-2.1.7/src/select.hpp +116 -0
  242. data/libzmq/zeromq-2.1.7/src/semaphore.hpp +189 -0
  243. data/libzmq/zeromq-2.1.7/src/session.cpp +347 -0
  244. data/libzmq/zeromq-2.1.7/src/session.hpp +150 -0
  245. data/libzmq/zeromq-2.1.7/src/socket_base.cpp +811 -0
  246. data/libzmq/zeromq-2.1.7/src/socket_base.hpp +207 -0
  247. data/libzmq/zeromq-2.1.7/src/stdint.hpp +63 -0
  248. data/libzmq/zeromq-2.1.7/src/sub.cpp +75 -0
  249. data/libzmq/zeromq-2.1.7/src/sub.hpp +50 -0
  250. data/libzmq/zeromq-2.1.7/src/swap.cpp +325 -0
  251. data/libzmq/zeromq-2.1.7/src/swap.hpp +123 -0
  252. data/libzmq/zeromq-2.1.7/src/tcp_connecter.cpp +310 -0
  253. data/libzmq/zeromq-2.1.7/src/tcp_connecter.hpp +81 -0
  254. data/libzmq/zeromq-2.1.7/src/tcp_listener.cpp +371 -0
  255. data/libzmq/zeromq-2.1.7/src/tcp_listener.hpp +73 -0
  256. data/libzmq/zeromq-2.1.7/src/tcp_socket.cpp +228 -0
  257. data/libzmq/zeromq-2.1.7/src/tcp_socket.hpp +72 -0
  258. data/libzmq/zeromq-2.1.7/src/thread.cpp +97 -0
  259. data/libzmq/zeromq-2.1.7/src/thread.hpp +78 -0
  260. data/libzmq/zeromq-2.1.7/src/transient_session.cpp +41 -0
  261. data/libzmq/zeromq-2.1.7/src/transient_session.hpp +52 -0
  262. data/libzmq/zeromq-2.1.7/src/trie.cpp +181 -0
  263. data/libzmq/zeromq-2.1.7/src/trie.hpp +59 -0
  264. data/libzmq/zeromq-2.1.7/src/uuid.cpp +233 -0
  265. data/libzmq/zeromq-2.1.7/src/uuid.hpp +111 -0
  266. data/libzmq/zeromq-2.1.7/src/windows.hpp +79 -0
  267. data/libzmq/zeromq-2.1.7/src/wire.hpp +99 -0
  268. data/libzmq/zeromq-2.1.7/src/xpub.cpp +76 -0
  269. data/libzmq/zeromq-2.1.7/src/xpub.hpp +61 -0
  270. data/libzmq/zeromq-2.1.7/src/xrep.cpp +337 -0
  271. data/libzmq/zeromq-2.1.7/src/xrep.hpp +116 -0
  272. data/libzmq/zeromq-2.1.7/src/xreq.cpp +74 -0
  273. data/libzmq/zeromq-2.1.7/src/xreq.hpp +65 -0
  274. data/libzmq/zeromq-2.1.7/src/xsub.cpp +172 -0
  275. data/libzmq/zeromq-2.1.7/src/xsub.hpp +80 -0
  276. data/libzmq/zeromq-2.1.7/src/ypipe.hpp +209 -0
  277. data/libzmq/zeromq-2.1.7/src/yqueue.hpp +198 -0
  278. data/libzmq/zeromq-2.1.7/src/zmq.cpp +798 -0
  279. data/libzmq/zeromq-2.1.7/src/zmq_connecter.cpp +166 -0
  280. data/libzmq/zeromq-2.1.7/src/zmq_connecter.hpp +92 -0
  281. data/libzmq/zeromq-2.1.7/src/zmq_engine.cpp +220 -0
  282. data/libzmq/zeromq-2.1.7/src/zmq_engine.hpp +87 -0
  283. data/libzmq/zeromq-2.1.7/src/zmq_init.cpp +216 -0
  284. data/libzmq/zeromq-2.1.7/src/zmq_init.hpp +93 -0
  285. data/libzmq/zeromq-2.1.7/src/zmq_listener.cpp +78 -0
  286. data/libzmq/zeromq-2.1.7/src/zmq_listener.hpp +67 -0
  287. data/libzmq/zeromq-2.1.7/tests/Makefile.am +30 -0
  288. data/libzmq/zeromq-2.1.7/tests/Makefile.in +713 -0
  289. data/libzmq/zeromq-2.1.7/tests/test_hwm.cpp +68 -0
  290. data/libzmq/zeromq-2.1.7/tests/test_pair_inproc.cpp +31 -0
  291. data/libzmq/zeromq-2.1.7/tests/test_pair_ipc.cpp +31 -0
  292. data/libzmq/zeromq-2.1.7/tests/test_pair_tcp.cpp +31 -0
  293. data/libzmq/zeromq-2.1.7/tests/test_reqrep_inproc.cpp +31 -0
  294. data/libzmq/zeromq-2.1.7/tests/test_reqrep_ipc.cpp +31 -0
  295. data/libzmq/zeromq-2.1.7/tests/test_reqrep_tcp.cpp +31 -0
  296. data/libzmq/zeromq-2.1.7/tests/test_shutdown_stress.cpp +87 -0
  297. data/libzmq/zeromq-2.1.7/tests/testutil.hpp +130 -0
  298. data/libzmq/zeromq-2.1.7/version.sh +21 -0
  299. data/libzmq/zeromq-2.1.7/zeromq.spec +139 -0
  300. metadata +348 -0
@@ -0,0 +1,2923 @@
1
+ /**
2
+ ****************************************************************************
3
+ * <P> XML.c - implementation file for basic XML parser written in ANSI C++
4
+ * for portability. It works by using recursion and a node tree for breaking
5
+ * down the elements of an XML document. </P>
6
+ *
7
+ * @version V2.39
8
+ * @author Frank Vanden Berghen
9
+ *
10
+ * NOTE:
11
+ *
12
+ * If you add "#define STRICT_PARSING", on the first line of this file
13
+ * the parser will see the following XML-stream:
14
+ * <a><b>some text</b><b>other text </a>
15
+ * as an error. Otherwise, this tring will be equivalent to:
16
+ * <a><b>some text</b><b>other text</b></a>
17
+ *
18
+ * NOTE:
19
+ *
20
+ * If you add "#define APPROXIMATE_PARSING" on the first line of this file
21
+ * the parser will see the following XML-stream:
22
+ * <data name="n1">
23
+ * <data name="n2">
24
+ * <data name="n3" />
25
+ * as equivalent to the following XML-stream:
26
+ * <data name="n1" />
27
+ * <data name="n2" />
28
+ * <data name="n3" />
29
+ * This can be useful for badly-formed XML-streams but prevent the use
30
+ * of the following XML-stream (problem is: tags at contiguous levels
31
+ * have the same names):
32
+ * <data name="n1">
33
+ * <data name="n2">
34
+ * <data name="n3" />
35
+ * </data>
36
+ * </data>
37
+ *
38
+ * NOTE:
39
+ *
40
+ * If you add "#define _XMLPARSER_NO_MESSAGEBOX_" on the first line of this file
41
+ * the "openFileHelper" function will always display error messages inside the
42
+ * console instead of inside a message-box-window. Message-box-windows are
43
+ * available on windows 9x/NT/2000/XP/Vista only.
44
+ *
45
+ * Copyright (c) 2002, Frank Vanden Berghen
46
+ * All rights reserved.
47
+ *
48
+ * The following license terms apply to projects that are in some way related to
49
+ * the "ZeroMQ project", including applications
50
+ * using "ZeroMQ project" and tools developed
51
+ * for enhancing "ZeroMQ project". All other projects
52
+ * (not related to "ZeroMQ project") have to use this
53
+ * code under the Aladdin Free Public License (AFPL)
54
+ * See the file "AFPL-license.txt" for more informations about the AFPL license.
55
+ * (see http://www.artifex.com/downloads/doc/Public.htm for detailed AFPL terms)
56
+ *
57
+ * Redistribution and use in source and binary forms, with or without
58
+ * modification, are permitted provided that the following conditions are met:
59
+ * * Redistributions of source code must retain the above copyright
60
+ * notice, this list of conditions and the following disclaimer.
61
+ * * Redistributions in binary form must reproduce the above copyright
62
+ * notice, this list of conditions and the following disclaimer in the
63
+ * documentation and/or other materials provided with the distribution.
64
+ * * Neither the name of Frank Vanden Berghen nor the
65
+ * names of its contributors may be used to endorse or promote products
66
+ * derived from this software without specific prior written permission.
67
+ *
68
+ * THIS SOFTWARE IS PROVIDED BY Frank Vanden Berghen ``AS IS'' AND ANY
69
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
70
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
71
+ * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
72
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
73
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
74
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
75
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
76
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
77
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
78
+ *
79
+ ****************************************************************************
80
+ */
81
+
82
+ #if defined _MSC_VER
83
+ #pragma warning (push)
84
+ #pragma warning (disable:4996)
85
+ #endif
86
+
87
+ #ifndef _CRT_SECURE_NO_DEPRECATE
88
+ #define _CRT_SECURE_NO_DEPRECATE
89
+ #endif
90
+ #include "xmlParser.hpp"
91
+ #ifdef _XMLWINDOWS
92
+ //#ifdef _DEBUG
93
+ //#define _CRTDBG_MAP_ALLOC
94
+ //#include <crtdbg.h>
95
+ //#endif
96
+ #define WIN32_LEAN_AND_MEAN
97
+ #include <windows.h> // to have IsTextUnicode, MultiByteToWideChar, WideCharToMultiByte to handle unicode files
98
+ // to have "MessageBoxA" to display error messages for openFilHelper
99
+ #endif
100
+
101
+ #include <memory.h>
102
+ #include <assert.h>
103
+ #include <stdio.h>
104
+ #include <string.h>
105
+ #include <stdlib.h>
106
+
107
+ XMLCSTR XMLNode::getVersion() { return _CXML("v2.39"); }
108
+ void freeXMLString(XMLSTR t){if(t)free(t);}
109
+
110
+ static XMLNode::XMLCharEncoding characterEncoding=XMLNode::char_encoding_UTF8;
111
+ static char guessWideCharChars=1, dropWhiteSpace=1, removeCommentsInMiddleOfText=1;
112
+
113
+ inline int mmin( const int t1, const int t2 ) { return t1 < t2 ? t1 : t2; }
114
+
115
+ // You can modify the initialization of the variable "XMLClearTags" below
116
+ // to change the clearTags that are currently recognized by the library.
117
+ // The number on the second columns is the length of the string inside the
118
+ // first column. The "<!DOCTYPE" declaration must be the second in the list.
119
+ // The "<!--" declaration must be the third in the list.
120
+ typedef struct { XMLCSTR lpszOpen; int openTagLen; XMLCSTR lpszClose;} ALLXMLClearTag;
121
+ static ALLXMLClearTag XMLClearTags[] =
122
+ {
123
+ { _CXML("<![CDATA["),9, _CXML("]]>") },
124
+ { _CXML("<!DOCTYPE"),9, _CXML(">") },
125
+ { _CXML("<!--") ,4, _CXML("-->") },
126
+ { _CXML("<PRE>") ,5, _CXML("</PRE>") },
127
+ // { _CXML("<Script>") ,8, _CXML("</Script>")},
128
+ { NULL ,0, NULL }
129
+ };
130
+
131
+ // You can modify the initialization of the variable "XMLEntities" below
132
+ // to change the character entities that are currently recognized by the library.
133
+ // The number on the second columns is the length of the string inside the
134
+ // first column. Additionally, the syntaxes "&#xA0;" and "&#160;" are recognized.
135
+ typedef struct { XMLCSTR s; int l; XMLCHAR c;} XMLCharacterEntity;
136
+ static XMLCharacterEntity XMLEntities[] =
137
+ {
138
+ { _CXML("&amp;" ), 5, _CXML('&' )},
139
+ { _CXML("&lt;" ), 4, _CXML('<' )},
140
+ { _CXML("&gt;" ), 4, _CXML('>' )},
141
+ { _CXML("&quot;"), 6, _CXML('\"')},
142
+ { _CXML("&apos;"), 6, _CXML('\'')},
143
+ { NULL , 0, '\0' }
144
+ };
145
+
146
+ // When rendering the XMLNode to a string (using the "createXMLString" function),
147
+ // you can ask for a beautiful formatting. This formatting is using the
148
+ // following indentation character:
149
+ #define INDENTCHAR _CXML('\t')
150
+
151
+ // The following function parses the XML errors into a user friendly string.
152
+ // You can edit this to change the output language of the library to something else.
153
+ XMLCSTR XMLNode::getError(XMLError xerror)
154
+ {
155
+ switch (xerror)
156
+ {
157
+ case eXMLErrorNone: return _CXML("No error");
158
+ case eXMLErrorMissingEndTag: return _CXML("Warning: Unmatched end tag");
159
+ case eXMLErrorNoXMLTagFound: return _CXML("Warning: No XML tag found");
160
+ case eXMLErrorEmpty: return _CXML("Error: No XML data");
161
+ case eXMLErrorMissingTagName: return _CXML("Error: Missing start tag name");
162
+ case eXMLErrorMissingEndTagName: return _CXML("Error: Missing end tag name");
163
+ case eXMLErrorUnmatchedEndTag: return _CXML("Error: Unmatched end tag");
164
+ case eXMLErrorUnmatchedEndClearTag: return _CXML("Error: Unmatched clear tag end");
165
+ case eXMLErrorUnexpectedToken: return _CXML("Error: Unexpected token found");
166
+ case eXMLErrorNoElements: return _CXML("Error: No elements found");
167
+ case eXMLErrorFileNotFound: return _CXML("Error: File not found");
168
+ case eXMLErrorFirstTagNotFound: return _CXML("Error: First Tag not found");
169
+ case eXMLErrorUnknownCharacterEntity:return _CXML("Error: Unknown character entity");
170
+ case eXMLErrorCharacterCodeAbove255: return _CXML("Error: Character code above 255 is forbidden in MultiByte char mode.");
171
+ case eXMLErrorCharConversionError: return _CXML("Error: unable to convert between WideChar and MultiByte chars");
172
+ case eXMLErrorCannotOpenWriteFile: return _CXML("Error: unable to open file for writing");
173
+ case eXMLErrorCannotWriteFile: return _CXML("Error: cannot write into file");
174
+
175
+ case eXMLErrorBase64DataSizeIsNotMultipleOf4: return _CXML("Warning: Base64-string length is not a multiple of 4");
176
+ case eXMLErrorBase64DecodeTruncatedData: return _CXML("Warning: Base64-string is truncated");
177
+ case eXMLErrorBase64DecodeIllegalCharacter: return _CXML("Error: Base64-string contains an illegal character");
178
+ case eXMLErrorBase64DecodeBufferTooSmall: return _CXML("Error: Base64 decode output buffer is too small");
179
+ };
180
+ return _CXML("Unknown");
181
+ }
182
+
183
+ /////////////////////////////////////////////////////////////////////////
184
+ // Here start the abstraction layer to be OS-independent //
185
+ /////////////////////////////////////////////////////////////////////////
186
+
187
+ // Here is an abstraction layer to access some common string manipulation functions.
188
+ // The abstraction layer is currently working for gcc, Microsoft Visual Studio 6.0,
189
+ // Microsoft Visual Studio .NET, CC (sun compiler) and Borland C++.
190
+ // If you plan to "port" the library to a new system/compiler, all you have to do is
191
+ // to edit the following lines.
192
+ #ifdef XML_NO_WIDE_CHAR
193
+ char myIsTextWideChar(const void *b, int len) { return FALSE; }
194
+ #else
195
+ #if defined (UNDER_CE) || !defined(_XMLWINDOWS)
196
+ char myIsTextWideChar(const void *b, int len) // inspired by the Wine API: RtlIsTextUnicode
197
+ {
198
+ #ifdef sun
199
+ // for SPARC processors: wchar_t* buffers must always be alligned, otherwise it's a char* buffer.
200
+ if ((((unsigned long)b)%sizeof(wchar_t))!=0) return FALSE;
201
+ #endif
202
+ const wchar_t *s=(const wchar_t*)b;
203
+
204
+ // buffer too small:
205
+ if (len<(int)sizeof(wchar_t)) return FALSE;
206
+
207
+ // odd length test
208
+ if (len&1) return FALSE;
209
+
210
+ /* only checks the first 256 characters */
211
+ len=mmin(256,len/sizeof(wchar_t));
212
+
213
+ // Check for the special byte order:
214
+ if (*((unsigned short*)s) == 0xFFFE) return TRUE; // IS_TEXT_UNICODE_REVERSE_SIGNATURE;
215
+ if (*((unsigned short*)s) == 0xFEFF) return TRUE; // IS_TEXT_UNICODE_SIGNATURE
216
+
217
+ // checks for ASCII characters in the UNICODE stream
218
+ int i,stats=0;
219
+ for (i=0; i<len; i++) if (s[i]<=(unsigned short)255) stats++;
220
+ if (stats>len/2) return TRUE;
221
+
222
+ // Check for UNICODE NULL chars
223
+ for (i=0; i<len; i++) if (!s[i]) return TRUE;
224
+
225
+ return FALSE;
226
+ }
227
+ #else
228
+ char myIsTextWideChar(const void *b,int l) { return (char)IsTextUnicode((CONST LPVOID)b,l,NULL); }
229
+ #endif
230
+ #endif
231
+
232
+ #ifdef _XMLWINDOWS
233
+ // for Microsoft Visual Studio 6.0 and Microsoft Visual Studio .NET and Borland C++ Builder 6.0
234
+ #ifdef _XMLWIDECHAR
235
+ wchar_t *myMultiByteToWideChar(const char *s, XMLNode::XMLCharEncoding ce)
236
+ {
237
+ int i;
238
+ if (ce==XMLNode::char_encoding_UTF8) i=(int)MultiByteToWideChar(CP_UTF8,0 ,s,-1,NULL,0);
239
+ else i=(int)MultiByteToWideChar(CP_ACP ,MB_PRECOMPOSED,s,-1,NULL,0);
240
+ if (i<0) return NULL;
241
+ wchar_t *d=(wchar_t *)malloc((i+1)*sizeof(XMLCHAR));
242
+ if (ce==XMLNode::char_encoding_UTF8) i=(int)MultiByteToWideChar(CP_UTF8,0 ,s,-1,d,i);
243
+ else i=(int)MultiByteToWideChar(CP_ACP ,MB_PRECOMPOSED,s,-1,d,i);
244
+ d[i]=0;
245
+ return d;
246
+ }
247
+ static inline FILE *xfopen(XMLCSTR filename,XMLCSTR mode) { return _wfopen(filename,mode); }
248
+ static inline int xstrlen(XMLCSTR c) { return (int)wcslen(c); }
249
+ static inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) { return _wcsnicmp(c1,c2,l);}
250
+ static inline int xstrncmp(XMLCSTR c1, XMLCSTR c2, int l) { return wcsncmp(c1,c2,l);}
251
+ static inline int xstricmp(XMLCSTR c1, XMLCSTR c2) { return _wcsicmp(c1,c2); }
252
+ static inline XMLSTR xstrstr(XMLCSTR c1, XMLCSTR c2) { return (XMLSTR)wcsstr(c1,c2); }
253
+ static inline XMLSTR xstrcpy(XMLSTR c1, XMLCSTR c2) { return (XMLSTR)wcscpy(c1,c2); }
254
+ #else
255
+ char *myWideCharToMultiByte(const wchar_t *s)
256
+ {
257
+ UINT codePage=CP_ACP; if (characterEncoding==XMLNode::char_encoding_UTF8) codePage=CP_UTF8;
258
+ int i=(int)WideCharToMultiByte(codePage, // code page
259
+ 0, // performance and mapping flags
260
+ s, // wide-character string
261
+ -1, // number of chars in string
262
+ NULL, // buffer for new string
263
+ 0, // size of buffer
264
+ NULL, // default for unmappable chars
265
+ NULL // set when default char used
266
+ );
267
+ if (i<0) return NULL;
268
+ char *d=(char*)malloc(i+1);
269
+ WideCharToMultiByte(codePage, // code page
270
+ 0, // performance and mapping flags
271
+ s, // wide-character string
272
+ -1, // number of chars in string
273
+ d, // buffer for new string
274
+ i, // size of buffer
275
+ NULL, // default for unmappable chars
276
+ NULL // set when default char used
277
+ );
278
+ d[i]=0;
279
+ return d;
280
+ }
281
+ static inline FILE *xfopen(XMLCSTR filename,XMLCSTR mode) { return fopen(filename,mode); }
282
+ static inline int xstrlen(XMLCSTR c) { return (int)strlen(c); }
283
+ #ifdef __BORLANDC__
284
+ static inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) { return strnicmp(c1,c2,l);}
285
+ static inline int xstricmp(XMLCSTR c1, XMLCSTR c2) { return stricmp(c1,c2); }
286
+ #else
287
+ static inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) { return _strnicmp(c1,c2,l);}
288
+ static inline int xstricmp(XMLCSTR c1, XMLCSTR c2) { return _stricmp(c1,c2); }
289
+ #endif
290
+ static inline int xstrncmp(XMLCSTR c1, XMLCSTR c2, int l) { return strncmp(c1,c2,l);}
291
+ static inline XMLSTR xstrstr(XMLCSTR c1, XMLCSTR c2) { return (XMLSTR)strstr(c1,c2); }
292
+ static inline XMLSTR xstrcpy(XMLSTR c1, XMLCSTR c2) { return (XMLSTR)strcpy(c1,c2); }
293
+ #endif
294
+ #else
295
+ // for gcc and CC
296
+ #ifdef XML_NO_WIDE_CHAR
297
+ char *myWideCharToMultiByte(const wchar_t *s) { return NULL; }
298
+ #else
299
+ char *myWideCharToMultiByte(const wchar_t *s)
300
+ {
301
+ const wchar_t *ss=s;
302
+ int i=(int)wcsrtombs(NULL,&ss,0,NULL);
303
+ if (i<0) return NULL;
304
+ char *d=(char *)malloc(i+1);
305
+ wcsrtombs(d,&s,i,NULL);
306
+ d[i]=0;
307
+ return d;
308
+ }
309
+ #endif
310
+ #ifdef _XMLWIDECHAR
311
+ wchar_t *myMultiByteToWideChar(const char *s, XMLNode::XMLCharEncoding ce)
312
+ {
313
+ const char *ss=s;
314
+ int i=(int)mbsrtowcs(NULL,&ss,0,NULL);
315
+ if (i<0) return NULL;
316
+ wchar_t *d=(wchar_t *)malloc((i+1)*sizeof(wchar_t));
317
+ mbsrtowcs(d,&s,i,NULL);
318
+ d[i]=0;
319
+ return d;
320
+ }
321
+ int xstrlen(XMLCSTR c) { return wcslen(c); }
322
+ #ifdef sun
323
+ // for CC
324
+ #include <widec.h>
325
+ static inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) { return wsncasecmp(c1,c2,l);}
326
+ static inline int xstrncmp(XMLCSTR c1, XMLCSTR c2, int l) { return wsncmp(c1,c2,l);}
327
+ static inline int xstricmp(XMLCSTR c1, XMLCSTR c2) { return wscasecmp(c1,c2); }
328
+ #else
329
+ // for gcc
330
+ static inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) { return wcsncasecmp(c1,c2,l);}
331
+ static inline int xstrncmp(XMLCSTR c1, XMLCSTR c2, int l) { return wcsncmp(c1,c2,l);}
332
+ static inline int xstricmp(XMLCSTR c1, XMLCSTR c2) { return wcscasecmp(c1,c2); }
333
+ #endif
334
+ static inline XMLSTR xstrstr(XMLCSTR c1, XMLCSTR c2) { return (XMLSTR)wcsstr(c1,c2); }
335
+ static inline XMLSTR xstrcpy(XMLSTR c1, XMLCSTR c2) { return (XMLSTR)wcscpy(c1,c2); }
336
+ static inline FILE *xfopen(XMLCSTR filename,XMLCSTR mode)
337
+ {
338
+ char *filenameAscii=myWideCharToMultiByte(filename);
339
+ FILE *f;
340
+ if (mode[0]==_CXML('r')) f=fopen(filenameAscii,"rb");
341
+ else f=fopen(filenameAscii,"wb");
342
+ free(filenameAscii);
343
+ return f;
344
+ }
345
+ #else
346
+ static inline FILE *xfopen(XMLCSTR filename,XMLCSTR mode) { return fopen(filename,mode); }
347
+ static inline int xstrlen(XMLCSTR c) { return strlen(c); }
348
+ static inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) { return strncasecmp(c1,c2,l);}
349
+ static inline int xstrncmp(XMLCSTR c1, XMLCSTR c2, int l) { return strncmp(c1,c2,l);}
350
+ static inline int xstricmp(XMLCSTR c1, XMLCSTR c2) { return strcasecmp(c1,c2); }
351
+ static inline XMLSTR xstrstr(XMLCSTR c1, XMLCSTR c2) { return (XMLSTR)strstr(c1,c2); }
352
+ static inline XMLSTR xstrcpy(XMLSTR c1, XMLCSTR c2) { return (XMLSTR)strcpy(c1,c2); }
353
+ #endif
354
+ static inline int _strnicmp(const char *c1,const char *c2, int l) { return strncasecmp(c1,c2,l);}
355
+ #endif
356
+
357
+
358
+ ///////////////////////////////////////////////////////////////////////////////
359
+ // the "xmltoc,xmltob,xmltoi,xmltol,xmltof,xmltoa" functions //
360
+ ///////////////////////////////////////////////////////////////////////////////
361
+ // These 6 functions are not used inside the XMLparser.
362
+ // There are only here as "convenience" functions for the user.
363
+ // If you don't need them, you can delete them without any trouble.
364
+ #ifdef _XMLWIDECHAR
365
+ #ifdef _XMLWINDOWS
366
+ // for Microsoft Visual Studio 6.0 and Microsoft Visual Studio .NET and Borland C++ Builder 6.0
367
+ char xmltob(XMLCSTR t,int v){ if (t&&(*t)) return (char)_wtoi(t); return v; }
368
+ int xmltoi(XMLCSTR t,int v){ if (t&&(*t)) return _wtoi(t); return v; }
369
+ long xmltol(XMLCSTR t,long v){ if (t&&(*t)) return _wtol(t); return v; }
370
+ double xmltof(XMLCSTR t,double v){ if (t&&(*t)) wscanf(t, "%f", &v); /*v=_wtof(t);*/ return v; }
371
+ #else
372
+ #ifdef sun
373
+ // for CC
374
+ #include <widec.h>
375
+ char xmltob(XMLCSTR t,int v){ if (t) return (char)wstol(t,NULL,10); return v; }
376
+ int xmltoi(XMLCSTR t,int v){ if (t) return (int)wstol(t,NULL,10); return v; }
377
+ long xmltol(XMLCSTR t,long v){ if (t) return wstol(t,NULL,10); return v; }
378
+ #else
379
+ // for gcc
380
+ char xmltob(XMLCSTR t,int v){ if (t) return (char)wcstol(t,NULL,10); return v; }
381
+ int xmltoi(XMLCSTR t,int v){ if (t) return (int)wcstol(t,NULL,10); return v; }
382
+ long xmltol(XMLCSTR t,long v){ if (t) return wcstol(t,NULL,10); return v; }
383
+ #endif
384
+ double xmltof(XMLCSTR t,double v){ if (t&&(*t)) wscanf(t, "%f", &v); /*v=_wtof(t);*/ return v; }
385
+ #endif
386
+ #else
387
+ char xmltob(XMLCSTR t,char v){ if (t&&(*t)) return (char)atoi(t); return v; }
388
+ int xmltoi(XMLCSTR t,int v){ if (t&&(*t)) return atoi(t); return v; }
389
+ long xmltol(XMLCSTR t,long v){ if (t&&(*t)) return atol(t); return v; }
390
+ double xmltof(XMLCSTR t,double v){ if (t&&(*t)) return atof(t); return v; }
391
+ #endif
392
+ XMLCSTR xmltoa(XMLCSTR t,XMLCSTR v){ if (t) return t; return v; }
393
+ XMLCHAR xmltoc(XMLCSTR t,XMLCHAR v){ if (t&&(*t)) return *t; return v; }
394
+
395
+ /////////////////////////////////////////////////////////////////////////
396
+ // the "openFileHelper" function //
397
+ /////////////////////////////////////////////////////////////////////////
398
+
399
+ // Since each application has its own way to report and deal with errors, you should modify & rewrite
400
+ // the following "openFileHelper" function to get an "error reporting mechanism" tailored to your needs.
401
+ XMLNode XMLNode::openFileHelper(XMLCSTR filename, XMLCSTR tag)
402
+ {
403
+ // guess the value of the global parameter "characterEncoding"
404
+ // (the guess is based on the first 200 bytes of the file).
405
+ FILE *f=xfopen(filename,_CXML("rb"));
406
+ if (f)
407
+ {
408
+ char bb[205];
409
+ int l=(int)fread(bb,1,200,f);
410
+ setGlobalOptions(guessCharEncoding(bb,l),guessWideCharChars,dropWhiteSpace,removeCommentsInMiddleOfText);
411
+ fclose(f);
412
+ }
413
+
414
+ // parse the file
415
+ XMLResults pResults;
416
+ XMLNode xnode=XMLNode::parseFile(filename,tag,&pResults);
417
+
418
+ // display error message (if any)
419
+ if (pResults.error != eXMLErrorNone)
420
+ {
421
+ // create message
422
+ char message[2000],*s1=(char*)"",*s3=(char*)""; XMLCSTR s2=_CXML("");
423
+ if (pResults.error==eXMLErrorFirstTagNotFound) { s1=(char*)"First Tag should be '"; s2=tag; s3=(char*)"'.\n"; }
424
+ sprintf(message,
425
+ #ifdef _XMLWIDECHAR
426
+ "XML Parsing error inside file '%S'.\n%S\nAt line %i, column %i.\n%s%S%s"
427
+ #else
428
+ "XML Parsing error inside file '%s'.\n%s\nAt line %i, column %i.\n%s%s%s"
429
+ #endif
430
+ ,filename,XMLNode::getError(pResults.error),pResults.nLine,pResults.nColumn,s1,s2,s3);
431
+
432
+ // display message
433
+ #if defined(_XMLWINDOWS) && !defined(UNDER_CE) && !defined(_XMLPARSER_NO_MESSAGEBOX_)
434
+ MessageBoxA(NULL,message,"XML Parsing error",MB_OK|MB_ICONERROR|MB_TOPMOST);
435
+ #else
436
+ printf("%s",message);
437
+ #endif
438
+ exit(255);
439
+ }
440
+ return xnode;
441
+ }
442
+
443
+ /////////////////////////////////////////////////////////////////////////
444
+ // Here start the core implementation of the XMLParser library //
445
+ /////////////////////////////////////////////////////////////////////////
446
+
447
+ // You should normally not change anything below this point.
448
+
449
+ #ifndef _XMLWIDECHAR
450
+ // If "characterEncoding=ascii" then we assume that all characters have the same length of 1 byte.
451
+ // If "characterEncoding=UTF8" then the characters have different lengths (from 1 byte to 4 bytes).
452
+ // If "characterEncoding=ShiftJIS" then the characters have different lengths (from 1 byte to 2 bytes).
453
+ // This table is used as lookup-table to know the length of a character (in byte) based on the
454
+ // content of the first byte of the character.
455
+ // (note: if you modify this, you must always have XML_utf8ByteTable[0]=0 ).
456
+ static const char XML_utf8ByteTable[256] =
457
+ {
458
+ // 0 1 2 3 4 5 6 7 8 9 a b c d e f
459
+ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x00
460
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x10
461
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x20
462
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x30
463
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x40
464
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x50
465
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x60
466
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x70 End of ASCII range
467
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x80 0x80 to 0xc1 invalid
468
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x90
469
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0xa0
470
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0xb0
471
+ 1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xc0 0xc2 to 0xdf 2 byte
472
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xd0
473
+ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,// 0xe0 0xe0 to 0xef 3 byte
474
+ 4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid
475
+ };
476
+ static const char XML_legacyByteTable[256] =
477
+ {
478
+ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
479
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
480
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
481
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
482
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
483
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
484
+ };
485
+ static const char XML_sjisByteTable[256] =
486
+ {
487
+ // 0 1 2 3 4 5 6 7 8 9 a b c d e f
488
+ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x00
489
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x10
490
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x20
491
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x30
492
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x40
493
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x50
494
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x60
495
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x70
496
+ 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0x80 0x81 to 0x9F 2 bytes
497
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0x90
498
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0xa0
499
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0xb0
500
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0xc0
501
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0xd0
502
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xe0 0xe0 to 0xef 2 bytes
503
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 // 0xf0
504
+ };
505
+ static const char XML_gb2312ByteTable[256] =
506
+ {
507
+ // 0 1 2 3 4 5 6 7 8 9 a b c d e f
508
+ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x00
509
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x10
510
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x20
511
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x30
512
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x40
513
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x50
514
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x60
515
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x70
516
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x80
517
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x90
518
+ 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xa0 0xa1 to 0xf7 2 bytes
519
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xb0
520
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xc0
521
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xd0
522
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xe0
523
+ 2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1 // 0xf0
524
+ };
525
+ static const char XML_gbk_big5_ByteTable[256] =
526
+ {
527
+ // 0 1 2 3 4 5 6 7 8 9 a b c d e f
528
+ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x00
529
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x10
530
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x20
531
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x30
532
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x40
533
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x50
534
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x60
535
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x70
536
+ 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0x80 0x81 to 0xfe 2 bytes
537
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0x90
538
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xa0
539
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xb0
540
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xc0
541
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xd0
542
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xe0
543
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1 // 0xf0
544
+ };
545
+ static const char *XML_ByteTable=(const char *)XML_utf8ByteTable; // the default is "characterEncoding=XMLNode::encoding_UTF8"
546
+ #endif
547
+
548
+
549
+ XMLNode XMLNode::emptyXMLNode;
550
+ XMLClear XMLNode::emptyXMLClear={ NULL, NULL, NULL};
551
+ XMLAttribute XMLNode::emptyXMLAttribute={ NULL, NULL};
552
+
553
+ // Enumeration used to decipher what type a token is
554
+ typedef enum XMLTokenTypeTag
555
+ {
556
+ eTokenText = 0,
557
+ eTokenQuotedText,
558
+ eTokenTagStart, /* "<" */
559
+ eTokenTagEnd, /* "</" */
560
+ eTokenCloseTag, /* ">" */
561
+ eTokenEquals, /* "=" */
562
+ eTokenDeclaration, /* "<?" */
563
+ eTokenShortHandClose, /* "/>" */
564
+ eTokenClear,
565
+ eTokenError
566
+ } XMLTokenType;
567
+
568
+ // Main structure used for parsing XML
569
+ typedef struct XML
570
+ {
571
+ XMLCSTR lpXML;
572
+ XMLCSTR lpszText;
573
+ int nIndex,nIndexMissigEndTag;
574
+ enum XMLError error;
575
+ XMLCSTR lpEndTag;
576
+ int cbEndTag;
577
+ XMLCSTR lpNewElement;
578
+ int cbNewElement;
579
+ int nFirst;
580
+ } XML;
581
+
582
+ typedef struct
583
+ {
584
+ ALLXMLClearTag *pClr;
585
+ XMLCSTR pStr;
586
+ } NextToken;
587
+
588
+ // Enumeration used when parsing attributes
589
+ typedef enum Attrib
590
+ {
591
+ eAttribName = 0,
592
+ eAttribEquals,
593
+ eAttribValue
594
+ } Attrib;
595
+
596
+ // Enumeration used when parsing elements to dictate whether we are currently
597
+ // inside a tag
598
+ typedef enum Status
599
+ {
600
+ eInsideTag = 0,
601
+ eOutsideTag
602
+ } Status;
603
+
604
+ XMLError XMLNode::writeToFile(XMLCSTR filename, const char *encoding, char nFormat) const
605
+ {
606
+ if (!d) return eXMLErrorNone;
607
+ FILE *f=xfopen(filename,_CXML("wb"));
608
+ if (!f) return eXMLErrorCannotOpenWriteFile;
609
+ #ifdef _XMLWIDECHAR
610
+ unsigned char h[2]={ 0xFF, 0xFE };
611
+ if (!fwrite(h,2,1,f))
612
+ {
613
+ fclose(f);
614
+ return eXMLErrorCannotWriteFile;
615
+ }
616
+ if ((!isDeclaration())&&((d->lpszName)||(!getChildNode().isDeclaration())))
617
+ {
618
+ if (!fwrite(L"<?xml version=\"1.0\" encoding=\"utf-16\"?>\n",sizeof(wchar_t)*40,1,f))
619
+ {
620
+ fclose(f);
621
+ return eXMLErrorCannotWriteFile;
622
+ }
623
+ }
624
+ #else
625
+ if ((!isDeclaration())&&((d->lpszName)||(!getChildNode().isDeclaration())))
626
+ {
627
+ if (characterEncoding==char_encoding_UTF8)
628
+ {
629
+ // header so that windows recognize the file as UTF-8:
630
+ unsigned char h[3]={0xEF,0xBB,0xBF};
631
+ if (!fwrite(h,3,1,f))
632
+ {
633
+ fclose(f);
634
+ return eXMLErrorCannotWriteFile;
635
+ }
636
+ encoding="utf-8";
637
+ } else if (characterEncoding==char_encoding_ShiftJIS) encoding="SHIFT-JIS";
638
+
639
+ if (!encoding) encoding="ISO-8859-1";
640
+ if (fprintf(f,"<?xml version=\"1.0\" encoding=\"%s\"?>\n",encoding)<0)
641
+ {
642
+ fclose(f);
643
+ return eXMLErrorCannotWriteFile;
644
+ }
645
+ } else
646
+ {
647
+ if (characterEncoding==char_encoding_UTF8)
648
+ {
649
+ unsigned char h[3]={0xEF,0xBB,0xBF};
650
+ if (!fwrite(h,3,1,f))
651
+ {
652
+ fclose(f);
653
+ return eXMLErrorCannotWriteFile;
654
+ }
655
+ }
656
+ }
657
+ #endif
658
+ int i;
659
+ XMLSTR t=createXMLString(nFormat,&i);
660
+ if (!fwrite(t,sizeof(XMLCHAR)*i,1,f))
661
+ {
662
+ fclose(f);
663
+ return eXMLErrorCannotWriteFile;
664
+ }
665
+ if (fclose(f)!=0) return eXMLErrorCannotWriteFile;
666
+ free(t);
667
+ return eXMLErrorNone;
668
+ }
669
+
670
+ // Duplicate a given string.
671
+ XMLSTR stringDup(XMLCSTR lpszData, int cbData)
672
+ {
673
+ if (lpszData==NULL) return NULL;
674
+
675
+ XMLSTR lpszNew;
676
+ if (cbData==-1) cbData=(int)xstrlen(lpszData);
677
+ lpszNew = (XMLSTR)malloc((cbData+1) * sizeof(XMLCHAR));
678
+ if (lpszNew)
679
+ {
680
+ memcpy(lpszNew, lpszData, (cbData) * sizeof(XMLCHAR));
681
+ lpszNew[cbData] = (XMLCHAR)NULL;
682
+ }
683
+ return lpszNew;
684
+ }
685
+
686
+ XMLSTR ToXMLStringTool::toXMLUnSafe(XMLSTR dest,XMLCSTR source)
687
+ {
688
+ XMLSTR dd=dest;
689
+ XMLCHAR ch;
690
+ XMLCharacterEntity *entity;
691
+ while ((ch=*source))
692
+ {
693
+ entity=XMLEntities;
694
+ do
695
+ {
696
+ if (ch==entity->c) {xstrcpy(dest,entity->s); dest+=entity->l; source++; goto out_of_loop1; }
697
+ entity++;
698
+ } while(entity->s);
699
+ #ifdef _XMLWIDECHAR
700
+ *(dest++)=*(source++);
701
+ #else
702
+ switch(XML_ByteTable[(unsigned char)ch])
703
+ {
704
+ case 4: *(dest++)=*(source++);
705
+ case 3: *(dest++)=*(source++);
706
+ case 2: *(dest++)=*(source++);
707
+ case 1: *(dest++)=*(source++);
708
+ }
709
+ #endif
710
+ out_of_loop1:
711
+ ;
712
+ }
713
+ *dest=0;
714
+ return dd;
715
+ }
716
+
717
+ // private (used while rendering):
718
+ int ToXMLStringTool::lengthXMLString(XMLCSTR source)
719
+ {
720
+ int r=0;
721
+ XMLCharacterEntity *entity;
722
+ XMLCHAR ch;
723
+ while ((ch=*source))
724
+ {
725
+ entity=XMLEntities;
726
+ do
727
+ {
728
+ if (ch==entity->c) { r+=entity->l; source++; goto out_of_loop1; }
729
+ entity++;
730
+ } while(entity->s);
731
+ #ifdef _XMLWIDECHAR
732
+ r++; source++;
733
+ #else
734
+ ch=XML_ByteTable[(unsigned char)ch]; r+=ch; source+=ch;
735
+ #endif
736
+ out_of_loop1:
737
+ ;
738
+ }
739
+ return r;
740
+ }
741
+
742
+ ToXMLStringTool::~ToXMLStringTool(){ freeBuffer(); }
743
+ void ToXMLStringTool::freeBuffer(){ if (buf) free(buf); buf=NULL; buflen=0; }
744
+ XMLSTR ToXMLStringTool::toXML(XMLCSTR source)
745
+ {
746
+ int l=lengthXMLString(source)+1;
747
+ if (l>buflen) { buflen=l; buf=(XMLSTR)realloc(buf,l*sizeof(XMLCHAR)); }
748
+ return toXMLUnSafe(buf,source);
749
+ }
750
+
751
+ // private:
752
+ XMLSTR fromXMLString(XMLCSTR s, int lo, XML *pXML)
753
+ {
754
+ // This function is the opposite of the function "toXMLString". It decodes the escape
755
+ // sequences &amp;, &quot;, &apos;, &lt;, &gt; and replace them by the characters
756
+ // &,",',<,>. This function is used internally by the XML Parser. All the calls to
757
+ // the XML library will always gives you back "decoded" strings.
758
+ //
759
+ // in: string (s) and length (lo) of string
760
+ // out: new allocated string converted from xml
761
+ if (!s) return NULL;
762
+
763
+ int ll=0,j;
764
+ XMLSTR d;
765
+ XMLCSTR ss=s;
766
+ XMLCharacterEntity *entity;
767
+ while ((lo>0)&&(*s))
768
+ {
769
+ if (*s==_CXML('&'))
770
+ {
771
+ if ((lo>2)&&(s[1]==_CXML('#')))
772
+ {
773
+ s+=2; lo-=2;
774
+ if ((*s==_CXML('X'))||(*s==_CXML('x'))) { s++; lo--; }
775
+ while ((*s)&&(*s!=_CXML(';'))&&((lo--)>0)) s++;
776
+ if (*s!=_CXML(';'))
777
+ {
778
+ pXML->error=eXMLErrorUnknownCharacterEntity;
779
+ return NULL;
780
+ }
781
+ s++; lo--;
782
+ } else
783
+ {
784
+ entity=XMLEntities;
785
+ do
786
+ {
787
+ if ((lo>=entity->l)&&(xstrnicmp(s,entity->s,entity->l)==0)) { s+=entity->l; lo-=entity->l; break; }
788
+ entity++;
789
+ } while(entity->s);
790
+ if (!entity->s)
791
+ {
792
+ pXML->error=eXMLErrorUnknownCharacterEntity;
793
+ return NULL;
794
+ }
795
+ }
796
+ } else
797
+ {
798
+ #ifdef _XMLWIDECHAR
799
+ s++; lo--;
800
+ #else
801
+ j=XML_ByteTable[(unsigned char)*s]; s+=j; lo-=j; ll+=j-1;
802
+ #endif
803
+ }
804
+ ll++;
805
+ }
806
+
807
+ d=(XMLSTR)malloc((ll+1)*sizeof(XMLCHAR));
808
+ s=d;
809
+ while (ll-->0)
810
+ {
811
+ if (*ss==_CXML('&'))
812
+ {
813
+ if (ss[1]==_CXML('#'))
814
+ {
815
+ ss+=2; j=0;
816
+ if ((*ss==_CXML('X'))||(*ss==_CXML('x')))
817
+ {
818
+ ss++;
819
+ while (*ss!=_CXML(';'))
820
+ {
821
+ if ((*ss>=_CXML('0'))&&(*ss<=_CXML('9'))) j=(j<<4)+*ss-_CXML('0');
822
+ else if ((*ss>=_CXML('A'))&&(*ss<=_CXML('F'))) j=(j<<4)+*ss-_CXML('A')+10;
823
+ else if ((*ss>=_CXML('a'))&&(*ss<=_CXML('f'))) j=(j<<4)+*ss-_CXML('a')+10;
824
+ else { free((void*)s); pXML->error=eXMLErrorUnknownCharacterEntity;return NULL;}
825
+ ss++;
826
+ }
827
+ } else
828
+ {
829
+ while (*ss!=_CXML(';'))
830
+ {
831
+ if ((*ss>=_CXML('0'))&&(*ss<=_CXML('9'))) j=(j*10)+*ss-_CXML('0');
832
+ else { free((void*)s); pXML->error=eXMLErrorUnknownCharacterEntity;return NULL;}
833
+ ss++;
834
+ }
835
+ }
836
+ #ifndef _XMLWIDECHAR
837
+ if (j>255) { free((void*)s); pXML->error=eXMLErrorCharacterCodeAbove255;return NULL;}
838
+ #endif
839
+ (*d++)=(XMLCHAR)j; ss++;
840
+ } else
841
+ {
842
+ entity=XMLEntities;
843
+ do
844
+ {
845
+ if (xstrnicmp(ss,entity->s,entity->l)==0) { *(d++)=entity->c; ss+=entity->l; break; }
846
+ entity++;
847
+ } while(entity->s);
848
+ }
849
+ } else
850
+ {
851
+ #ifdef _XMLWIDECHAR
852
+ *(d++)=*(ss++);
853
+ #else
854
+ switch(XML_ByteTable[(unsigned char)*ss])
855
+ {
856
+ case 4: *(d++)=*(ss++); ll--;
857
+ case 3: *(d++)=*(ss++); ll--;
858
+ case 2: *(d++)=*(ss++); ll--;
859
+ case 1: *(d++)=*(ss++);
860
+ }
861
+ #endif
862
+ }
863
+ }
864
+ *d=0;
865
+ return (XMLSTR)s;
866
+ }
867
+
868
+ #define XML_isSPACECHAR(ch) ((ch==_CXML('\n'))||(ch==_CXML(' '))||(ch== _CXML('\t'))||(ch==_CXML('\r')))
869
+
870
+ // private:
871
+ char myTagCompare(XMLCSTR cclose, XMLCSTR copen)
872
+ // !!!! WARNING strange convention&:
873
+ // return 0 if equals
874
+ // return 1 if different
875
+ {
876
+ if (!cclose) return 1;
877
+ int l=(int)xstrlen(cclose);
878
+ if (xstrnicmp(cclose, copen, l)!=0) return 1;
879
+ const XMLCHAR c=copen[l];
880
+ if (XML_isSPACECHAR(c)||
881
+ (c==_CXML('/' ))||
882
+ (c==_CXML('<' ))||
883
+ (c==_CXML('>' ))||
884
+ (c==_CXML('=' ))) return 0;
885
+ return 1;
886
+ }
887
+
888
+ // Obtain the next character from the string.
889
+ static inline XMLCHAR getNextChar(XML *pXML)
890
+ {
891
+ XMLCHAR ch = pXML->lpXML[pXML->nIndex];
892
+ #ifdef _XMLWIDECHAR
893
+ if (ch!=0) pXML->nIndex++;
894
+ #else
895
+ pXML->nIndex+=XML_ByteTable[(unsigned char)ch];
896
+ #endif
897
+ return ch;
898
+ }
899
+
900
+ // Find the next token in a string.
901
+ // pcbToken contains the number of characters that have been read.
902
+ static NextToken GetNextToken(XML *pXML, int *pcbToken, enum XMLTokenTypeTag *pType)
903
+ {
904
+ NextToken result;
905
+ XMLCHAR ch;
906
+ XMLCHAR chTemp;
907
+ int indexStart,nFoundMatch,nIsText=FALSE;
908
+ result.pClr=NULL; // prevent warning
909
+
910
+ // Find next non-white space character
911
+ do { indexStart=pXML->nIndex; ch=getNextChar(pXML); } while XML_isSPACECHAR(ch);
912
+
913
+ if (ch)
914
+ {
915
+ // Cache the current string pointer
916
+ result.pStr = &pXML->lpXML[indexStart];
917
+
918
+ // First check whether the token is in the clear tag list (meaning it
919
+ // does not need formatting).
920
+ ALLXMLClearTag *ctag=XMLClearTags;
921
+ do
922
+ {
923
+ if (xstrncmp(ctag->lpszOpen, result.pStr, ctag->openTagLen)==0)
924
+ {
925
+ result.pClr=ctag;
926
+ pXML->nIndex+=ctag->openTagLen-1;
927
+ *pType=eTokenClear;
928
+ return result;
929
+ }
930
+ ctag++;
931
+ } while(ctag->lpszOpen);
932
+
933
+ // If we didn't find a clear tag then check for standard tokens
934
+ switch(ch)
935
+ {
936
+ // Check for quotes
937
+ case _CXML('\''):
938
+ case _CXML('\"'):
939
+ // Type of token
940
+ *pType = eTokenQuotedText;
941
+ chTemp = ch;
942
+
943
+ // Set the size
944
+ nFoundMatch = FALSE;
945
+
946
+ // Search through the string to find a matching quote
947
+ while((ch = getNextChar(pXML)))
948
+ {
949
+ if (ch==chTemp) { nFoundMatch = TRUE; break; }
950
+ if (ch==_CXML('<')) break;
951
+ }
952
+
953
+ // If we failed to find a matching quote
954
+ if (nFoundMatch == FALSE)
955
+ {
956
+ pXML->nIndex=indexStart+1;
957
+ nIsText=TRUE;
958
+ break;
959
+ }
960
+
961
+ // 4.02.2002
962
+ // if (FindNonWhiteSpace(pXML)) pXML->nIndex--;
963
+
964
+ break;
965
+
966
+ // Equals (used with attribute values)
967
+ case _CXML('='):
968
+ *pType = eTokenEquals;
969
+ break;
970
+
971
+ // Close tag
972
+ case _CXML('>'):
973
+ *pType = eTokenCloseTag;
974
+ break;
975
+
976
+ // Check for tag start and tag end
977
+ case _CXML('<'):
978
+
979
+ // Peek at the next character to see if we have an end tag '</',
980
+ // or an xml declaration '<?'
981
+ chTemp = pXML->lpXML[pXML->nIndex];
982
+
983
+ // If we have a tag end...
984
+ if (chTemp == _CXML('/'))
985
+ {
986
+ // Set the type and ensure we point at the next character
987
+ getNextChar(pXML);
988
+ *pType = eTokenTagEnd;
989
+ }
990
+
991
+ // If we have an XML declaration tag
992
+ else if (chTemp == _CXML('?'))
993
+ {
994
+
995
+ // Set the type and ensure we point at the next character
996
+ getNextChar(pXML);
997
+ *pType = eTokenDeclaration;
998
+ }
999
+
1000
+ // Otherwise we must have a start tag
1001
+ else
1002
+ {
1003
+ *pType = eTokenTagStart;
1004
+ }
1005
+ break;
1006
+
1007
+ // Check to see if we have a short hand type end tag ('/>').
1008
+ case _CXML('/'):
1009
+
1010
+ // Peek at the next character to see if we have a short end tag '/>'
1011
+ chTemp = pXML->lpXML[pXML->nIndex];
1012
+
1013
+ // If we have a short hand end tag...
1014
+ if (chTemp == _CXML('>'))
1015
+ {
1016
+ // Set the type and ensure we point at the next character
1017
+ getNextChar(pXML);
1018
+ *pType = eTokenShortHandClose;
1019
+ break;
1020
+ }
1021
+
1022
+ // If we haven't found a short hand closing tag then drop into the
1023
+ // text process
1024
+
1025
+ // Other characters
1026
+ default:
1027
+ nIsText = TRUE;
1028
+ }
1029
+
1030
+ // If this is a TEXT node
1031
+ if (nIsText)
1032
+ {
1033
+ // Indicate we are dealing with text
1034
+ *pType = eTokenText;
1035
+ while((ch = getNextChar(pXML)))
1036
+ {
1037
+ if XML_isSPACECHAR(ch)
1038
+ {
1039
+ indexStart++; break;
1040
+
1041
+ } else if (ch==_CXML('/'))
1042
+ {
1043
+ // If we find a slash then this maybe text or a short hand end tag
1044
+ // Peek at the next character to see it we have short hand end tag
1045
+ ch=pXML->lpXML[pXML->nIndex];
1046
+ // If we found a short hand end tag then we need to exit the loop
1047
+ if (ch==_CXML('>')) { pXML->nIndex--; break; }
1048
+
1049
+ } else if ((ch==_CXML('<'))||(ch==_CXML('>'))||(ch==_CXML('=')))
1050
+ {
1051
+ pXML->nIndex--; break;
1052
+ }
1053
+ }
1054
+ }
1055
+ *pcbToken = pXML->nIndex-indexStart;
1056
+ } else
1057
+ {
1058
+ // If we failed to obtain a valid character
1059
+ *pcbToken = 0;
1060
+ *pType = eTokenError;
1061
+ result.pStr=NULL;
1062
+ }
1063
+
1064
+ return result;
1065
+ }
1066
+
1067
+ XMLCSTR XMLNode::updateName_WOSD(XMLSTR lpszName)
1068
+ {
1069
+ if (!d) { free(lpszName); return NULL; }
1070
+ if (d->lpszName&&(lpszName!=d->lpszName)) free((void*)d->lpszName);
1071
+ d->lpszName=lpszName;
1072
+ return lpszName;
1073
+ }
1074
+
1075
+ // private:
1076
+ XMLNode::XMLNode(struct XMLNodeDataTag *p){ d=p; (p->ref_count)++; }
1077
+ XMLNode::XMLNode(XMLNodeData *pParent, XMLSTR lpszName, char isDeclaration)
1078
+ {
1079
+ d=(XMLNodeData*)malloc(sizeof(XMLNodeData));
1080
+ d->ref_count=1;
1081
+
1082
+ d->lpszName=NULL;
1083
+ d->nChild= 0;
1084
+ d->nText = 0;
1085
+ d->nClear = 0;
1086
+ d->nAttribute = 0;
1087
+
1088
+ d->isDeclaration = isDeclaration;
1089
+
1090
+ d->pParent = pParent;
1091
+ d->pChild= NULL;
1092
+ d->pText= NULL;
1093
+ d->pClear= NULL;
1094
+ d->pAttribute= NULL;
1095
+ d->pOrder= NULL;
1096
+
1097
+ updateName_WOSD(lpszName);
1098
+ }
1099
+
1100
+ XMLNode XMLNode::createXMLTopNode_WOSD(XMLSTR lpszName, char isDeclaration) { return XMLNode(NULL,lpszName,isDeclaration); }
1101
+ XMLNode XMLNode::createXMLTopNode(XMLCSTR lpszName, char isDeclaration) { return XMLNode(NULL,stringDup(lpszName),isDeclaration); }
1102
+
1103
+ #define MEMORYINCREASE 50
1104
+
1105
+ static inline void myFree(void *p) { if (p) free(p); }
1106
+ static inline void *myRealloc(void *p, int newsize, int memInc, int sizeofElem)
1107
+ {
1108
+ if (p==NULL) { if (memInc) return malloc(memInc*sizeofElem); return malloc(sizeofElem); }
1109
+ if ((memInc==0)||((newsize%memInc)==0)) p=realloc(p,(newsize+memInc)*sizeofElem);
1110
+ // if (!p)
1111
+ // {
1112
+ // printf("XMLParser Error: Not enough memory! Aborting...\n"); exit(220);
1113
+ // }
1114
+ return p;
1115
+ }
1116
+
1117
+ // private:
1118
+ XMLElementPosition XMLNode::findPosition(XMLNodeData *d, int index, XMLElementType xxtype)
1119
+ {
1120
+ if (index<0) return -1;
1121
+ int i=0,j=(int)((index<<2)+xxtype),*o=d->pOrder; while (o[i]!=j) i++; return i;
1122
+ }
1123
+
1124
+ // private:
1125
+ // update "order" information when deleting a content of a XMLNode
1126
+ int XMLNode::removeOrderElement(XMLNodeData *d, XMLElementType t, int index)
1127
+ {
1128
+ int n=d->nChild+d->nText+d->nClear, *o=d->pOrder,i=findPosition(d,index,t);
1129
+ memmove(o+i, o+i+1, (n-i)*sizeof(int));
1130
+ for (;i<n;i++)
1131
+ if ((o[i]&3)==(int)t) o[i]-=4;
1132
+ // We should normally do:
1133
+ // d->pOrder=(int)realloc(d->pOrder,n*sizeof(int));
1134
+ // but we skip reallocation because it's too time consuming.
1135
+ // Anyway, at the end, it will be free'd completely at once.
1136
+ return i;
1137
+ }
1138
+
1139
+ void *XMLNode::addToOrder(int memoryIncrease,int *_pos, int nc, void *p, int size, XMLElementType xtype)
1140
+ {
1141
+ // in: *_pos is the position inside d->pOrder ("-1" means "EndOf")
1142
+ // out: *_pos is the index inside p
1143
+ p=myRealloc(p,(nc+1),memoryIncrease,size);
1144
+ int n=d->nChild+d->nText+d->nClear;
1145
+ d->pOrder=(int*)myRealloc(d->pOrder,n+1,memoryIncrease*3,sizeof(int));
1146
+ int pos=*_pos,*o=d->pOrder;
1147
+
1148
+ if ((pos<0)||(pos>=n)) { *_pos=nc; o[n]=(int)((nc<<2)+xtype); return p; }
1149
+
1150
+ int i=pos;
1151
+ memmove(o+i+1, o+i, (n-i)*sizeof(int));
1152
+
1153
+ while ((pos<n)&&((o[pos]&3)!=(int)xtype)) pos++;
1154
+ if (pos==n) { *_pos=nc; o[n]=(int)((nc<<2)+xtype); return p; }
1155
+
1156
+ o[i]=o[pos];
1157
+ for (i=pos+1;i<=n;i++) if ((o[i]&3)==(int)xtype) o[i]+=4;
1158
+
1159
+ *_pos=pos=o[pos]>>2;
1160
+ memmove(((char*)p)+(pos+1)*size,((char*)p)+pos*size,(nc-pos)*size);
1161
+
1162
+ return p;
1163
+ }
1164
+
1165
+ // Add a child node to the given element.
1166
+ XMLNode XMLNode::addChild_priv(int memoryIncrease, XMLSTR lpszName, char isDeclaration, int pos)
1167
+ {
1168
+ if (!lpszName) return emptyXMLNode;
1169
+ d->pChild=(XMLNode*)addToOrder(memoryIncrease,&pos,d->nChild,d->pChild,sizeof(XMLNode),eNodeChild);
1170
+ d->pChild[pos].d=NULL;
1171
+ d->pChild[pos]=XMLNode(d,lpszName,isDeclaration);
1172
+ d->nChild++;
1173
+ return d->pChild[pos];
1174
+ }
1175
+
1176
+ // Add an attribute to an element.
1177
+ XMLAttribute *XMLNode::addAttribute_priv(int memoryIncrease,XMLSTR lpszName, XMLSTR lpszValuev)
1178
+ {
1179
+ if (!lpszName) return &emptyXMLAttribute;
1180
+ if (!d) { myFree(lpszName); myFree(lpszValuev); return &emptyXMLAttribute; }
1181
+ int nc=d->nAttribute;
1182
+ d->pAttribute=(XMLAttribute*)myRealloc(d->pAttribute,(nc+1),memoryIncrease,sizeof(XMLAttribute));
1183
+ XMLAttribute *pAttr=d->pAttribute+nc;
1184
+ pAttr->lpszName = lpszName;
1185
+ pAttr->lpszValue = lpszValuev;
1186
+ d->nAttribute++;
1187
+ return pAttr;
1188
+ }
1189
+
1190
+ // Add text to the element.
1191
+ XMLCSTR XMLNode::addText_priv(int memoryIncrease, XMLSTR lpszValue, int pos)
1192
+ {
1193
+ if (!lpszValue) return NULL;
1194
+ if (!d) { myFree(lpszValue); return NULL; }
1195
+ d->pText=(XMLCSTR*)addToOrder(memoryIncrease,&pos,d->nText,d->pText,sizeof(XMLSTR),eNodeText);
1196
+ d->pText[pos]=lpszValue;
1197
+ d->nText++;
1198
+ return lpszValue;
1199
+ }
1200
+
1201
+ // Add clear (unformatted) text to the element.
1202
+ XMLClear *XMLNode::addClear_priv(int memoryIncrease, XMLSTR lpszValue, XMLCSTR lpszOpen, XMLCSTR lpszClose, int pos)
1203
+ {
1204
+ if (!lpszValue) return &emptyXMLClear;
1205
+ if (!d) { myFree(lpszValue); return &emptyXMLClear; }
1206
+ d->pClear=(XMLClear *)addToOrder(memoryIncrease,&pos,d->nClear,d->pClear,sizeof(XMLClear),eNodeClear);
1207
+ XMLClear *pNewClear=d->pClear+pos;
1208
+ pNewClear->lpszValue = lpszValue;
1209
+ if (!lpszOpen) lpszOpen=XMLClearTags->lpszOpen;
1210
+ if (!lpszClose) lpszClose=XMLClearTags->lpszClose;
1211
+ pNewClear->lpszOpenTag = lpszOpen;
1212
+ pNewClear->lpszCloseTag = lpszClose;
1213
+ d->nClear++;
1214
+ return pNewClear;
1215
+ }
1216
+
1217
+ // private:
1218
+ // Parse a clear (unformatted) type node.
1219
+ char XMLNode::parseClearTag(void *px, void *_pClear)
1220
+ {
1221
+ XML *pXML=(XML *)px;
1222
+ ALLXMLClearTag pClear=*((ALLXMLClearTag*)_pClear);
1223
+ int cbTemp=0;
1224
+ XMLCSTR lpszTemp=NULL;
1225
+ XMLCSTR lpXML=&pXML->lpXML[pXML->nIndex];
1226
+ static XMLCSTR docTypeEnd=_CXML("]>");
1227
+
1228
+ // Find the closing tag
1229
+ // Seems the <!DOCTYPE need a better treatment so lets handle it
1230
+ if (pClear.lpszOpen==XMLClearTags[1].lpszOpen)
1231
+ {
1232
+ XMLCSTR pCh=lpXML;
1233
+ while (*pCh)
1234
+ {
1235
+ if (*pCh==_CXML('<')) { pClear.lpszClose=docTypeEnd; lpszTemp=xstrstr(lpXML,docTypeEnd); break; }
1236
+ else if (*pCh==_CXML('>')) { lpszTemp=pCh; break; }
1237
+ #ifdef _XMLWIDECHAR
1238
+ pCh++;
1239
+ #else
1240
+ pCh+=XML_ByteTable[(unsigned char)(*pCh)];
1241
+ #endif
1242
+ }
1243
+ } else lpszTemp=xstrstr(lpXML, pClear.lpszClose);
1244
+
1245
+ if (lpszTemp)
1246
+ {
1247
+ // Cache the size and increment the index
1248
+ cbTemp = (int)(lpszTemp - lpXML);
1249
+
1250
+ pXML->nIndex += cbTemp+(int)xstrlen(pClear.lpszClose);
1251
+
1252
+ // Add the clear node to the current element
1253
+ addClear_priv(MEMORYINCREASE,stringDup(lpXML,cbTemp), pClear.lpszOpen, pClear.lpszClose,-1);
1254
+ return 0;
1255
+ }
1256
+
1257
+ // If we failed to find the end tag
1258
+ pXML->error = eXMLErrorUnmatchedEndClearTag;
1259
+ return 1;
1260
+ }
1261
+
1262
+ void XMLNode::exactMemory(XMLNodeData *d)
1263
+ {
1264
+ if (d->pOrder) d->pOrder=(int*)realloc(d->pOrder,(d->nChild+d->nText+d->nClear)*sizeof(int));
1265
+ if (d->pChild) d->pChild=(XMLNode*)realloc(d->pChild,d->nChild*sizeof(XMLNode));
1266
+ if (d->pAttribute) d->pAttribute=(XMLAttribute*)realloc(d->pAttribute,d->nAttribute*sizeof(XMLAttribute));
1267
+ if (d->pText) d->pText=(XMLCSTR*)realloc(d->pText,d->nText*sizeof(XMLSTR));
1268
+ if (d->pClear) d->pClear=(XMLClear *)realloc(d->pClear,d->nClear*sizeof(XMLClear));
1269
+ }
1270
+
1271
+ char XMLNode::maybeAddTxT(void *pa, XMLCSTR tokenPStr)
1272
+ {
1273
+ XML *pXML=(XML *)pa;
1274
+ XMLCSTR lpszText=pXML->lpszText;
1275
+ if (!lpszText) return 0;
1276
+ if (dropWhiteSpace) while (XML_isSPACECHAR(*lpszText)&&(lpszText!=tokenPStr)) lpszText++;
1277
+ int cbText = (int)(tokenPStr - lpszText);
1278
+ if (!cbText) { pXML->lpszText=NULL; return 0; }
1279
+ if (dropWhiteSpace) { cbText--; while ((cbText)&&XML_isSPACECHAR(lpszText[cbText])) cbText--; cbText++; }
1280
+ if (!cbText) { pXML->lpszText=NULL; return 0; }
1281
+ XMLSTR lpt=fromXMLString(lpszText,cbText,pXML);
1282
+ if (!lpt) return 1;
1283
+ pXML->lpszText=NULL;
1284
+ if (removeCommentsInMiddleOfText && d->nText && d->nClear)
1285
+ {
1286
+ // if the previous insertion was a comment (<!-- -->) AND
1287
+ // if the previous previous insertion was a text then, delete the comment and append the text
1288
+ int n=d->nChild+d->nText+d->nClear-1,*o=d->pOrder;
1289
+ if (((o[n]&3)==eNodeClear)&&((o[n-1]&3)==eNodeText))
1290
+ {
1291
+ int i=o[n]>>2;
1292
+ if (d->pClear[i].lpszOpenTag==XMLClearTags[2].lpszOpen)
1293
+ {
1294
+ deleteClear(i);
1295
+ i=o[n-1]>>2;
1296
+ n=xstrlen(d->pText[i]);
1297
+ int n2=xstrlen(lpt)+1;
1298
+ d->pText[i]=(XMLSTR)realloc((void*)d->pText[i],(n+n2)*sizeof(XMLCHAR));
1299
+ if (!d->pText[i]) return 1;
1300
+ memcpy((void*)(d->pText[i]+n),lpt,n2*sizeof(XMLCHAR));
1301
+ free(lpt);
1302
+ return 0;
1303
+ }
1304
+ }
1305
+ }
1306
+ addText_priv(MEMORYINCREASE,lpt,-1);
1307
+ return 0;
1308
+ }
1309
+ // private:
1310
+ // Recursively parse an XML element.
1311
+ int XMLNode::ParseXMLElement(void *pa)
1312
+ {
1313
+ XML *pXML=(XML *)pa;
1314
+ int cbToken;
1315
+ enum XMLTokenTypeTag xtype;
1316
+ NextToken token;
1317
+ XMLCSTR lpszTemp=NULL;
1318
+ int cbTemp=0;
1319
+ char nDeclaration;
1320
+ XMLNode pNew;
1321
+ enum Status status; // inside or outside a tag
1322
+ enum Attrib attrib = eAttribName;
1323
+
1324
+ assert(pXML);
1325
+
1326
+ // If this is the first call to the function
1327
+ if (pXML->nFirst)
1328
+ {
1329
+ // Assume we are outside of a tag definition
1330
+ pXML->nFirst = FALSE;
1331
+ status = eOutsideTag;
1332
+ } else
1333
+ {
1334
+ // If this is not the first call then we should only be called when inside a tag.
1335
+ status = eInsideTag;
1336
+ }
1337
+
1338
+ // Iterate through the tokens in the document
1339
+ for(;;)
1340
+ {
1341
+ // Obtain the next token
1342
+ token = GetNextToken(pXML, &cbToken, &xtype);
1343
+
1344
+ if (xtype != eTokenError)
1345
+ {
1346
+ // Check the current status
1347
+ switch(status)
1348
+ {
1349
+
1350
+ // If we are outside of a tag definition
1351
+ case eOutsideTag:
1352
+
1353
+ // Check what type of token we obtained
1354
+ switch(xtype)
1355
+ {
1356
+ // If we have found text or quoted text
1357
+ case eTokenText:
1358
+ case eTokenCloseTag: /* '>' */
1359
+ case eTokenShortHandClose: /* '/>' */
1360
+ case eTokenQuotedText:
1361
+ case eTokenEquals:
1362
+ break;
1363
+
1364
+ // If we found a start tag '<' and declarations '<?'
1365
+ case eTokenTagStart:
1366
+ case eTokenDeclaration:
1367
+
1368
+ // Cache whether this new element is a declaration or not
1369
+ nDeclaration = (xtype == eTokenDeclaration);
1370
+
1371
+ // If we have node text then add this to the element
1372
+ if (maybeAddTxT(pXML,token.pStr)) return FALSE;
1373
+
1374
+ // Find the name of the tag
1375
+ token = GetNextToken(pXML, &cbToken, &xtype);
1376
+
1377
+ // Return an error if we couldn't obtain the next token or
1378
+ // it wasnt text
1379
+ if (xtype != eTokenText)
1380
+ {
1381
+ pXML->error = eXMLErrorMissingTagName;
1382
+ return FALSE;
1383
+ }
1384
+
1385
+ // If we found a new element which is the same as this
1386
+ // element then we need to pass this back to the caller..
1387
+
1388
+ #ifdef APPROXIMATE_PARSING
1389
+ if (d->lpszName &&
1390
+ myTagCompare(d->lpszName, token.pStr) == 0)
1391
+ {
1392
+ // Indicate to the caller that it needs to create a
1393
+ // new element.
1394
+ pXML->lpNewElement = token.pStr;
1395
+ pXML->cbNewElement = cbToken;
1396
+ return TRUE;
1397
+ } else
1398
+ #endif
1399
+ {
1400
+ // If the name of the new element differs from the name of
1401
+ // the current element we need to add the new element to
1402
+ // the current one and recurse
1403
+ pNew = addChild_priv(MEMORYINCREASE,stringDup(token.pStr,cbToken), nDeclaration,-1);
1404
+
1405
+ while (!pNew.isEmpty())
1406
+ {
1407
+ // Callself to process the new node. If we return
1408
+ // FALSE this means we dont have any more
1409
+ // processing to do...
1410
+
1411
+ if (!pNew.ParseXMLElement(pXML)) return FALSE;
1412
+ else
1413
+ {
1414
+ // If the call to recurse this function
1415
+ // evented in a end tag specified in XML then
1416
+ // we need to unwind the calls to this
1417
+ // function until we find the appropriate node
1418
+ // (the element name and end tag name must
1419
+ // match)
1420
+ if (pXML->cbEndTag)
1421
+ {
1422
+ // If we are back at the root node then we
1423
+ // have an unmatched end tag
1424
+ if (!d->lpszName)
1425
+ {
1426
+ pXML->error=eXMLErrorUnmatchedEndTag;
1427
+ return FALSE;
1428
+ }
1429
+
1430
+ // If the end tag matches the name of this
1431
+ // element then we only need to unwind
1432
+ // once more...
1433
+
1434
+ if (myTagCompare(d->lpszName, pXML->lpEndTag)==0)
1435
+ {
1436
+ pXML->cbEndTag = 0;
1437
+ }
1438
+
1439
+ return TRUE;
1440
+ } else
1441
+ if (pXML->cbNewElement)
1442
+ {
1443
+ // If the call indicated a new element is to
1444
+ // be created on THIS element.
1445
+
1446
+ // If the name of this element matches the
1447
+ // name of the element we need to create
1448
+ // then we need to return to the caller
1449
+ // and let it process the element.
1450
+
1451
+ if (myTagCompare(d->lpszName, pXML->lpNewElement)==0)
1452
+ {
1453
+ return TRUE;
1454
+ }
1455
+
1456
+ // Add the new element and recurse
1457
+ pNew = addChild_priv(MEMORYINCREASE,stringDup(pXML->lpNewElement,pXML->cbNewElement),0,-1);
1458
+ pXML->cbNewElement = 0;
1459
+ }
1460
+ else
1461
+ {
1462
+ // If we didn't have a new element to create
1463
+ pNew = emptyXMLNode;
1464
+
1465
+ }
1466
+ }
1467
+ }
1468
+ }
1469
+ break;
1470
+
1471
+ // If we found an end tag
1472
+ case eTokenTagEnd:
1473
+
1474
+ // If we have node text then add this to the element
1475
+ if (maybeAddTxT(pXML,token.pStr)) return FALSE;
1476
+
1477
+ // Find the name of the end tag
1478
+ token = GetNextToken(pXML, &cbTemp, &xtype);
1479
+
1480
+ // The end tag should be text
1481
+ if (xtype != eTokenText)
1482
+ {
1483
+ pXML->error = eXMLErrorMissingEndTagName;
1484
+ return FALSE;
1485
+ }
1486
+ lpszTemp = token.pStr;
1487
+
1488
+ // After the end tag we should find a closing tag
1489
+ token = GetNextToken(pXML, &cbToken, &xtype);
1490
+ if (xtype != eTokenCloseTag)
1491
+ {
1492
+ pXML->error = eXMLErrorMissingEndTagName;
1493
+ return FALSE;
1494
+ }
1495
+ pXML->lpszText=pXML->lpXML+pXML->nIndex;
1496
+
1497
+ // We need to return to the previous caller. If the name
1498
+ // of the tag cannot be found we need to keep returning to
1499
+ // caller until we find a match
1500
+ if (myTagCompare(d->lpszName, lpszTemp) != 0)
1501
+ #ifdef STRICT_PARSING
1502
+ {
1503
+ pXML->error=eXMLErrorUnmatchedEndTag;
1504
+ pXML->nIndexMissigEndTag=pXML->nIndex;
1505
+ return FALSE;
1506
+ }
1507
+ #else
1508
+ {
1509
+ pXML->error=eXMLErrorMissingEndTag;
1510
+ pXML->nIndexMissigEndTag=pXML->nIndex;
1511
+ pXML->lpEndTag = lpszTemp;
1512
+ pXML->cbEndTag = cbTemp;
1513
+ }
1514
+ #endif
1515
+
1516
+ // Return to the caller
1517
+ exactMemory(d);
1518
+ return TRUE;
1519
+
1520
+ // If we found a clear (unformatted) token
1521
+ case eTokenClear:
1522
+ // If we have node text then add this to the element
1523
+ if (maybeAddTxT(pXML,token.pStr)) return FALSE;
1524
+ if (parseClearTag(pXML, token.pClr)) return FALSE;
1525
+ pXML->lpszText=pXML->lpXML+pXML->nIndex;
1526
+ break;
1527
+
1528
+ default:
1529
+ break;
1530
+ }
1531
+ break;
1532
+
1533
+ // If we are inside a tag definition we need to search for attributes
1534
+ case eInsideTag:
1535
+
1536
+ // Check what part of the attribute (name, equals, value) we
1537
+ // are looking for.
1538
+ switch(attrib)
1539
+ {
1540
+ // If we are looking for a new attribute
1541
+ case eAttribName:
1542
+
1543
+ // Check what the current token type is
1544
+ switch(xtype)
1545
+ {
1546
+ // If the current type is text...
1547
+ // Eg. 'attribute'
1548
+ case eTokenText:
1549
+ // Cache the token then indicate that we are next to
1550
+ // look for the equals
1551
+ lpszTemp = token.pStr;
1552
+ cbTemp = cbToken;
1553
+ attrib = eAttribEquals;
1554
+ break;
1555
+
1556
+ // If we found a closing tag...
1557
+ // Eg. '>'
1558
+ case eTokenCloseTag:
1559
+ // We are now outside the tag
1560
+ status = eOutsideTag;
1561
+ pXML->lpszText=pXML->lpXML+pXML->nIndex;
1562
+ break;
1563
+
1564
+ // If we found a short hand '/>' closing tag then we can
1565
+ // return to the caller
1566
+ case eTokenShortHandClose:
1567
+ exactMemory(d);
1568
+ pXML->lpszText=pXML->lpXML+pXML->nIndex;
1569
+ return TRUE;
1570
+
1571
+ // Errors...
1572
+ case eTokenQuotedText: /* '"SomeText"' */
1573
+ case eTokenTagStart: /* '<' */
1574
+ case eTokenTagEnd: /* '</' */
1575
+ case eTokenEquals: /* '=' */
1576
+ case eTokenDeclaration: /* '<?' */
1577
+ case eTokenClear:
1578
+ pXML->error = eXMLErrorUnexpectedToken;
1579
+ return FALSE;
1580
+ default: break;
1581
+ }
1582
+ break;
1583
+
1584
+ // If we are looking for an equals
1585
+ case eAttribEquals:
1586
+ // Check what the current token type is
1587
+ switch(xtype)
1588
+ {
1589
+ // If the current type is text...
1590
+ // Eg. 'Attribute AnotherAttribute'
1591
+ case eTokenText:
1592
+ // Add the unvalued attribute to the list
1593
+ addAttribute_priv(MEMORYINCREASE,stringDup(lpszTemp,cbTemp), NULL);
1594
+ // Cache the token then indicate. We are next to
1595
+ // look for the equals attribute
1596
+ lpszTemp = token.pStr;
1597
+ cbTemp = cbToken;
1598
+ break;
1599
+
1600
+ // If we found a closing tag 'Attribute >' or a short hand
1601
+ // closing tag 'Attribute />'
1602
+ case eTokenShortHandClose:
1603
+ case eTokenCloseTag:
1604
+ // If we are a declaration element '<?' then we need
1605
+ // to remove extra closing '?' if it exists
1606
+ pXML->lpszText=pXML->lpXML+pXML->nIndex;
1607
+
1608
+ if (d->isDeclaration &&
1609
+ (lpszTemp[cbTemp-1]) == _CXML('?'))
1610
+ {
1611
+ cbTemp--;
1612
+ if (d->pParent && d->pParent->pParent) xtype = eTokenShortHandClose;
1613
+ }
1614
+
1615
+ if (cbTemp)
1616
+ {
1617
+ // Add the unvalued attribute to the list
1618
+ addAttribute_priv(MEMORYINCREASE,stringDup(lpszTemp,cbTemp), NULL);
1619
+ }
1620
+
1621
+ // If this is the end of the tag then return to the caller
1622
+ if (xtype == eTokenShortHandClose)
1623
+ {
1624
+ exactMemory(d);
1625
+ return TRUE;
1626
+ }
1627
+
1628
+ // We are now outside the tag
1629
+ status = eOutsideTag;
1630
+ break;
1631
+
1632
+ // If we found the equals token...
1633
+ // Eg. 'Attribute ='
1634
+ case eTokenEquals:
1635
+ // Indicate that we next need to search for the value
1636
+ // for the attribute
1637
+ attrib = eAttribValue;
1638
+ break;
1639
+
1640
+ // Errors...
1641
+ case eTokenQuotedText: /* 'Attribute "InvalidAttr"'*/
1642
+ case eTokenTagStart: /* 'Attribute <' */
1643
+ case eTokenTagEnd: /* 'Attribute </' */
1644
+ case eTokenDeclaration: /* 'Attribute <?' */
1645
+ case eTokenClear:
1646
+ pXML->error = eXMLErrorUnexpectedToken;
1647
+ return FALSE;
1648
+ default: break;
1649
+ }
1650
+ break;
1651
+
1652
+ // If we are looking for an attribute value
1653
+ case eAttribValue:
1654
+ // Check what the current token type is
1655
+ switch(xtype)
1656
+ {
1657
+ // If the current type is text or quoted text...
1658
+ // Eg. 'Attribute = "Value"' or 'Attribute = Value' or
1659
+ // 'Attribute = 'Value''.
1660
+ case eTokenText:
1661
+ case eTokenQuotedText:
1662
+ // If we are a declaration element '<?' then we need
1663
+ // to remove extra closing '?' if it exists
1664
+ if (d->isDeclaration &&
1665
+ (token.pStr[cbToken-1]) == _CXML('?'))
1666
+ {
1667
+ cbToken--;
1668
+ }
1669
+
1670
+ if (cbTemp)
1671
+ {
1672
+ // Add the valued attribute to the list
1673
+ if (xtype==eTokenQuotedText) { token.pStr++; cbToken-=2; }
1674
+ XMLSTR attrVal=(XMLSTR)token.pStr;
1675
+ if (attrVal)
1676
+ {
1677
+ attrVal=fromXMLString(attrVal,cbToken,pXML);
1678
+ if (!attrVal) return FALSE;
1679
+ }
1680
+ addAttribute_priv(MEMORYINCREASE,stringDup(lpszTemp,cbTemp),attrVal);
1681
+ }
1682
+
1683
+ // Indicate we are searching for a new attribute
1684
+ attrib = eAttribName;
1685
+ break;
1686
+
1687
+ // Errors...
1688
+ case eTokenTagStart: /* 'Attr = <' */
1689
+ case eTokenTagEnd: /* 'Attr = </' */
1690
+ case eTokenCloseTag: /* 'Attr = >' */
1691
+ case eTokenShortHandClose: /* "Attr = />" */
1692
+ case eTokenEquals: /* 'Attr = =' */
1693
+ case eTokenDeclaration: /* 'Attr = <?' */
1694
+ case eTokenClear:
1695
+ pXML->error = eXMLErrorUnexpectedToken;
1696
+ return FALSE;
1697
+ break;
1698
+ default: break;
1699
+ }
1700
+ }
1701
+ }
1702
+ }
1703
+ // If we failed to obtain the next token
1704
+ else
1705
+ {
1706
+ if ((!d->isDeclaration)&&(d->pParent))
1707
+ {
1708
+ #ifdef STRICT_PARSING
1709
+ pXML->error=eXMLErrorUnmatchedEndTag;
1710
+ #else
1711
+ pXML->error=eXMLErrorMissingEndTag;
1712
+ #endif
1713
+ pXML->nIndexMissigEndTag=pXML->nIndex;
1714
+ }
1715
+ maybeAddTxT(pXML,pXML->lpXML+pXML->nIndex);
1716
+ return FALSE;
1717
+ }
1718
+ }
1719
+ }
1720
+
1721
+ // Count the number of lines and columns in an XML string.
1722
+ static void CountLinesAndColumns(XMLCSTR lpXML, int nUpto, XMLResults *pResults)
1723
+ {
1724
+ XMLCHAR ch;
1725
+ assert(lpXML);
1726
+ assert(pResults);
1727
+
1728
+ struct XML xml={ lpXML,lpXML, 0, 0, eXMLErrorNone, NULL, 0, NULL, 0, TRUE };
1729
+
1730
+ pResults->nLine = 1;
1731
+ pResults->nColumn = 1;
1732
+ while (xml.nIndex<nUpto)
1733
+ {
1734
+ ch = getNextChar(&xml);
1735
+ if (ch != _CXML('\n')) pResults->nColumn++;
1736
+ else
1737
+ {
1738
+ pResults->nLine++;
1739
+ pResults->nColumn=1;
1740
+ }
1741
+ }
1742
+ }
1743
+
1744
+ // Parse XML and return the root element.
1745
+ XMLNode XMLNode::parseString(XMLCSTR lpszXML, XMLCSTR tag, XMLResults *pResults)
1746
+ {
1747
+ if (!lpszXML)
1748
+ {
1749
+ if (pResults)
1750
+ {
1751
+ pResults->error=eXMLErrorNoElements;
1752
+ pResults->nLine=0;
1753
+ pResults->nColumn=0;
1754
+ }
1755
+ return emptyXMLNode;
1756
+ }
1757
+
1758
+ XMLNode xnode(NULL,NULL,FALSE);
1759
+ struct XML xml={ lpszXML, lpszXML, 0, 0, eXMLErrorNone, NULL, 0, NULL, 0, TRUE };
1760
+
1761
+ // Create header element
1762
+ xnode.ParseXMLElement(&xml);
1763
+ enum XMLError error = xml.error;
1764
+ if (!xnode.nChildNode()) error=eXMLErrorNoXMLTagFound;
1765
+ if ((xnode.nChildNode()==1)&&(xnode.nElement()==1)) xnode=xnode.getChildNode(); // skip the empty node
1766
+
1767
+ // If no error occurred
1768
+ if ((error==eXMLErrorNone)||(error==eXMLErrorMissingEndTag)||(error==eXMLErrorNoXMLTagFound))
1769
+ {
1770
+ XMLCSTR name=xnode.getName();
1771
+ if (tag&&(*tag)&&((!name)||(xstricmp(name,tag))))
1772
+ {
1773
+ xnode=xnode.getChildNode(tag);
1774
+ if (xnode.isEmpty())
1775
+ {
1776
+ if (pResults)
1777
+ {
1778
+ pResults->error=eXMLErrorFirstTagNotFound;
1779
+ pResults->nLine=0;
1780
+ pResults->nColumn=0;
1781
+ }
1782
+ return emptyXMLNode;
1783
+ }
1784
+ }
1785
+ } else
1786
+ {
1787
+ // Cleanup: this will destroy all the nodes
1788
+ xnode = emptyXMLNode;
1789
+ }
1790
+
1791
+
1792
+ // If we have been given somewhere to place results
1793
+ if (pResults)
1794
+ {
1795
+ pResults->error = error;
1796
+
1797
+ // If we have an error
1798
+ if (error!=eXMLErrorNone)
1799
+ {
1800
+ if (error==eXMLErrorMissingEndTag) xml.nIndex=xml.nIndexMissigEndTag;
1801
+ // Find which line and column it starts on.
1802
+ CountLinesAndColumns(xml.lpXML, xml.nIndex, pResults);
1803
+ }
1804
+ }
1805
+ return xnode;
1806
+ }
1807
+
1808
+ XMLNode XMLNode::parseFile(XMLCSTR filename, XMLCSTR tag, XMLResults *pResults)
1809
+ {
1810
+ if (pResults) { pResults->nLine=0; pResults->nColumn=0; }
1811
+ FILE *f=xfopen(filename,_CXML("rb"));
1812
+ if (f==NULL) { if (pResults) pResults->error=eXMLErrorFileNotFound; return emptyXMLNode; }
1813
+ fseek(f,0,SEEK_END);
1814
+ int l=ftell(f),headerSz=0;
1815
+ if (!l) { if (pResults) pResults->error=eXMLErrorEmpty; fclose(f); return emptyXMLNode; }
1816
+ fseek(f,0,SEEK_SET);
1817
+ unsigned char *buf=(unsigned char*)malloc(l+4);
1818
+ l=fread(buf,1,l,f);
1819
+ fclose(f);
1820
+ buf[l]=0;buf[l+1]=0;buf[l+2]=0;buf[l+3]=0;
1821
+ #ifdef _XMLWIDECHAR
1822
+ if (guessWideCharChars)
1823
+ {
1824
+ if (!myIsTextWideChar(buf,l))
1825
+ {
1826
+ XMLNode::XMLCharEncoding ce=XMLNode::char_encoding_legacy;
1827
+ if ((buf[0]==0xef)&&(buf[1]==0xbb)&&(buf[2]==0xbf)) { headerSz=3; ce=XMLNode::char_encoding_UTF8; }
1828
+ XMLSTR b2=myMultiByteToWideChar((const char*)(buf+headerSz),ce);
1829
+ free(buf); buf=(unsigned char*)b2; headerSz=0;
1830
+ } else
1831
+ {
1832
+ if ((buf[0]==0xef)&&(buf[1]==0xff)) headerSz=2;
1833
+ if ((buf[0]==0xff)&&(buf[1]==0xfe)) headerSz=2;
1834
+ }
1835
+ }
1836
+ #else
1837
+ if (guessWideCharChars)
1838
+ {
1839
+ if (myIsTextWideChar(buf,l))
1840
+ {
1841
+ if ((buf[0]==0xef)&&(buf[1]==0xff)) headerSz=2;
1842
+ if ((buf[0]==0xff)&&(buf[1]==0xfe)) headerSz=2;
1843
+ char *b2=myWideCharToMultiByte((const wchar_t*)(buf+headerSz));
1844
+ free(buf); buf=(unsigned char*)b2; headerSz=0;
1845
+ } else
1846
+ {
1847
+ if ((buf[0]==0xef)&&(buf[1]==0xbb)&&(buf[2]==0xbf)) headerSz=3;
1848
+ }
1849
+ }
1850
+ #endif
1851
+
1852
+ if (!buf) { if (pResults) pResults->error=eXMLErrorCharConversionError; return emptyXMLNode; }
1853
+ XMLNode x=parseString((XMLSTR)(buf+headerSz),tag,pResults);
1854
+ free(buf);
1855
+ return x;
1856
+ }
1857
+
1858
+ static inline void charmemset(XMLSTR dest,XMLCHAR c,int l) { while (l--) *(dest++)=c; }
1859
+ // private:
1860
+ // Creates an user friendly XML string from a given element with
1861
+ // appropriate white space and carriage returns.
1862
+ //
1863
+ // This recurses through all subnodes then adds contents of the nodes to the
1864
+ // string.
1865
+ int XMLNode::CreateXMLStringR(XMLNodeData *pEntry, XMLSTR lpszMarker, int nFormat)
1866
+ {
1867
+ int nResult = 0;
1868
+ int cb=nFormat<0?0:nFormat;
1869
+ int cbElement;
1870
+ int nChildFormat=-1;
1871
+ int nElementI=pEntry->nChild+pEntry->nText+pEntry->nClear;
1872
+ int i,j;
1873
+ if ((nFormat>=0)&&(nElementI==1)&&(pEntry->nText==1)&&(!pEntry->isDeclaration)) nFormat=-2;
1874
+
1875
+ assert(pEntry);
1876
+
1877
+ #define LENSTR(lpsz) (lpsz ? xstrlen(lpsz) : 0)
1878
+
1879
+ // If the element has no name then assume this is the head node.
1880
+ cbElement = (int)LENSTR(pEntry->lpszName);
1881
+
1882
+ if (cbElement)
1883
+ {
1884
+ // "<elementname "
1885
+ if (lpszMarker)
1886
+ {
1887
+ if (cb) charmemset(lpszMarker, INDENTCHAR, cb);
1888
+ nResult = cb;
1889
+ lpszMarker[nResult++]=_CXML('<');
1890
+ if (pEntry->isDeclaration) lpszMarker[nResult++]=_CXML('?');
1891
+ xstrcpy(&lpszMarker[nResult], pEntry->lpszName);
1892
+ nResult+=cbElement;
1893
+ lpszMarker[nResult++]=_CXML(' ');
1894
+
1895
+ } else
1896
+ {
1897
+ nResult+=cbElement+2+cb;
1898
+ if (pEntry->isDeclaration) nResult++;
1899
+ }
1900
+
1901
+ // Enumerate attributes and add them to the string
1902
+ XMLAttribute *pAttr=pEntry->pAttribute;
1903
+ for (i=0; i<pEntry->nAttribute; i++)
1904
+ {
1905
+ // "Attrib
1906
+ cb = (int)LENSTR(pAttr->lpszName);
1907
+ if (cb)
1908
+ {
1909
+ if (lpszMarker) xstrcpy(&lpszMarker[nResult], pAttr->lpszName);
1910
+ nResult += cb;
1911
+ // "Attrib=Value "
1912
+ if (pAttr->lpszValue)
1913
+ {
1914
+ cb=(int)ToXMLStringTool::lengthXMLString(pAttr->lpszValue);
1915
+ if (lpszMarker)
1916
+ {
1917
+ lpszMarker[nResult]=_CXML('=');
1918
+ lpszMarker[nResult+1]=_CXML('"');
1919
+ if (cb) ToXMLStringTool::toXMLUnSafe(&lpszMarker[nResult+2],pAttr->lpszValue);
1920
+ lpszMarker[nResult+cb+2]=_CXML('"');
1921
+ }
1922
+ nResult+=cb+3;
1923
+ }
1924
+ if (lpszMarker) lpszMarker[nResult] = _CXML(' ');
1925
+ nResult++;
1926
+ }
1927
+ pAttr++;
1928
+ }
1929
+
1930
+ if (pEntry->isDeclaration)
1931
+ {
1932
+ if (lpszMarker)
1933
+ {
1934
+ lpszMarker[nResult-1]=_CXML('?');
1935
+ lpszMarker[nResult]=_CXML('>');
1936
+ }
1937
+ nResult++;
1938
+ if (nFormat!=-1)
1939
+ {
1940
+ if (lpszMarker) lpszMarker[nResult]=_CXML('\n');
1941
+ nResult++;
1942
+ }
1943
+ } else
1944
+ // If there are child nodes we need to terminate the start tag
1945
+ if (nElementI)
1946
+ {
1947
+ if (lpszMarker) lpszMarker[nResult-1]=_CXML('>');
1948
+ if (nFormat>=0)
1949
+ {
1950
+ if (lpszMarker) lpszMarker[nResult]=_CXML('\n');
1951
+ nResult++;
1952
+ }
1953
+ } else nResult--;
1954
+ }
1955
+
1956
+ // Calculate the child format for when we recurse. This is used to
1957
+ // determine the number of spaces used for prefixes.
1958
+ if (nFormat!=-1)
1959
+ {
1960
+ if (cbElement&&(!pEntry->isDeclaration)) nChildFormat=nFormat+1;
1961
+ else nChildFormat=nFormat;
1962
+ }
1963
+
1964
+ // Enumerate through remaining children
1965
+ for (i=0; i<nElementI; i++)
1966
+ {
1967
+ j=pEntry->pOrder[i];
1968
+ switch((XMLElementType)(j&3))
1969
+ {
1970
+ // Text nodes
1971
+ case eNodeText:
1972
+ {
1973
+ // "Text"
1974
+ XMLCSTR pChild=pEntry->pText[j>>2];
1975
+ cb = (int)ToXMLStringTool::lengthXMLString(pChild);
1976
+ if (cb)
1977
+ {
1978
+ if (nFormat>=0)
1979
+ {
1980
+ if (lpszMarker)
1981
+ {
1982
+ charmemset(&lpszMarker[nResult],INDENTCHAR,nFormat+1);
1983
+ ToXMLStringTool::toXMLUnSafe(&lpszMarker[nResult+nFormat+1],pChild);
1984
+ lpszMarker[nResult+nFormat+1+cb]=_CXML('\n');
1985
+ }
1986
+ nResult+=cb+nFormat+2;
1987
+ } else
1988
+ {
1989
+ if (lpszMarker) ToXMLStringTool::toXMLUnSafe(&lpszMarker[nResult], pChild);
1990
+ nResult += cb;
1991
+ }
1992
+ }
1993
+ break;
1994
+ }
1995
+
1996
+ // Clear type nodes
1997
+ case eNodeClear:
1998
+ {
1999
+ XMLClear *pChild=pEntry->pClear+(j>>2);
2000
+ // "OpenTag"
2001
+ cb = (int)LENSTR(pChild->lpszOpenTag);
2002
+ if (cb)
2003
+ {
2004
+ if (nFormat!=-1)
2005
+ {
2006
+ if (lpszMarker)
2007
+ {
2008
+ charmemset(&lpszMarker[nResult], INDENTCHAR, nFormat+1);
2009
+ xstrcpy(&lpszMarker[nResult+nFormat+1], pChild->lpszOpenTag);
2010
+ }
2011
+ nResult+=cb+nFormat+1;
2012
+ }
2013
+ else
2014
+ {
2015
+ if (lpszMarker)xstrcpy(&lpszMarker[nResult], pChild->lpszOpenTag);
2016
+ nResult += cb;
2017
+ }
2018
+ }
2019
+
2020
+ // "OpenTag Value"
2021
+ cb = (int)LENSTR(pChild->lpszValue);
2022
+ if (cb)
2023
+ {
2024
+ if (lpszMarker) xstrcpy(&lpszMarker[nResult], pChild->lpszValue);
2025
+ nResult += cb;
2026
+ }
2027
+
2028
+ // "OpenTag Value CloseTag"
2029
+ cb = (int)LENSTR(pChild->lpszCloseTag);
2030
+ if (cb)
2031
+ {
2032
+ if (lpszMarker) xstrcpy(&lpszMarker[nResult], pChild->lpszCloseTag);
2033
+ nResult += cb;
2034
+ }
2035
+
2036
+ if (nFormat!=-1)
2037
+ {
2038
+ if (lpszMarker) lpszMarker[nResult] = _CXML('\n');
2039
+ nResult++;
2040
+ }
2041
+ break;
2042
+ }
2043
+
2044
+ // Element nodes
2045
+ case eNodeChild:
2046
+ {
2047
+ // Recursively add child nodes
2048
+ nResult += CreateXMLStringR(pEntry->pChild[j>>2].d, lpszMarker ? lpszMarker + nResult : 0, nChildFormat);
2049
+ break;
2050
+ }
2051
+ default: break;
2052
+ }
2053
+ }
2054
+
2055
+ if ((cbElement)&&(!pEntry->isDeclaration))
2056
+ {
2057
+ // If we have child entries we need to use long XML notation for
2058
+ // closing the element - "<elementname>blah blah blah</elementname>"
2059
+ if (nElementI)
2060
+ {
2061
+ // "</elementname>\0"
2062
+ if (lpszMarker)
2063
+ {
2064
+ if (nFormat >=0)
2065
+ {
2066
+ charmemset(&lpszMarker[nResult], INDENTCHAR,nFormat);
2067
+ nResult+=nFormat;
2068
+ }
2069
+
2070
+ lpszMarker[nResult]=_CXML('<'); lpszMarker[nResult+1]=_CXML('/');
2071
+ nResult += 2;
2072
+ xstrcpy(&lpszMarker[nResult], pEntry->lpszName);
2073
+ nResult += cbElement;
2074
+
2075
+ lpszMarker[nResult]=_CXML('>');
2076
+ if (nFormat == -1) nResult++;
2077
+ else
2078
+ {
2079
+ lpszMarker[nResult+1]=_CXML('\n');
2080
+ nResult+=2;
2081
+ }
2082
+ } else
2083
+ {
2084
+ if (nFormat>=0) nResult+=cbElement+4+nFormat;
2085
+ else if (nFormat==-1) nResult+=cbElement+3;
2086
+ else nResult+=cbElement+4;
2087
+ }
2088
+ } else
2089
+ {
2090
+ // If there are no children we can use shorthand XML notation -
2091
+ // "<elementname/>"
2092
+ // "/>\0"
2093
+ if (lpszMarker)
2094
+ {
2095
+ lpszMarker[nResult]=_CXML('/'); lpszMarker[nResult+1]=_CXML('>');
2096
+ if (nFormat != -1) lpszMarker[nResult+2]=_CXML('\n');
2097
+ }
2098
+ nResult += nFormat == -1 ? 2 : 3;
2099
+ }
2100
+ }
2101
+
2102
+ return nResult;
2103
+ }
2104
+
2105
+ #undef LENSTR
2106
+
2107
+ // Create an XML string
2108
+ // @param int nFormat - 0 if no formatting is required
2109
+ // otherwise nonzero for formatted text
2110
+ // with carriage returns and indentation.
2111
+ // @param int *pnSize - [out] pointer to the size of the
2112
+ // returned string not including the
2113
+ // NULL terminator.
2114
+ // @return XMLSTR - Allocated XML string, you must free
2115
+ // this with free().
2116
+ XMLSTR XMLNode::createXMLString(int nFormat, int *pnSize) const
2117
+ {
2118
+ if (!d) { if (pnSize) *pnSize=0; return NULL; }
2119
+
2120
+ XMLSTR lpszResult = NULL;
2121
+ int cbStr;
2122
+
2123
+ // Recursively Calculate the size of the XML string
2124
+ if (!dropWhiteSpace) nFormat=0;
2125
+ nFormat = nFormat ? 0 : -1;
2126
+ cbStr = CreateXMLStringR(d, 0, nFormat);
2127
+ // Alllocate memory for the XML string + the NULL terminator and
2128
+ // create the recursively XML string.
2129
+ lpszResult=(XMLSTR)malloc((cbStr+1)*sizeof(XMLCHAR));
2130
+ CreateXMLStringR(d, lpszResult, nFormat);
2131
+ lpszResult[cbStr]=_CXML('\0');
2132
+ if (pnSize) *pnSize = cbStr;
2133
+ return lpszResult;
2134
+ }
2135
+
2136
+ int XMLNode::detachFromParent(XMLNodeData *d)
2137
+ {
2138
+ XMLNode *pa=d->pParent->pChild;
2139
+ int i=0;
2140
+ while (((void*)(pa[i].d))!=((void*)d)) i++;
2141
+ d->pParent->nChild--;
2142
+ if (d->pParent->nChild) memmove(pa+i,pa+i+1,(d->pParent->nChild-i)*sizeof(XMLNode));
2143
+ else { free(pa); d->pParent->pChild=NULL; }
2144
+ return removeOrderElement(d->pParent,eNodeChild,i);
2145
+ }
2146
+
2147
+ XMLNode::~XMLNode()
2148
+ {
2149
+ if (!d) return;
2150
+ d->ref_count--;
2151
+ emptyTheNode(0);
2152
+ }
2153
+ void XMLNode::deleteNodeContent()
2154
+ {
2155
+ if (!d) return;
2156
+ if (d->pParent) { detachFromParent(d); d->pParent=NULL; d->ref_count--; }
2157
+ emptyTheNode(1);
2158
+ }
2159
+ void XMLNode::emptyTheNode(char force)
2160
+ {
2161
+ XMLNodeData *dd=d; // warning: must stay this way!
2162
+ if ((dd->ref_count==0)||force)
2163
+ {
2164
+ if (d->pParent) detachFromParent(d);
2165
+ int i;
2166
+ XMLNode *pc;
2167
+ for(i=0; i<dd->nChild; i++)
2168
+ {
2169
+ pc=dd->pChild+i;
2170
+ pc->d->pParent=NULL;
2171
+ pc->d->ref_count--;
2172
+ pc->emptyTheNode(force);
2173
+ }
2174
+ myFree(dd->pChild);
2175
+ for(i=0; i<dd->nText; i++) free((void*)dd->pText[i]);
2176
+ myFree(dd->pText);
2177
+ for(i=0; i<dd->nClear; i++) free((void*)dd->pClear[i].lpszValue);
2178
+ myFree(dd->pClear);
2179
+ for(i=0; i<dd->nAttribute; i++)
2180
+ {
2181
+ free((void*)dd->pAttribute[i].lpszName);
2182
+ if (dd->pAttribute[i].lpszValue) free((void*)dd->pAttribute[i].lpszValue);
2183
+ }
2184
+ myFree(dd->pAttribute);
2185
+ myFree(dd->pOrder);
2186
+ myFree((void*)dd->lpszName);
2187
+ dd->nChild=0; dd->nText=0; dd->nClear=0; dd->nAttribute=0;
2188
+ dd->pChild=NULL; dd->pText=NULL; dd->pClear=NULL; dd->pAttribute=NULL;
2189
+ dd->pOrder=NULL; dd->lpszName=NULL; dd->pParent=NULL;
2190
+ }
2191
+ if (dd->ref_count==0)
2192
+ {
2193
+ free(dd);
2194
+ d=NULL;
2195
+ }
2196
+ }
2197
+
2198
+ XMLNode& XMLNode::operator=( const XMLNode& A )
2199
+ {
2200
+ // shallow copy
2201
+ if (this != &A)
2202
+ {
2203
+ if (d) { d->ref_count--; emptyTheNode(0); }
2204
+ d=A.d;
2205
+ if (d) (d->ref_count) ++ ;
2206
+ }
2207
+ return *this;
2208
+ }
2209
+
2210
+ XMLNode::XMLNode(const XMLNode &A)
2211
+ {
2212
+ // shallow copy
2213
+ d=A.d;
2214
+ if (d) (d->ref_count)++ ;
2215
+ }
2216
+
2217
+ XMLNode XMLNode::deepCopy() const
2218
+ {
2219
+ if (!d) return XMLNode::emptyXMLNode;
2220
+ XMLNode x(NULL,stringDup(d->lpszName),d->isDeclaration);
2221
+ XMLNodeData *p=x.d;
2222
+ int n=d->nAttribute;
2223
+ if (n)
2224
+ {
2225
+ p->nAttribute=n; p->pAttribute=(XMLAttribute*)malloc(n*sizeof(XMLAttribute));
2226
+ while (n--)
2227
+ {
2228
+ p->pAttribute[n].lpszName=stringDup(d->pAttribute[n].lpszName);
2229
+ p->pAttribute[n].lpszValue=stringDup(d->pAttribute[n].lpszValue);
2230
+ }
2231
+ }
2232
+ if (d->pOrder)
2233
+ {
2234
+ n=(d->nChild+d->nText+d->nClear)*sizeof(int); p->pOrder=(int*)malloc(n); memcpy(p->pOrder,d->pOrder,n);
2235
+ }
2236
+ n=d->nText;
2237
+ if (n)
2238
+ {
2239
+ p->nText=n; p->pText=(XMLCSTR*)malloc(n*sizeof(XMLCSTR));
2240
+ while(n--) p->pText[n]=stringDup(d->pText[n]);
2241
+ }
2242
+ n=d->nClear;
2243
+ if (n)
2244
+ {
2245
+ p->nClear=n; p->pClear=(XMLClear*)malloc(n*sizeof(XMLClear));
2246
+ while (n--)
2247
+ {
2248
+ p->pClear[n].lpszCloseTag=d->pClear[n].lpszCloseTag;
2249
+ p->pClear[n].lpszOpenTag=d->pClear[n].lpszOpenTag;
2250
+ p->pClear[n].lpszValue=stringDup(d->pClear[n].lpszValue);
2251
+ }
2252
+ }
2253
+ n=d->nChild;
2254
+ if (n)
2255
+ {
2256
+ p->nChild=n; p->pChild=(XMLNode*)malloc(n*sizeof(XMLNode));
2257
+ while (n--)
2258
+ {
2259
+ p->pChild[n].d=NULL;
2260
+ p->pChild[n]=d->pChild[n].deepCopy();
2261
+ p->pChild[n].d->pParent=p;
2262
+ }
2263
+ }
2264
+ return x;
2265
+ }
2266
+
2267
+ XMLNode XMLNode::addChild(XMLNode childNode, int pos)
2268
+ {
2269
+ XMLNodeData *dc=childNode.d;
2270
+ if ((!dc)||(!d)) return childNode;
2271
+ if (!dc->lpszName)
2272
+ {
2273
+ // this is a root node: todo: correct fix
2274
+ int j=pos;
2275
+ while (dc->nChild)
2276
+ {
2277
+ addChild(dc->pChild[0],j);
2278
+ if (pos>=0) j++;
2279
+ }
2280
+ return childNode;
2281
+ }
2282
+ if (dc->pParent) { if ((detachFromParent(dc)<=pos)&&(dc->pParent==d)) pos--; } else dc->ref_count++;
2283
+ dc->pParent=d;
2284
+ // int nc=d->nChild;
2285
+ // d->pChild=(XMLNode*)myRealloc(d->pChild,(nc+1),memoryIncrease,sizeof(XMLNode));
2286
+ d->pChild=(XMLNode*)addToOrder(0,&pos,d->nChild,d->pChild,sizeof(XMLNode),eNodeChild);
2287
+ d->pChild[pos].d=dc;
2288
+ d->nChild++;
2289
+ return childNode;
2290
+ }
2291
+
2292
+ void XMLNode::deleteAttribute(int i)
2293
+ {
2294
+ if ((!d)||(i<0)||(i>=d->nAttribute)) return;
2295
+ d->nAttribute--;
2296
+ XMLAttribute *p=d->pAttribute+i;
2297
+ free((void*)p->lpszName);
2298
+ if (p->lpszValue) free((void*)p->lpszValue);
2299
+ if (d->nAttribute) memmove(p,p+1,(d->nAttribute-i)*sizeof(XMLAttribute)); else { free(p); d->pAttribute=NULL; }
2300
+ }
2301
+
2302
+ void XMLNode::deleteAttribute(XMLAttribute *a){ if (a) deleteAttribute(a->lpszName); }
2303
+ void XMLNode::deleteAttribute(XMLCSTR lpszName)
2304
+ {
2305
+ int j=0;
2306
+ getAttribute(lpszName,&j);
2307
+ if (j) deleteAttribute(j-1);
2308
+ }
2309
+
2310
+ XMLAttribute *XMLNode::updateAttribute_WOSD(XMLSTR lpszNewValue, XMLSTR lpszNewName,int i)
2311
+ {
2312
+ if (!d) { if (lpszNewValue) free(lpszNewValue); if (lpszNewName) free(lpszNewName); return NULL; }
2313
+ if (i>=d->nAttribute)
2314
+ {
2315
+ if (lpszNewName) return addAttribute_WOSD(lpszNewName,lpszNewValue);
2316
+ return NULL;
2317
+ }
2318
+ XMLAttribute *p=d->pAttribute+i;
2319
+ if (p->lpszValue&&p->lpszValue!=lpszNewValue) free((void*)p->lpszValue);
2320
+ p->lpszValue=lpszNewValue;
2321
+ if (lpszNewName&&p->lpszName!=lpszNewName) { free((void*)p->lpszName); p->lpszName=lpszNewName; };
2322
+ return p;
2323
+ }
2324
+
2325
+ XMLAttribute *XMLNode::updateAttribute_WOSD(XMLAttribute *newAttribute, XMLAttribute *oldAttribute)
2326
+ {
2327
+ if (oldAttribute) return updateAttribute_WOSD((XMLSTR)newAttribute->lpszValue,(XMLSTR)newAttribute->lpszName,oldAttribute->lpszName);
2328
+ return addAttribute_WOSD((XMLSTR)newAttribute->lpszName,(XMLSTR)newAttribute->lpszValue);
2329
+ }
2330
+
2331
+ XMLAttribute *XMLNode::updateAttribute_WOSD(XMLSTR lpszNewValue, XMLSTR lpszNewName,XMLCSTR lpszOldName)
2332
+ {
2333
+ int j=0;
2334
+ getAttribute(lpszOldName,&j);
2335
+ if (j) return updateAttribute_WOSD(lpszNewValue,lpszNewName,j-1);
2336
+ else
2337
+ {
2338
+ if (lpszNewName) return addAttribute_WOSD(lpszNewName,lpszNewValue);
2339
+ else return addAttribute_WOSD(stringDup(lpszOldName),lpszNewValue);
2340
+ }
2341
+ }
2342
+
2343
+ int XMLNode::indexText(XMLCSTR lpszValue) const
2344
+ {
2345
+ if (!d) return -1;
2346
+ int i,l=d->nText;
2347
+ if (!lpszValue) { if (l) return 0; return -1; }
2348
+ XMLCSTR *p=d->pText;
2349
+ for (i=0; i<l; i++) if (lpszValue==p[i]) return i;
2350
+ return -1;
2351
+ }
2352
+
2353
+ void XMLNode::deleteText(int i)
2354
+ {
2355
+ if ((!d)||(i<0)||(i>=d->nText)) return;
2356
+ d->nText--;
2357
+ XMLCSTR *p=d->pText+i;
2358
+ free((void*)*p);
2359
+ if (d->nText) memmove(p,p+1,(d->nText-i)*sizeof(XMLCSTR)); else { free(p); d->pText=NULL; }
2360
+ removeOrderElement(d,eNodeText,i);
2361
+ }
2362
+
2363
+ void XMLNode::deleteText(XMLCSTR lpszValue) { deleteText(indexText(lpszValue)); }
2364
+
2365
+ XMLCSTR XMLNode::updateText_WOSD(XMLSTR lpszNewValue, int i)
2366
+ {
2367
+ if (!d) { if (lpszNewValue) free(lpszNewValue); return NULL; }
2368
+ if (i>=d->nText) return addText_WOSD(lpszNewValue);
2369
+ XMLCSTR *p=d->pText+i;
2370
+ if (*p!=lpszNewValue) { free((void*)*p); *p=lpszNewValue; }
2371
+ return lpszNewValue;
2372
+ }
2373
+
2374
+ XMLCSTR XMLNode::updateText_WOSD(XMLSTR lpszNewValue, XMLCSTR lpszOldValue)
2375
+ {
2376
+ if (!d) { if (lpszNewValue) free(lpszNewValue); return NULL; }
2377
+ int i=indexText(lpszOldValue);
2378
+ if (i>=0) return updateText_WOSD(lpszNewValue,i);
2379
+ return addText_WOSD(lpszNewValue);
2380
+ }
2381
+
2382
+ void XMLNode::deleteClear(int i)
2383
+ {
2384
+ if ((!d)||(i<0)||(i>=d->nClear)) return;
2385
+ d->nClear--;
2386
+ XMLClear *p=d->pClear+i;
2387
+ free((void*)p->lpszValue);
2388
+ if (d->nClear) memmove(p,p+1,(d->nClear-i)*sizeof(XMLClear)); else { free(p); d->pClear=NULL; }
2389
+ removeOrderElement(d,eNodeClear,i);
2390
+ }
2391
+
2392
+ int XMLNode::indexClear(XMLCSTR lpszValue) const
2393
+ {
2394
+ if (!d) return -1;
2395
+ int i,l=d->nClear;
2396
+ if (!lpszValue) { if (l) return 0; return -1; }
2397
+ XMLClear *p=d->pClear;
2398
+ for (i=0; i<l; i++) if (lpszValue==p[i].lpszValue) return i;
2399
+ return -1;
2400
+ }
2401
+
2402
+ void XMLNode::deleteClear(XMLCSTR lpszValue) { deleteClear(indexClear(lpszValue)); }
2403
+ void XMLNode::deleteClear(XMLClear *a) { if (a) deleteClear(a->lpszValue); }
2404
+
2405
+ XMLClear *XMLNode::updateClear_WOSD(XMLSTR lpszNewContent, int i)
2406
+ {
2407
+ if (!d) { if (lpszNewContent) free(lpszNewContent); return NULL; }
2408
+ if (i>=d->nClear) return addClear_WOSD(lpszNewContent);
2409
+ XMLClear *p=d->pClear+i;
2410
+ if (lpszNewContent!=p->lpszValue) { free((void*)p->lpszValue); p->lpszValue=lpszNewContent; }
2411
+ return p;
2412
+ }
2413
+
2414
+ XMLClear *XMLNode::updateClear_WOSD(XMLSTR lpszNewContent, XMLCSTR lpszOldValue)
2415
+ {
2416
+ if (!d) { if (lpszNewContent) free(lpszNewContent); return NULL; }
2417
+ int i=indexClear(lpszOldValue);
2418
+ if (i>=0) return updateClear_WOSD(lpszNewContent,i);
2419
+ return addClear_WOSD(lpszNewContent);
2420
+ }
2421
+
2422
+ XMLClear *XMLNode::updateClear_WOSD(XMLClear *newP,XMLClear *oldP)
2423
+ {
2424
+ if (oldP) return updateClear_WOSD((XMLSTR)newP->lpszValue,(XMLSTR)oldP->lpszValue);
2425
+ return NULL;
2426
+ }
2427
+
2428
+ int XMLNode::nChildNode(XMLCSTR name) const
2429
+ {
2430
+ if (!d) return 0;
2431
+ int i,j=0,n=d->nChild;
2432
+ XMLNode *pc=d->pChild;
2433
+ for (i=0; i<n; i++)
2434
+ {
2435
+ if (xstricmp(pc->d->lpszName, name)==0) j++;
2436
+ pc++;
2437
+ }
2438
+ return j;
2439
+ }
2440
+
2441
+ XMLNode XMLNode::getChildNode(XMLCSTR name, int *j) const
2442
+ {
2443
+ if (!d) return emptyXMLNode;
2444
+ int i=0,n=d->nChild;
2445
+ if (j) i=*j;
2446
+ XMLNode *pc=d->pChild+i;
2447
+ for (; i<n; i++)
2448
+ {
2449
+ if (!xstricmp(pc->d->lpszName, name))
2450
+ {
2451
+ if (j) *j=i+1;
2452
+ return *pc;
2453
+ }
2454
+ pc++;
2455
+ }
2456
+ return emptyXMLNode;
2457
+ }
2458
+
2459
+ XMLNode XMLNode::getChildNode(XMLCSTR name, int j) const
2460
+ {
2461
+ if (!d) return emptyXMLNode;
2462
+ if (j>=0)
2463
+ {
2464
+ int i=0;
2465
+ while (j-->0) getChildNode(name,&i);
2466
+ return getChildNode(name,&i);
2467
+ }
2468
+ int i=d->nChild;
2469
+ while (i--) if (!xstricmp(name,d->pChild[i].d->lpszName)) break;
2470
+ if (i<0) return emptyXMLNode;
2471
+ return getChildNode(i);
2472
+ }
2473
+
2474
+ XMLNode XMLNode::getChildNodeByPath(XMLCSTR _path, char createMissing, XMLCHAR sep)
2475
+ {
2476
+ XMLSTR path=stringDup(_path);
2477
+ XMLNode x=getChildNodeByPathNonConst(path,createMissing,sep);
2478
+ if (path) free(path);
2479
+ return x;
2480
+ }
2481
+
2482
+ XMLNode XMLNode::getChildNodeByPathNonConst(XMLSTR path, char createIfMissing, XMLCHAR sep)
2483
+ {
2484
+ if ((!path)||(!(*path))) return *this;
2485
+ XMLNode xn,xbase=*this;
2486
+ XMLCHAR *tend1,sepString[2]; sepString[0]=sep; sepString[1]=0;
2487
+ tend1=xstrstr(path,sepString);
2488
+ while(tend1)
2489
+ {
2490
+ *tend1=0;
2491
+ xn=xbase.getChildNode(path);
2492
+ *tend1=sep;
2493
+ if (xn.isEmpty())
2494
+ {
2495
+ if (createIfMissing) xn=xbase.addChild(path);
2496
+ else return XMLNode::emptyXMLNode;
2497
+ }
2498
+ xbase=xn;
2499
+ path=tend1+1;
2500
+ tend1=xstrstr(path,sepString);
2501
+ }
2502
+ xn=xbase.getChildNode(path);
2503
+ if (xn.isEmpty()&&createIfMissing) xn=xbase.addChild(path);
2504
+ return xn;
2505
+ }
2506
+
2507
+ XMLElementPosition XMLNode::positionOfText (int i) const { if (i>=d->nText ) i=d->nText-1; return findPosition(d,i,eNodeText ); }
2508
+ XMLElementPosition XMLNode::positionOfClear (int i) const { if (i>=d->nClear) i=d->nClear-1; return findPosition(d,i,eNodeClear); }
2509
+ XMLElementPosition XMLNode::positionOfChildNode(int i) const { if (i>=d->nChild) i=d->nChild-1; return findPosition(d,i,eNodeChild); }
2510
+ XMLElementPosition XMLNode::positionOfText (XMLCSTR lpszValue) const { return positionOfText (indexText (lpszValue)); }
2511
+ XMLElementPosition XMLNode::positionOfClear(XMLCSTR lpszValue) const { return positionOfClear(indexClear(lpszValue)); }
2512
+ XMLElementPosition XMLNode::positionOfClear(XMLClear *a) const { if (a) return positionOfClear(a->lpszValue); return positionOfClear(); }
2513
+ XMLElementPosition XMLNode::positionOfChildNode(XMLNode x) const
2514
+ {
2515
+ if ((!d)||(!x.d)) return -1;
2516
+ XMLNodeData *dd=x.d;
2517
+ XMLNode *pc=d->pChild;
2518
+ int i=d->nChild;
2519
+ while (i--) if (pc[i].d==dd) return findPosition(d,i,eNodeChild);
2520
+ return -1;
2521
+ }
2522
+ XMLElementPosition XMLNode::positionOfChildNode(XMLCSTR name, int count) const
2523
+ {
2524
+ if (!name) return positionOfChildNode(count);
2525
+ int j=0;
2526
+ do { getChildNode(name,&j); if (j<0) return -1; } while (count--);
2527
+ return findPosition(d,j-1,eNodeChild);
2528
+ }
2529
+
2530
+ XMLNode XMLNode::getChildNodeWithAttribute(XMLCSTR name,XMLCSTR attributeName,XMLCSTR attributeValue, int *k) const
2531
+ {
2532
+ int i=0,j;
2533
+ if (k) i=*k;
2534
+ XMLNode x;
2535
+ XMLCSTR t;
2536
+ do
2537
+ {
2538
+ x=getChildNode(name,&i);
2539
+ if (!x.isEmpty())
2540
+ {
2541
+ if (attributeValue)
2542
+ {
2543
+ j=0;
2544
+ do
2545
+ {
2546
+ t=x.getAttribute(attributeName,&j);
2547
+ if (t&&(xstricmp(attributeValue,t)==0)) { if (k) *k=i; return x; }
2548
+ } while (t);
2549
+ } else
2550
+ {
2551
+ if (x.isAttributeSet(attributeName)) { if (k) *k=i; return x; }
2552
+ }
2553
+ }
2554
+ } while (!x.isEmpty());
2555
+ return emptyXMLNode;
2556
+ }
2557
+
2558
+ // Find an attribute on an node.
2559
+ XMLCSTR XMLNode::getAttribute(XMLCSTR lpszAttrib, int *j) const
2560
+ {
2561
+ if (!d) return NULL;
2562
+ int i=0,n=d->nAttribute;
2563
+ if (j) i=*j;
2564
+ XMLAttribute *pAttr=d->pAttribute+i;
2565
+ for (; i<n; i++)
2566
+ {
2567
+ if (xstricmp(pAttr->lpszName, lpszAttrib)==0)
2568
+ {
2569
+ if (j) *j=i+1;
2570
+ return pAttr->lpszValue;
2571
+ }
2572
+ pAttr++;
2573
+ }
2574
+ return NULL;
2575
+ }
2576
+
2577
+ char XMLNode::isAttributeSet(XMLCSTR lpszAttrib) const
2578
+ {
2579
+ if (!d) return FALSE;
2580
+ int i,n=d->nAttribute;
2581
+ XMLAttribute *pAttr=d->pAttribute;
2582
+ for (i=0; i<n; i++)
2583
+ {
2584
+ if (xstricmp(pAttr->lpszName, lpszAttrib)==0)
2585
+ {
2586
+ return TRUE;
2587
+ }
2588
+ pAttr++;
2589
+ }
2590
+ return FALSE;
2591
+ }
2592
+
2593
+ XMLCSTR XMLNode::getAttribute(XMLCSTR name, int j) const
2594
+ {
2595
+ if (!d) return NULL;
2596
+ int i=0;
2597
+ while (j-->0) getAttribute(name,&i);
2598
+ return getAttribute(name,&i);
2599
+ }
2600
+
2601
+ XMLNodeContents XMLNode::enumContents(int i) const
2602
+ {
2603
+ XMLNodeContents c;
2604
+ if (!d) { c.etype=eNodeNULL; return c; }
2605
+ if (i<d->nAttribute)
2606
+ {
2607
+ c.etype=eNodeAttribute;
2608
+ c.attrib=d->pAttribute[i];
2609
+ return c;
2610
+ }
2611
+ i-=d->nAttribute;
2612
+ c.etype=(XMLElementType)(d->pOrder[i]&3);
2613
+ i=(d->pOrder[i])>>2;
2614
+ switch (c.etype)
2615
+ {
2616
+ case eNodeChild: c.child = d->pChild[i]; break;
2617
+ case eNodeText: c.text = d->pText[i]; break;
2618
+ case eNodeClear: c.clear = d->pClear[i]; break;
2619
+ default: break;
2620
+ }
2621
+ return c;
2622
+ }
2623
+
2624
+ XMLCSTR XMLNode::getName() const { if (!d) return NULL; return d->lpszName; }
2625
+ int XMLNode::nText() const { if (!d) return 0; return d->nText; }
2626
+ int XMLNode::nChildNode() const { if (!d) return 0; return d->nChild; }
2627
+ int XMLNode::nAttribute() const { if (!d) return 0; return d->nAttribute; }
2628
+ int XMLNode::nClear() const { if (!d) return 0; return d->nClear; }
2629
+ int XMLNode::nElement() const { if (!d) return 0; return d->nAttribute+d->nChild+d->nText+d->nClear; }
2630
+ XMLClear XMLNode::getClear (int i) const { if ((!d)||(i>=d->nClear )) return emptyXMLClear; return d->pClear[i]; }
2631
+ XMLAttribute XMLNode::getAttribute (int i) const { if ((!d)||(i>=d->nAttribute)) return emptyXMLAttribute; return d->pAttribute[i]; }
2632
+ XMLCSTR XMLNode::getAttributeName (int i) const { if ((!d)||(i>=d->nAttribute)) return NULL; return d->pAttribute[i].lpszName; }
2633
+ XMLCSTR XMLNode::getAttributeValue(int i) const { if ((!d)||(i>=d->nAttribute)) return NULL; return d->pAttribute[i].lpszValue; }
2634
+ XMLCSTR XMLNode::getText (int i) const { if ((!d)||(i>=d->nText )) return NULL; return d->pText[i]; }
2635
+ XMLNode XMLNode::getChildNode (int i) const { if ((!d)||(i>=d->nChild )) return emptyXMLNode; return d->pChild[i]; }
2636
+ XMLNode XMLNode::getParentNode ( ) const { if ((!d)||(!d->pParent )) return emptyXMLNode; return XMLNode(d->pParent); }
2637
+ char XMLNode::isDeclaration ( ) const { if (!d) return 0; return d->isDeclaration; }
2638
+ char XMLNode::isEmpty ( ) const { return (d==NULL); }
2639
+ XMLNode XMLNode::emptyNode ( ) { return XMLNode::emptyXMLNode; }
2640
+
2641
+ XMLNode XMLNode::addChild(XMLCSTR lpszName, char isDeclaration, XMLElementPosition pos)
2642
+ { return addChild_priv(0,stringDup(lpszName),isDeclaration,pos); }
2643
+ XMLNode XMLNode::addChild_WOSD(XMLSTR lpszName, char isDeclaration, XMLElementPosition pos)
2644
+ { return addChild_priv(0,lpszName,isDeclaration,pos); }
2645
+ XMLAttribute *XMLNode::addAttribute(XMLCSTR lpszName, XMLCSTR lpszValue)
2646
+ { return addAttribute_priv(0,stringDup(lpszName),stringDup(lpszValue)); }
2647
+ XMLAttribute *XMLNode::addAttribute_WOSD(XMLSTR lpszName, XMLSTR lpszValuev)
2648
+ { return addAttribute_priv(0,lpszName,lpszValuev); }
2649
+ XMLCSTR XMLNode::addText(XMLCSTR lpszValue, XMLElementPosition pos)
2650
+ { return addText_priv(0,stringDup(lpszValue),pos); }
2651
+ XMLCSTR XMLNode::addText_WOSD(XMLSTR lpszValue, XMLElementPosition pos)
2652
+ { return addText_priv(0,lpszValue,pos); }
2653
+ XMLClear *XMLNode::addClear(XMLCSTR lpszValue, XMLCSTR lpszOpen, XMLCSTR lpszClose, XMLElementPosition pos)
2654
+ { return addClear_priv(0,stringDup(lpszValue),lpszOpen,lpszClose,pos); }
2655
+ XMLClear *XMLNode::addClear_WOSD(XMLSTR lpszValue, XMLCSTR lpszOpen, XMLCSTR lpszClose, XMLElementPosition pos)
2656
+ { return addClear_priv(0,lpszValue,lpszOpen,lpszClose,pos); }
2657
+ XMLCSTR XMLNode::updateName(XMLCSTR lpszName)
2658
+ { return updateName_WOSD(stringDup(lpszName)); }
2659
+ XMLAttribute *XMLNode::updateAttribute(XMLAttribute *newAttribute, XMLAttribute *oldAttribute)
2660
+ { return updateAttribute_WOSD(stringDup(newAttribute->lpszValue),stringDup(newAttribute->lpszName),oldAttribute->lpszName); }
2661
+ XMLAttribute *XMLNode::updateAttribute(XMLCSTR lpszNewValue, XMLCSTR lpszNewName,int i)
2662
+ { return updateAttribute_WOSD(stringDup(lpszNewValue),stringDup(lpszNewName),i); }
2663
+ XMLAttribute *XMLNode::updateAttribute(XMLCSTR lpszNewValue, XMLCSTR lpszNewName,XMLCSTR lpszOldName)
2664
+ { return updateAttribute_WOSD(stringDup(lpszNewValue),stringDup(lpszNewName),lpszOldName); }
2665
+ XMLCSTR XMLNode::updateText(XMLCSTR lpszNewValue, int i)
2666
+ { return updateText_WOSD(stringDup(lpszNewValue),i); }
2667
+ XMLCSTR XMLNode::updateText(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue)
2668
+ { return updateText_WOSD(stringDup(lpszNewValue),lpszOldValue); }
2669
+ XMLClear *XMLNode::updateClear(XMLCSTR lpszNewContent, int i)
2670
+ { return updateClear_WOSD(stringDup(lpszNewContent),i); }
2671
+ XMLClear *XMLNode::updateClear(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue)
2672
+ { return updateClear_WOSD(stringDup(lpszNewValue),lpszOldValue); }
2673
+ XMLClear *XMLNode::updateClear(XMLClear *newP,XMLClear *oldP)
2674
+ { return updateClear_WOSD(stringDup(newP->lpszValue),oldP->lpszValue); }
2675
+
2676
+ char XMLNode::setGlobalOptions(XMLCharEncoding _characterEncoding, char _guessWideCharChars,
2677
+ char _dropWhiteSpace, char _removeCommentsInMiddleOfText)
2678
+ {
2679
+ guessWideCharChars=_guessWideCharChars; dropWhiteSpace=_dropWhiteSpace; removeCommentsInMiddleOfText=_removeCommentsInMiddleOfText;
2680
+ #ifdef _XMLWIDECHAR
2681
+ if (_characterEncoding) characterEncoding=_characterEncoding;
2682
+ #else
2683
+ switch(_characterEncoding)
2684
+ {
2685
+ case char_encoding_UTF8: characterEncoding=_characterEncoding; XML_ByteTable=XML_utf8ByteTable; break;
2686
+ case char_encoding_legacy: characterEncoding=_characterEncoding; XML_ByteTable=XML_legacyByteTable; break;
2687
+ case char_encoding_ShiftJIS: characterEncoding=_characterEncoding; XML_ByteTable=XML_sjisByteTable; break;
2688
+ case char_encoding_GB2312: characterEncoding=_characterEncoding; XML_ByteTable=XML_gb2312ByteTable; break;
2689
+ case char_encoding_Big5:
2690
+ case char_encoding_GBK: characterEncoding=_characterEncoding; XML_ByteTable=XML_gbk_big5_ByteTable; break;
2691
+ default: return 1;
2692
+ }
2693
+ #endif
2694
+ return 0;
2695
+ }
2696
+
2697
+ XMLNode::XMLCharEncoding XMLNode::guessCharEncoding(void *buf,int l, char useXMLEncodingAttribute)
2698
+ {
2699
+ #ifdef _XMLWIDECHAR
2700
+ return (XMLCharEncoding)0;
2701
+ #else
2702
+ if (l<25) return (XMLCharEncoding)0;
2703
+ if (guessWideCharChars&&(myIsTextWideChar(buf,l))) return (XMLCharEncoding)0;
2704
+ unsigned char *b=(unsigned char*)buf;
2705
+ if ((b[0]==0xef)&&(b[1]==0xbb)&&(b[2]==0xbf)) return char_encoding_UTF8;
2706
+
2707
+ // Match utf-8 model ?
2708
+ XMLCharEncoding bestGuess=char_encoding_UTF8;
2709
+ int i=0;
2710
+ while (i<l)
2711
+ switch (XML_utf8ByteTable[b[i]])
2712
+ {
2713
+ case 4: i++; if ((i<l)&&(b[i]& 0xC0)!=0x80) { bestGuess=char_encoding_legacy; i=l; } // 10bbbbbb ?
2714
+ case 3: i++; if ((i<l)&&(b[i]& 0xC0)!=0x80) { bestGuess=char_encoding_legacy; i=l; } // 10bbbbbb ?
2715
+ case 2: i++; if ((i<l)&&(b[i]& 0xC0)!=0x80) { bestGuess=char_encoding_legacy; i=l; } // 10bbbbbb ?
2716
+ case 1: i++; break;
2717
+ case 0: i=l;
2718
+ }
2719
+ if (!useXMLEncodingAttribute) return bestGuess;
2720
+ // if encoding is specified and different from utf-8 than it's non-utf8
2721
+ // otherwise it's utf-8
2722
+ char bb[201];
2723
+ l=mmin(l,200);
2724
+ memcpy(bb,buf,l); // copy buf into bb to be able to do "bb[l]=0"
2725
+ bb[l]=0;
2726
+ b=(unsigned char*)strstr(bb,"encoding");
2727
+ if (!b) return bestGuess;
2728
+ b+=8; while XML_isSPACECHAR(*b) b++; if (*b!='=') return bestGuess;
2729
+ b++; while XML_isSPACECHAR(*b) b++; if ((*b!='\'')&&(*b!='"')) return bestGuess;
2730
+ b++; while XML_isSPACECHAR(*b) b++;
2731
+
2732
+ if ((xstrnicmp((char*)b,"utf-8",5)==0)||
2733
+ (xstrnicmp((char*)b,"utf8",4)==0))
2734
+ {
2735
+ if (bestGuess==char_encoding_legacy) return char_encoding_error;
2736
+ return char_encoding_UTF8;
2737
+ }
2738
+
2739
+ if ((xstrnicmp((char*)b,"shiftjis",8)==0)||
2740
+ (xstrnicmp((char*)b,"shift-jis",9)==0)||
2741
+ (xstrnicmp((char*)b,"sjis",4)==0)) return char_encoding_ShiftJIS;
2742
+
2743
+ if (xstrnicmp((char*)b,"GB2312",6)==0) return char_encoding_GB2312;
2744
+ if (xstrnicmp((char*)b,"Big5",4)==0) return char_encoding_Big5;
2745
+ if (xstrnicmp((char*)b,"GBK",3)==0) return char_encoding_GBK;
2746
+
2747
+ return char_encoding_legacy;
2748
+ #endif
2749
+ }
2750
+ #undef XML_isSPACECHAR
2751
+
2752
+ //////////////////////////////////////////////////////////
2753
+ // Here starts the base64 conversion functions. //
2754
+ //////////////////////////////////////////////////////////
2755
+
2756
+ static const char base64Fillchar = _CXML('='); // used to mark partial words at the end
2757
+
2758
+ // this lookup table defines the base64 encoding
2759
+ XMLCSTR base64EncodeTable=_CXML("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
2760
+
2761
+ // Decode Table gives the index of any valid base64 character in the Base64 table]
2762
+ // 96: '=' - 97: space char - 98: illegal char - 99: end of string
2763
+ const unsigned char base64DecodeTable[] = {
2764
+ 99,98,98,98,98,98,98,98,98,97, 97,98,98,97,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, //00 -29
2765
+ 98,98,97,98,98,98,98,98,98,98, 98,98,98,62,98,98,98,63,52,53, 54,55,56,57,58,59,60,61,98,98, //30 -59
2766
+ 98,96,98,98,98, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, 15,16,17,18,19,20,21,22,23,24, //60 -89
2767
+ 25,98,98,98,98,98,98,26,27,28, 29,30,31,32,33,34,35,36,37,38, 39,40,41,42,43,44,45,46,47,48, //90 -119
2768
+ 49,50,51,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, //120 -149
2769
+ 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, //150 -179
2770
+ 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, //180 -209
2771
+ 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, //210 -239
2772
+ 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98 //240 -255
2773
+ };
2774
+
2775
+ XMLParserBase64Tool::~XMLParserBase64Tool(){ freeBuffer(); }
2776
+
2777
+ void XMLParserBase64Tool::freeBuffer(){ if (buf) free(buf); buf=NULL; buflen=0; }
2778
+
2779
+ int XMLParserBase64Tool::encodeLength(int inlen, char formatted)
2780
+ {
2781
+ unsigned int i=((inlen-1)/3*4+4+1);
2782
+ if (formatted) i+=inlen/54;
2783
+ return i;
2784
+ }
2785
+
2786
+ XMLSTR XMLParserBase64Tool::encode(unsigned char *inbuf, unsigned int inlen, char formatted)
2787
+ {
2788
+ int i=encodeLength(inlen,formatted),k=17,eLen=inlen/3,j;
2789
+ alloc(i*sizeof(XMLCHAR));
2790
+ XMLSTR curr=(XMLSTR)buf;
2791
+ for(i=0;i<eLen;i++)
2792
+ {
2793
+ // Copy next three bytes into lower 24 bits of int, paying attention to sign.
2794
+ j=(inbuf[0]<<16)|(inbuf[1]<<8)|inbuf[2]; inbuf+=3;
2795
+ // Encode the int into four chars
2796
+ *(curr++)=base64EncodeTable[ j>>18 ];
2797
+ *(curr++)=base64EncodeTable[(j>>12)&0x3f];
2798
+ *(curr++)=base64EncodeTable[(j>> 6)&0x3f];
2799
+ *(curr++)=base64EncodeTable[(j )&0x3f];
2800
+ if (formatted) { if (!k) { *(curr++)=_CXML('\n'); k=18; } k--; }
2801
+ }
2802
+ eLen=inlen-eLen*3; // 0 - 2.
2803
+ if (eLen==1)
2804
+ {
2805
+ *(curr++)=base64EncodeTable[ inbuf[0]>>2 ];
2806
+ *(curr++)=base64EncodeTable[(inbuf[0]<<4)&0x3F];
2807
+ *(curr++)=base64Fillchar;
2808
+ *(curr++)=base64Fillchar;
2809
+ } else if (eLen==2)
2810
+ {
2811
+ j=(inbuf[0]<<8)|inbuf[1];
2812
+ *(curr++)=base64EncodeTable[ j>>10 ];
2813
+ *(curr++)=base64EncodeTable[(j>> 4)&0x3f];
2814
+ *(curr++)=base64EncodeTable[(j<< 2)&0x3f];
2815
+ *(curr++)=base64Fillchar;
2816
+ }
2817
+ *(curr++)=0;
2818
+ return (XMLSTR)buf;
2819
+ }
2820
+
2821
+ unsigned int XMLParserBase64Tool::decodeSize(XMLCSTR data,XMLError *xe)
2822
+ {
2823
+ if (xe) *xe=eXMLErrorNone;
2824
+ int size=0;
2825
+ unsigned char c;
2826
+ //skip any extra characters (e.g. newlines or spaces)
2827
+ while (*data)
2828
+ {
2829
+ #ifdef _XMLWIDECHAR
2830
+ if (*data>255) { if (xe) *xe=eXMLErrorBase64DecodeIllegalCharacter; return 0; }
2831
+ #endif
2832
+ c=base64DecodeTable[(unsigned char)(*data)];
2833
+ if (c<97) size++;
2834
+ else if (c==98) { if (xe) *xe=eXMLErrorBase64DecodeIllegalCharacter; return 0; }
2835
+ data++;
2836
+ }
2837
+ if (xe&&(size%4!=0)) *xe=eXMLErrorBase64DataSizeIsNotMultipleOf4;
2838
+ if (size==0) return 0;
2839
+ do { data--; size--; } while(*data==base64Fillchar); size++;
2840
+ return (unsigned int)((size*3)/4);
2841
+ }
2842
+
2843
+ unsigned char XMLParserBase64Tool::decode(XMLCSTR data, unsigned char *buf, int len, XMLError *xe)
2844
+ {
2845
+ if (xe) *xe=eXMLErrorNone;
2846
+ int i=0,p=0;
2847
+ unsigned char d,c;
2848
+ for(;;)
2849
+ {
2850
+
2851
+ #ifdef _XMLWIDECHAR
2852
+ #define BASE64DECODE_READ_NEXT_CHAR(c) \
2853
+ do { \
2854
+ if (data[i]>255){ c=98; break; } \
2855
+ c=base64DecodeTable[(unsigned char)data[i++]]; \
2856
+ }while (c==97); \
2857
+ if(c==98){ if(xe)*xe=eXMLErrorBase64DecodeIllegalCharacter; return 0; }
2858
+ #else
2859
+ #define BASE64DECODE_READ_NEXT_CHAR(c) \
2860
+ do { c=base64DecodeTable[(unsigned char)data[i++]]; }while (c==97); \
2861
+ if(c==98){ if(xe)*xe=eXMLErrorBase64DecodeIllegalCharacter; return 0; }
2862
+ #endif
2863
+
2864
+ BASE64DECODE_READ_NEXT_CHAR(c)
2865
+ if (c==99) { return 2; }
2866
+ if (c==96)
2867
+ {
2868
+ if (p==(int)len) return 2;
2869
+ if (xe) *xe=eXMLErrorBase64DecodeTruncatedData;
2870
+ return 1;
2871
+ }
2872
+
2873
+ BASE64DECODE_READ_NEXT_CHAR(d)
2874
+ if ((d==99)||(d==96)) { if (xe) *xe=eXMLErrorBase64DecodeTruncatedData; return 1; }
2875
+ if (p==(int)len) { if (xe) *xe=eXMLErrorBase64DecodeBufferTooSmall; return 0; }
2876
+ buf[p++]=(unsigned char)((c<<2)|((d>>4)&0x3));
2877
+
2878
+ BASE64DECODE_READ_NEXT_CHAR(c)
2879
+ if (c==99) { if (xe) *xe=eXMLErrorBase64DecodeTruncatedData; return 1; }
2880
+ if (p==(int)len)
2881
+ {
2882
+ if (c==96) return 2;
2883
+ if (xe) *xe=eXMLErrorBase64DecodeBufferTooSmall;
2884
+ return 0;
2885
+ }
2886
+ if (c==96) { if (xe) *xe=eXMLErrorBase64DecodeTruncatedData; return 1; }
2887
+ buf[p++]=(unsigned char)(((d<<4)&0xf0)|((c>>2)&0xf));
2888
+
2889
+ BASE64DECODE_READ_NEXT_CHAR(d)
2890
+ if (d==99 ) { if (xe) *xe=eXMLErrorBase64DecodeTruncatedData; return 1; }
2891
+ if (p==(int)len)
2892
+ {
2893
+ if (d==96) return 2;
2894
+ if (xe) *xe=eXMLErrorBase64DecodeBufferTooSmall;
2895
+ return 0;
2896
+ }
2897
+ if (d==96) { if (xe) *xe=eXMLErrorBase64DecodeTruncatedData; return 1; }
2898
+ buf[p++]=(unsigned char)(((c<<6)&0xc0)|d);
2899
+ }
2900
+ }
2901
+ #undef BASE64DECODE_READ_NEXT_CHAR
2902
+
2903
+ void XMLParserBase64Tool::alloc(int newsize)
2904
+ {
2905
+ if ((!buf)&&(newsize)) { buf=malloc(newsize); buflen=newsize; return; }
2906
+ if (newsize>buflen) { buf=realloc(buf,newsize); buflen=newsize; }
2907
+ }
2908
+
2909
+ unsigned char *XMLParserBase64Tool::decode(XMLCSTR data, int *outlen, XMLError *xe)
2910
+ {
2911
+ if (xe) *xe=eXMLErrorNone;
2912
+ unsigned int len=decodeSize(data,xe);
2913
+ if (outlen) *outlen=len;
2914
+ if (!len) return NULL;
2915
+ alloc(len+1);
2916
+ if(!decode(data,(unsigned char*)buf,len,xe)){ return NULL; }
2917
+ return (unsigned char*)buf;
2918
+ }
2919
+
2920
+ #if defined _MSC_VER
2921
+ #pragma warning (pop)
2922
+ #endif
2923
+