XTPMarkupParser.cpp
上传用户:szled88
上传日期:2015-04-09
资源大小:43957k
文件大小:11k
源码类别:

对话框与窗口

开发平台:

Visual C++

  1. // XTPMarkupParser.cpp: implementation of the CXTPMarkupParser class.
  2. //
  3. // This file is a part of the XTREME TOOLKIT PRO MFC class library.
  4. // (c)1998-2008 Codejock Software, All Rights Reserved.
  5. //
  6. // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
  7. // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
  8. // CONSENT OF CODEJOCK SOFTWARE.
  9. //
  10. // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
  11. // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
  12. // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
  13. // SINGLE COMPUTER.
  14. //
  15. // CONTACT INFORMATION:
  16. // support@codejock.com
  17. // http://www.codejock.com
  18. //
  19. /////////////////////////////////////////////////////////////////////////////
  20. #include "stdafx.h"
  21. #include "Common/XTPVc80Helpers.h"
  22. #include "XTPMarkupParser.h"
  23. // Based on code of Andrew Fedoniouk @ terrainformatica.com
  24. #ifdef _DEBUG
  25. #undef THIS_FILE
  26. static char THIS_FILE[]=__FILE__;
  27. #define new DEBUG_NEW
  28. #endif
  29. //////////////////////////////////////////////////////////////////////
  30. // Construction/Destruction
  31. //////////////////////////////////////////////////////////////////////
  32. CXTPMarkupParser::CXTPMarkupParser()
  33. :   m_cInputChar(0),
  34. m_nValueLength(0),
  35. m_nTagNameLength(0),
  36. m_nAttributeNameLength(0),
  37. m_bGotTail(FALSE)
  38. {
  39. m_lpszPos = NULL;
  40. m_lpszEnd = NULL;
  41. m_nLine = 0;
  42. m_nPosition = 0;
  43. m_bUnicode = FALSE;
  44. m_nEncoding = CP_ACP;
  45. m_scan = &CXTPMarkupParser::ScanBody;
  46. }
  47. CXTPMarkupParser::~CXTPMarkupParser()
  48. {
  49. }
  50. void CXTPMarkupParser::SetBuffer(LPCSTR lpszStart, LPCSTR lpszEnd)
  51. {
  52. m_lpszPos = lpszStart;
  53. m_lpszEnd = lpszEnd;
  54. m_bUnicode = FALSE;
  55. }
  56. void CXTPMarkupParser::SetBuffer(LPCWSTR lpszStart, LPCWSTR lpszEnd)
  57. {
  58. m_lpszPos = (LPCSTR)lpszStart;
  59. m_lpszEnd = (LPCSTR)lpszEnd;
  60. m_bUnicode = TRUE;
  61. }
  62. CXTPMarkupParser::TokenType CXTPMarkupParser::GetNextToken()
  63. {
  64. return (this->*m_scan)();
  65. }
  66. const WCHAR* CXTPMarkupParser::GetValue()
  67. {
  68. m_lpszValue[m_nValueLength] = 0;
  69. return m_lpszValue;
  70. }
  71. const WCHAR* CXTPMarkupParser::GetAttributeName()
  72. {
  73. m_lpszAttributeName[m_nAttributeNameLength] = 0;
  74. return m_lpszAttributeName;
  75. }
  76. const WCHAR* CXTPMarkupParser::GetTagName()
  77. {
  78. m_lpszTagName[m_nTagNameLength] = 0;
  79. return m_lpszTagName;
  80. }
  81. CXTPMarkupParser::TokenType CXTPMarkupParser::ReportError(LPCWSTR lpszError)
  82. {
  83. WCSNCPY_S(m_lpszValue, lpszError, 1024);
  84. m_nValueLength = (int)wcslen(m_lpszValue);
  85. return tokenError;
  86. }
  87. BOOL CXTPMarkupParser::FindFirstTag()
  88. {
  89. WCHAR c = GetChar();
  90. while(c != 0)
  91. {
  92. if (c == '<')
  93. {
  94. PushBack(c);
  95. return TRUE;
  96. }
  97. else if (!IsWhitespace(c))
  98. {
  99. return FALSE;
  100. }
  101. c = GetChar();
  102. }
  103. return FALSE;
  104. }
  105. CXTPMarkupParser::TokenType CXTPMarkupParser::ScanBody()
  106. {
  107. WCHAR c = GetChar();
  108. m_nValueLength = 0;
  109. BOOL ws = FALSE;
  110. if (c == 0) return tokenEof;
  111. else if (c == '<') return ScanTag();
  112. else if (c == '&')
  113. c = ScanEntity();
  114. else
  115. ws = IsWhitespace(c);
  116. while(TRUE)
  117. {
  118. AppendValue(c);
  119. c = GetNextChar();
  120. if (c == 0)  { PushBack(c); break; }
  121. if (c == '<') { PushBack(c); break; }
  122. if (c == '&') { PushBack(c); break; }
  123. if (IsWhitespace(c) != ws)
  124. {
  125. PushBack(c);
  126. break;
  127. }
  128. }
  129. return ws? tokenSpace : tokenWord;
  130. }
  131. CXTPMarkupParser::TokenType CXTPMarkupParser::ScanHead()
  132. {
  133. WCHAR c = SkipWhitespace();
  134. if (c == '>') { m_scan = &CXTPMarkupParser::ScanBody; return ScanBody(); }
  135. if (c == '/')
  136. {
  137. WCHAR t = GetChar();
  138. if (t == '>')   { m_scan = &CXTPMarkupParser::ScanBody; return tokenTagEnd; }
  139. else { PushBack(t); return ReportError(L"Unexpected token. The expected token is '>'"); }
  140. }
  141. m_nAttributeNameLength = 0;
  142. m_nValueLength = 0;
  143. // attribute name...
  144. while(c != '=')
  145. {
  146. if ( c == 0) return tokenEof;
  147. if ( c == '>' ) return ReportError(L"'>' is an unexpected token. The expected token is '='");
  148. if ( IsWhitespace(c) )
  149. {
  150. c = SkipWhitespace();
  151. if (c != '=') return ReportError(L"Unexpected token. The expected token is '='");
  152. else break;
  153. }
  154. if ( c == '<') return ReportError(L"'<' is an unexpected token. The expected token is '='");
  155. AppendAttributeName(c);
  156. c = GetChar();
  157. }
  158. c = SkipWhitespace();
  159. // attribute m_lpszValue...
  160. if (c == '"')
  161. {
  162. while((c = GetChar()) != NULL)
  163. {
  164. if (c == '"') return tokenAttribute;
  165. AppendValue(c);
  166. }
  167. }
  168. else if (c == ''')
  169. {
  170. while((c = GetChar()) != NULL)
  171. {
  172. if (c == ''') return tokenAttribute;
  173. AppendValue(c);
  174. }
  175. }
  176. return ReportError(L"Unexpected token. The expected token is '"' or '''");
  177. }
  178. // caller already consumed '<'
  179. // scan header start or tag tail
  180. CXTPMarkupParser::TokenType CXTPMarkupParser::ScanTag()
  181. {
  182. m_nTagNameLength = 0;
  183. WCHAR c = GetChar();
  184. BOOL is_tail = c == '/';
  185. if (is_tail) c = GetChar();
  186. else if ( c == '?' )
  187. {
  188. m_scan = &CXTPMarkupParser::ScanPI;
  189. return tokenPIStart;
  190. }
  191. while(c)
  192. {
  193. if (IsWhitespace(c)) { c = SkipWhitespace(); break; }
  194. if (c == '/' || c == '>') break;
  195. AppendTagName(c);
  196. switch(m_nTagNameLength)
  197. {
  198. case 3:
  199. if (wcsncmp(m_lpszTagName, L"!--", 3) == 0)  { m_scan = &CXTPMarkupParser::ScanComment; return tokenCommentStart; }
  200. break;
  201. case 8:
  202. if ( wcsncmp(m_lpszTagName, L"![CDATA[", 8) == 0 ) { m_scan = &CXTPMarkupParser::ScanCData; return tokenCDataStart; }
  203. break;
  204. }
  205. c = GetChar();
  206. }
  207. if (c == 0) return ReportError(L"Unexpected end of file has occurred.");
  208. if (is_tail)
  209. {
  210. if (c == '>') return tokenTagEnd;
  211. return ReportError(L"Unexpected token. The expected token is '>'");
  212. }
  213. else
  214. PushBack(c);
  215. m_scan = &CXTPMarkupParser::ScanHead;
  216. return tokenTagStart;
  217. }
  218. // skip whitespaces.
  219. // returns first non-whitespace WCHAR
  220. WCHAR CXTPMarkupParser::SkipWhitespace()
  221. {
  222. for (WCHAR c = GetChar(); c != 0; c = GetChar())
  223. {
  224. if (!IsWhitespace(c)) return c;
  225. }
  226. return 0;
  227. }
  228. void CXTPMarkupParser::PushBack(WCHAR c)
  229. {
  230. m_cInputChar = c;
  231. }
  232. WCHAR CXTPMarkupParser::GetNextChar()
  233. {
  234. if (m_lpszPos >= m_lpszEnd)
  235. return NULL;
  236. WCHAR c = 0;
  237. if (m_bUnicode)
  238. {
  239. c = *((LPCWSTR)m_lpszPos);
  240. m_lpszPos += sizeof(WCHAR);
  241. }
  242. else
  243. {
  244. char t = *m_lpszPos;
  245. if (m_nEncoding == CP_UTF8)
  246. {
  247. if( 0 == ( t & 'x80' ) )
  248. {
  249. c = t;
  250. }
  251. else if('xF0' == (t & 'xF0')) // 1111 - error, more than 16-bit char
  252. {
  253. }
  254. else if( 'xE0' == (t & 'xF0')) // 1110xxxx 10xxxxxx 10xxxxxx
  255. {
  256. char t2 = *(++m_lpszPos);
  257. char t3 = *(++m_lpszPos);
  258. c = (WCHAR)((WCHAR(t & 'x0F') << 12 ) | ( WCHAR(t2 & 'x3F' ) << 6 ) | WCHAR(t3 & 'x3F' ));
  259. }
  260. else if( 'xC0' == (t & 'xE0')) // 110xxxxx 10xxxxxx
  261. {
  262. char t2 = *(++m_lpszPos);
  263. c = (WCHAR)((WCHAR( t & 'x1F' ) << 6 ) | ( t2 & 'x3F' ));
  264. }
  265. else
  266. {
  267. }
  268. }
  269. else if (_istlead(t))
  270. {
  271. MultiByteToWideChar(m_nEncoding, 0, m_lpszPos, 2, &c, 1);
  272. m_lpszPos++;
  273. }
  274. else if (t > 0 && t < 128)
  275. {
  276. c = t;
  277. }
  278. else
  279. {
  280. MultiByteToWideChar(m_nEncoding, 0, m_lpszPos, 1, &c, 1);
  281. }
  282. m_lpszPos++;
  283. }
  284. m_nPosition++;
  285. if (c == 'r' || c == 'n')
  286. {
  287. m_nLine++;
  288. m_nPosition = 0;
  289. }
  290. return c;
  291. }
  292. WCHAR CXTPMarkupParser::GetChar()
  293. {
  294. if (m_cInputChar) { WCHAR t(m_cInputChar); m_cInputChar = 0; return t; }
  295. return GetNextChar();
  296. }
  297. WCHAR CXTPMarkupParser::ResolveEntity(const WCHAR* buf, int buf_size)
  298. {
  299. if (buf[0] == '#')
  300. {
  301. int nAscii = 0;
  302. if (buf[1] == 'x' && buf_size > 2)
  303. {
  304. if (WSCANF_S(buf + 2, L"%x", &nAscii) != 1)
  305. return 0;
  306. return (WCHAR)nAscii;
  307. }
  308. else
  309. {
  310. if (WSCANF_S(buf + 1, L"%i", &nAscii) != 1)
  311. return 0;
  312. return (WCHAR)nAscii;
  313. }
  314. }
  315. return 0;
  316. }
  317. // caller consumed '&'
  318. WCHAR CXTPMarkupParser::ScanEntity()
  319. {
  320. WCHAR buf[32];
  321. int i = 0;
  322. WCHAR t;
  323. for (; i < 31 ; ++i )
  324. {
  325. t = GetChar();
  326. if (t == 0) return tokenEof;
  327. buf[i] = t;
  328. if (t == ';')
  329. break;
  330. }
  331. buf[i] = 0;
  332. if (i == 2)
  333. {
  334. if (wcsncmp(buf, L"gt", 2) == 0) return '>';
  335. if (wcsncmp(buf, L"lt", 2) == 0) return '<';
  336. }
  337. else if (i == 3 && (wcsncmp(buf, L"amp", 3) == 0))
  338. return '&';
  339. else if (i == 4)
  340. {
  341. if (wcsncmp(buf, L"apos", 4) == 0) return ''';
  342. if (wcsncmp(buf, L"quot", 4) == 0) return '"';
  343. }
  344. t = ResolveEntity(buf, i);
  345. if (t) return t;
  346. // no luck ...
  347. AppendValue('&');
  348. for (int n = 0; n < i; ++n)
  349. AppendValue(buf[n]);
  350. return ';';
  351. }
  352. BOOL CXTPMarkupParser::IsWhitespace(WCHAR c) const
  353. {
  354. return c <= ' '
  355. && (c == ' ' || c == 't' || c == 'n' || c == 'r' || c == 'f');
  356. }
  357. void CXTPMarkupParser::AppendValue(WCHAR c)
  358. {
  359. if (m_nValueLength < (XTP_MAX_TOKEN_SIZE - 1))
  360. m_lpszValue[m_nValueLength++] = c;
  361. }
  362. void CXTPMarkupParser::AppendAttributeName(WCHAR c)
  363. {
  364. if (m_nAttributeNameLength < (XTP_MAX_NAME_SIZE - 1))
  365. m_lpszAttributeName[m_nAttributeNameLength++] = c;
  366. }
  367. void CXTPMarkupParser::AppendTagName(WCHAR c)
  368. {
  369. if (m_nTagNameLength < (XTP_MAX_NAME_SIZE - 1))
  370. m_lpszTagName[m_nTagNameLength++] = c;
  371. }
  372. CXTPMarkupParser::TokenType CXTPMarkupParser::ScanComment()
  373. {
  374. if (m_bGotTail)
  375. {
  376. m_scan = &CXTPMarkupParser::ScanBody;
  377. m_bGotTail = FALSE;
  378. return tokenCommentEnd;
  379. }
  380. for (m_nValueLength = 0; m_nValueLength < (XTP_MAX_TOKEN_SIZE - 1); ++m_nValueLength)
  381. {
  382. WCHAR c = GetChar();
  383. if ( c == 0) return tokenEof;
  384. m_lpszValue[m_nValueLength] = c;
  385. if (m_nValueLength >= 2
  386. && m_lpszValue[m_nValueLength] == '>'
  387. && m_lpszValue[m_nValueLength - 1] == '-'
  388. && m_lpszValue[m_nValueLength - 2] == '-')
  389. {
  390. m_bGotTail = TRUE;
  391. m_nValueLength -= 2;
  392. break;
  393. }
  394. }
  395. return tokenData;
  396. }
  397. CXTPMarkupParser::TokenType CXTPMarkupParser::ScanCData()
  398. {
  399. if (m_bGotTail)
  400. {
  401. m_scan = &CXTPMarkupParser::ScanBody;
  402. m_bGotTail = FALSE;
  403. return tokenCDataEnd;
  404. }
  405. for (m_nValueLength = 0; m_nValueLength < (XTP_MAX_TOKEN_SIZE - 1); ++m_nValueLength)
  406. {
  407. WCHAR c = GetChar();
  408. if ( c == 0) return tokenEof;
  409. m_lpszValue[m_nValueLength] = c;
  410. if (m_nValueLength >= 2
  411. && m_lpszValue[m_nValueLength] == '>'
  412. && m_lpszValue[m_nValueLength - 1] == ']'
  413. && m_lpszValue[m_nValueLength - 2] == ']')
  414. {
  415. m_bGotTail = TRUE;
  416. m_nValueLength -= 2;
  417. break;
  418. }
  419. }
  420. return tokenData;
  421. }
  422. CXTPMarkupParser::TokenType CXTPMarkupParser::ScanPI()
  423. {
  424. if (m_bGotTail)
  425. {
  426. m_scan = &CXTPMarkupParser::ScanBody;
  427. m_bGotTail = FALSE;
  428. return tokenPIEnd;
  429. }
  430. for (m_nValueLength = 0; m_nValueLength < (XTP_MAX_TOKEN_SIZE - 1); ++m_nValueLength)
  431. {
  432. WCHAR c = GetChar();
  433. if ( c == 0)
  434. return tokenEof;
  435. if (IsWhitespace(c))
  436. {
  437. m_nValueLength--;
  438. continue;
  439. }
  440. m_lpszValue[m_nValueLength] = c;
  441. if (m_nValueLength >= 1
  442. && m_lpszValue[m_nValueLength] == '>'
  443. && m_lpszValue[m_nValueLength - 1] == '?')
  444. {
  445. m_bGotTail = TRUE;
  446. m_nValueLength -= 1;
  447. break;
  448. }
  449. }
  450. return tokenData;
  451. }