PageRenderTime 56ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/ATF2/control-software/epics-3.14.8/extensions/src/ChannelArchiver/ThirdParty/xerces-c-src2_4_0/src/xercesc/internal/ElemStack.cpp

http://atf2flightsim.googlecode.com/
C++ | 964 lines | 462 code | 144 blank | 358 comment | 86 complexity | 47bc4f33ef9304dfcd63083fe6885828 MD5 | raw file
Possible License(s): BSD-2-Clause, LGPL-2.0, IPL-1.0, BSD-3-Clause
  1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. * Copyright (c) 1999-2001 The Apache Software Foundation. All rights
  5. * reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. *
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in
  16. * the documentation and/or other materials provided with the
  17. * distribution.
  18. *
  19. * 3. The end-user documentation included with the redistribution,
  20. * if any, must include the following acknowledgment:
  21. * "This product includes software developed by the
  22. * Apache Software Foundation (http://www.apache.org/)."
  23. * Alternately, this acknowledgment may appear in the software itself,
  24. * if and wherever such third-party acknowledgments normally appear.
  25. *
  26. * 4. The names "Xerces" and "Apache Software Foundation" must
  27. * not be used to endorse or promote products derived from this
  28. * software without prior written permission. For written
  29. * permission, please contact apache\@apache.org.
  30. *
  31. * 5. Products derived from this software may not be called "Apache",
  32. * nor may "Apache" appear in their name, without prior written
  33. * permission of the Apache Software Foundation.
  34. *
  35. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46. * SUCH DAMAGE.
  47. * ====================================================================
  48. *
  49. * This software consists of voluntary contributions made by many
  50. * individuals on behalf of the Apache Software Foundation, and was
  51. * originally based on software copyright (c) 1999, International
  52. * Business Machines, Inc., http://www.ibm.com . For more information
  53. * on the Apache Software Foundation, please see
  54. * <http://www.apache.org/>.
  55. */
  56. /*
  57. * $Log: ElemStack.cpp,v $
  58. * Revision 1.1.1.1 2009/03/14 06:42:21 whitegr
  59. * epics channel archiver
  60. *
  61. * Revision 1.9 2003/10/23 14:11:07 knoaman
  62. * Fix memory leak.
  63. *
  64. * Revision 1.8 2003/10/22 20:22:30 knoaman
  65. * Prepare for annotation support.
  66. *
  67. * Revision 1.7 2003/05/18 14:02:04 knoaman
  68. * Memory manager implementation: pass per instance manager.
  69. *
  70. * Revision 1.6 2003/05/16 21:36:57 knoaman
  71. * Memory manager implementation: Modify constructors to pass in the memory manager.
  72. *
  73. * Revision 1.5 2003/05/15 18:26:29 knoaman
  74. * Partial implementation of the configurable memory manager.
  75. *
  76. * Revision 1.4 2003/01/02 16:38:00 knoaman
  77. * Some cleanup.
  78. *
  79. * Revision 1.3 2002/12/04 02:23:50 knoaman
  80. * Scanner re-organization.
  81. *
  82. * Revision 1.2 2002/11/04 14:58:18 tng
  83. * C++ Namespace Support.
  84. *
  85. * Revision 1.1.1.1 2002/02/01 22:21:57 peiyongz
  86. * sane_include
  87. *
  88. * Revision 1.17 2001/12/12 14:29:50 tng
  89. * Remove obsolete code in ElemStack which can help performance.
  90. *
  91. * Revision 1.16 2001/08/29 16:42:27 tng
  92. * No need to new the child QName in ElemStack addChild. Remove it for performance gain.
  93. *
  94. * Revision 1.15 2001/08/07 13:47:47 tng
  95. * Schema: Fix unmatched end tag for qualified/unqualifed start tag.
  96. *
  97. * Revision 1.14 2001/06/18 21:33:57 peiyongz
  98. * Memory leak fix: to addlevel(), by Erik Rydgren.
  99. *
  100. * Revision 1.13 2001/06/12 19:08:27 peiyongz
  101. * Memory leak: fixed by Erik Rydgren
  102. *
  103. * Revision 1.12 2001/05/28 20:55:19 tng
  104. * Schema: Store Grammar in ElemStack as well.
  105. *
  106. * Revision 1.11 2001/05/11 13:26:16 tng
  107. * Copyright update.
  108. *
  109. * Revision 1.10 2001/05/03 20:34:28 tng
  110. * Schema: SchemaValidator update
  111. *
  112. * Revision 1.9 2001/04/19 18:16:57 tng
  113. * Schema: SchemaValidator update, and use QName in Content Model
  114. *
  115. * Revision 1.8 2001/02/16 17:58:02 tng
  116. * use EmptyNamespaceId for attribute, GlobalNamespaceId for element.
  117. *
  118. * Revision 1.7 2000/07/05 05:20:17 roddey
  119. * Fixed a memory leak when namespaces are enabled.
  120. *
  121. * Revision 1.6 2000/05/15 22:31:15 andyh
  122. * Replace #include<memory.h> with <string.h> everywhere.
  123. *
  124. * Revision 1.5 2000/03/02 19:54:28 roddey
  125. * This checkin includes many changes done while waiting for the
  126. * 1.1.0 code to be finished. I can't list them all here, but a list is
  127. * available elsewhere.
  128. *
  129. * Revision 1.4 2000/02/08 19:38:58 roddey
  130. * xmlns:xxx="" should affect the mapping of the prefixes of sibling attributes,
  131. * which was not being done.
  132. *
  133. * Revision 1.3 2000/02/06 07:47:52 rahulj
  134. * Year 2K copyright swat.
  135. *
  136. * Revision 1.2 2000/01/19 00:55:45 roddey
  137. * Changes to get rid of dependence on old utils standard streams classes
  138. * and a small fix in the progressive parseFirst() call.
  139. *
  140. * Revision 1.1.1.1 1999/11/09 01:08:04 twl
  141. * Initial checkin
  142. *
  143. * Revision 1.4 1999/11/08 20:44:41 rahul
  144. * Swat for adding in Product name and CVS comment log variable.
  145. *
  146. */
  147. // ---------------------------------------------------------------------------
  148. // Includes
  149. // ---------------------------------------------------------------------------
  150. #include <string.h>
  151. #include <xercesc/util/EmptyStackException.hpp>
  152. #include <xercesc/util/NoSuchElementException.hpp>
  153. #include <xercesc/framework/XMLElementDecl.hpp>
  154. #include <xercesc/internal/ElemStack.hpp>
  155. #include <xercesc/validators/common/Grammar.hpp>
  156. XERCES_CPP_NAMESPACE_BEGIN
  157. // ---------------------------------------------------------------------------
  158. // ElemStack: Constructors and Destructor
  159. // ---------------------------------------------------------------------------
  160. ElemStack::ElemStack(MemoryManager* const manager) :
  161. fEmptyNamespaceId(0)
  162. , fGlobalPoolId(0)
  163. , fPrefixPool(109, manager)
  164. , fStack(0)
  165. , fStackCapacity(32)
  166. , fStackTop(0)
  167. , fUnknownNamespaceId(0)
  168. , fXMLNamespaceId(0)
  169. , fXMLPoolId(0)
  170. , fXMLNSNamespaceId(0)
  171. , fXMLNSPoolId(0)
  172. , fNamespaceMap(0)
  173. , fMemoryManager(manager)
  174. {
  175. // Do an initial allocation of the stack and zero it out
  176. fStack = (StackElem**) fMemoryManager->allocate
  177. (
  178. fStackCapacity * sizeof(StackElem*)
  179. );//new StackElem*[fStackCapacity];
  180. memset(fStack, 0, fStackCapacity * sizeof(StackElem*));
  181. fNamespaceMap = new (fMemoryManager) ValueVectorOf<PrefMapElem*>(16, fMemoryManager);
  182. }
  183. ElemStack::~ElemStack()
  184. {
  185. //
  186. // Start working from the bottom of the stack and clear it out as we
  187. // go up. Once we hit an uninitialized one, we can break out.
  188. //
  189. for (unsigned int stackInd = 0; stackInd < fStackCapacity; stackInd++)
  190. {
  191. // If this entry has been set, then lets clean it up
  192. if (!fStack[stackInd])
  193. break;
  194. fMemoryManager->deallocate(fStack[stackInd]->fChildren);//delete [] fStack[stackInd]->fChildren;
  195. fMemoryManager->deallocate(fStack[stackInd]->fMap);//delete [] fStack[stackInd]->fMap;
  196. delete fStack[stackInd];
  197. }
  198. // Delete the stack array itself now
  199. fMemoryManager->deallocate(fStack);//delete [] fStack;
  200. delete fNamespaceMap;
  201. }
  202. // ---------------------------------------------------------------------------
  203. // ElemStack: Stack access
  204. // ---------------------------------------------------------------------------
  205. unsigned int ElemStack::addLevel()
  206. {
  207. // See if we need to expand the stack
  208. if (fStackTop == fStackCapacity)
  209. expandStack();
  210. // If this element has not been initialized yet, then initialize it
  211. if (!fStack[fStackTop])
  212. {
  213. fStack[fStackTop] = new (fMemoryManager) StackElem;
  214. fStack[fStackTop]->fChildCapacity = 0;
  215. fStack[fStackTop]->fChildren = 0;
  216. fStack[fStackTop]->fMapCapacity = 0;
  217. fStack[fStackTop]->fMap = 0;
  218. }
  219. // Set up the new top row
  220. fStack[fStackTop]->fThisElement = 0;
  221. fStack[fStackTop]->fReaderNum = 0xFFFFFFFF;
  222. fStack[fStackTop]->fChildCount = 0;
  223. fStack[fStackTop]->fMapCount = 0;
  224. fStack[fStackTop]->fValidationFlag = false;
  225. fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId;
  226. fStack[fStackTop]->fCurrentScope = Grammar::TOP_LEVEL_SCOPE;
  227. fStack[fStackTop]->fCurrentGrammar = 0;
  228. // Bump the top of stack
  229. fStackTop++;
  230. return fStackTop-1;
  231. }
  232. unsigned int
  233. ElemStack::addLevel(XMLElementDecl* const toSet, const unsigned int readerNum)
  234. {
  235. // See if we need to expand the stack
  236. if (fStackTop == fStackCapacity)
  237. expandStack();
  238. // If this element has not been initialized yet, then initialize it
  239. if (!fStack[fStackTop])
  240. {
  241. fStack[fStackTop] = new (fMemoryManager) StackElem;
  242. fStack[fStackTop]->fChildCapacity = 0;
  243. fStack[fStackTop]->fChildren = 0;
  244. fStack[fStackTop]->fMapCapacity = 0;
  245. fStack[fStackTop]->fMap = 0;
  246. }
  247. // Set up the new top row
  248. fStack[fStackTop]->fThisElement = toSet;
  249. fStack[fStackTop]->fReaderNum = readerNum;
  250. fStack[fStackTop]->fChildCount = 0;
  251. fStack[fStackTop]->fMapCount = 0;
  252. fStack[fStackTop]->fValidationFlag = false;
  253. fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId;
  254. fStack[fStackTop]->fCurrentScope = Grammar::TOP_LEVEL_SCOPE;
  255. fStack[fStackTop]->fCurrentGrammar = 0;
  256. // Bump the top of stack
  257. fStackTop++;
  258. return fStackTop-1;
  259. }
  260. const ElemStack::StackElem* ElemStack::popTop()
  261. {
  262. // Watch for an underflow error
  263. if (!fStackTop)
  264. ThrowXML(EmptyStackException, XMLExcepts::ElemStack_StackUnderflow);
  265. fStackTop--;
  266. return fStack[fStackTop];
  267. }
  268. void
  269. ElemStack::setElement(XMLElementDecl* const toSet, const unsigned int readerNum)
  270. {
  271. if (!fStackTop)
  272. ThrowXML(EmptyStackException, XMLExcepts::ElemStack_EmptyStack);
  273. fStack[fStackTop - 1]->fThisElement = toSet;
  274. fStack[fStackTop - 1]->fReaderNum = readerNum;
  275. }
  276. // ---------------------------------------------------------------------------
  277. // ElemStack: Stack top access
  278. // ---------------------------------------------------------------------------
  279. unsigned int ElemStack::addChild(QName* const child, const bool toParent)
  280. {
  281. if (!fStackTop)
  282. ThrowXML(EmptyStackException, XMLExcepts::ElemStack_EmptyStack);
  283. //
  284. // If they want to add to the parent, then we have to have at least two
  285. // elements on the stack.
  286. //
  287. if (toParent && (fStackTop < 2))
  288. ThrowXML(NoSuchElementException, XMLExcepts::ElemStack_NoParentPushed);
  289. // Get a convenience pointer to the stack top row
  290. StackElem* curRow = toParent
  291. ? fStack[fStackTop - 2] : fStack[fStackTop - 1];
  292. // See if we need to expand this row's child array
  293. if (curRow->fChildCount == curRow->fChildCapacity)
  294. {
  295. // Increase the capacity by a quarter and allocate a new row
  296. const unsigned int newCapacity = curRow->fChildCapacity ?
  297. (unsigned int)(curRow->fChildCapacity * 1.25) :
  298. 32;
  299. QName** newRow = (QName**) fMemoryManager->allocate
  300. (
  301. newCapacity * sizeof(QName*)
  302. );//new QName*[newCapacity];
  303. //
  304. // Copy over the old contents. We don't have to initialize the new
  305. // part because The current child count is used to know how much of
  306. // it is valid.
  307. //
  308. // Only both doing this if there is any current content, since
  309. // this code also does the initial faulting in of the array when
  310. // both the current capacity and child count are zero.
  311. //
  312. if (curRow->fChildCount)
  313. {
  314. unsigned int index = 0;
  315. for (; index < curRow->fChildCount; index++)
  316. newRow[index] = curRow->fChildren[index];
  317. }
  318. // Clean up the old children and store the new info
  319. fMemoryManager->deallocate(curRow->fChildren);//delete [] curRow->fChildren;
  320. curRow->fChildren = newRow;
  321. curRow->fChildCapacity = newCapacity;
  322. }
  323. // Add this id to the end of the row's child id array and bump the count
  324. curRow->fChildren[curRow->fChildCount++] = child;
  325. // Return the level of the index we just filled (before the bump)
  326. return curRow->fChildCount - 1;
  327. }
  328. const ElemStack::StackElem* ElemStack::topElement() const
  329. {
  330. if (!fStackTop)
  331. ThrowXML(EmptyStackException, XMLExcepts::ElemStack_EmptyStack);
  332. return fStack[fStackTop - 1];
  333. }
  334. // ---------------------------------------------------------------------------
  335. // ElemStack: Prefix map methods
  336. // ---------------------------------------------------------------------------
  337. void ElemStack::addPrefix( const XMLCh* const prefixToAdd
  338. , const unsigned int uriId)
  339. {
  340. if (!fStackTop)
  341. ThrowXML(EmptyStackException, XMLExcepts::ElemStack_EmptyStack);
  342. // Get a convenience pointer to the stack top row
  343. StackElem* curRow = fStack[fStackTop - 1];
  344. // Map the prefix to its unique id
  345. const unsigned int prefId = fPrefixPool.addOrFind(prefixToAdd);
  346. //
  347. // Add a new element to the prefix map for this element. If its full,
  348. // then expand it out.
  349. //
  350. if (curRow->fMapCount == curRow->fMapCapacity)
  351. expandMap(curRow);
  352. //
  353. // And now add a new element for this prefix. Watch for the special case
  354. // of xmlns=="", and force it to ""=[globalid]
  355. //
  356. curRow->fMap[curRow->fMapCount].fPrefId = prefId;
  357. if ((prefId == fGlobalPoolId) && (uriId == fEmptyNamespaceId))
  358. curRow->fMap[curRow->fMapCount].fURIId = fEmptyNamespaceId;
  359. else
  360. curRow->fMap[curRow->fMapCount].fURIId = uriId;
  361. // Bump the map count now
  362. curRow->fMapCount++;
  363. }
  364. unsigned int ElemStack::mapPrefixToURI( const XMLCh* const prefixToMap
  365. , const MapModes mode
  366. , bool& unknown) const
  367. {
  368. // Assume we find it
  369. unknown = false;
  370. //
  371. // Map the prefix to its unique id, from the prefix string pool. If its
  372. // not a valid prefix, then its a failure.
  373. //
  374. unsigned int prefixId = fPrefixPool.getId(prefixToMap);
  375. if (!prefixId)
  376. {
  377. unknown = true;
  378. return fUnknownNamespaceId;
  379. }
  380. //
  381. // If the prefix is empty, and we are in attribute mode, then we assign
  382. // it to the empty namespace because the default namespace does not
  383. // apply to attributes.
  384. //
  385. if (!*prefixToMap && (mode == Mode_Attribute))
  386. return fEmptyNamespaceId;
  387. //
  388. // Check for the special prefixes 'xml' and 'xmlns' since they cannot
  389. // be overridden.
  390. //
  391. if (prefixId == fXMLPoolId)
  392. return fXMLNamespaceId;
  393. else if (prefixId == fXMLNSPoolId)
  394. return fXMLNSNamespaceId;
  395. //
  396. // Start at the stack top and work backwards until we come to some
  397. // element that mapped this prefix.
  398. //
  399. int startAt = (int)(fStackTop - 1);
  400. for (int index = startAt; index >= 0; index--)
  401. {
  402. // Get a convenience pointer to the current element
  403. StackElem* curRow = fStack[index];
  404. // If no prefixes mapped at this level, then go the next one
  405. if (!curRow->fMapCount)
  406. continue;
  407. // Search the map at this level for the passed prefix
  408. for (unsigned int mapIndex = 0; mapIndex < curRow->fMapCount; mapIndex++)
  409. {
  410. if (curRow->fMap[mapIndex].fPrefId == prefixId)
  411. return curRow->fMap[mapIndex].fURIId;
  412. }
  413. }
  414. //
  415. // If the prefix is an empty string, then we will return the special
  416. // global namespace id. This can be overridden, but no one has or we
  417. // would have not gotten here.
  418. //
  419. if (!*prefixToMap)
  420. return fEmptyNamespaceId;
  421. // Oh well, don't have a clue so return the unknown id
  422. unknown = true;
  423. return fUnknownNamespaceId;
  424. }
  425. ValueVectorOf<PrefMapElem*>* ElemStack::getNamespaceMap() const
  426. {
  427. fNamespaceMap->removeAllElements();
  428. // Start at the stack top and work backwards until we come to some
  429. // element that mapped this prefix.
  430. int startAt = (int)(fStackTop - 1);
  431. for (int index = startAt; index >= 0; index--)
  432. {
  433. // Get a convenience pointer to the current element
  434. StackElem* curRow = fStack[index];
  435. // If no prefixes mapped at this level, then go the next one
  436. if (!curRow->fMapCount)
  437. continue;
  438. // Search the map at this level for the passed prefix
  439. for (unsigned int mapIndex = 0; mapIndex < curRow->fMapCount; mapIndex++)
  440. {
  441. fNamespaceMap->addElement(&(curRow->fMap[mapIndex]));
  442. }
  443. }
  444. return fNamespaceMap;
  445. }
  446. // ---------------------------------------------------------------------------
  447. // ElemStack: Miscellaneous methods
  448. // ---------------------------------------------------------------------------
  449. void ElemStack::reset( const unsigned int emptyId
  450. , const unsigned int unknownId
  451. , const unsigned int xmlId
  452. , const unsigned int xmlNSId)
  453. {
  454. // Reset the stack top to clear the stack
  455. fStackTop = 0;
  456. // if first time, put in the standard prefixes
  457. if (fXMLPoolId == 0) {
  458. fGlobalPoolId = fPrefixPool.addOrFind(XMLUni::fgZeroLenString);
  459. fXMLPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLString);
  460. fXMLNSPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLNSString);
  461. }
  462. // And store the new special URI ids
  463. fEmptyNamespaceId = emptyId;
  464. fUnknownNamespaceId = unknownId;
  465. fXMLNamespaceId = xmlId;
  466. fXMLNSNamespaceId = xmlNSId;
  467. }
  468. // ---------------------------------------------------------------------------
  469. // ElemStack: Private helpers
  470. // ---------------------------------------------------------------------------
  471. void ElemStack::expandMap(StackElem* const toExpand)
  472. {
  473. // For convenience get the old map size
  474. const unsigned int oldCap = toExpand->fMapCapacity;
  475. //
  476. // Expand the capacity by 25%, or initialize it to 16 if its currently
  477. // empty. Then allocate a new temp buffer.
  478. //
  479. const unsigned int newCapacity = oldCap ?
  480. (unsigned int)(oldCap * 1.25) : 16;
  481. PrefMapElem* newMap = (PrefMapElem*) fMemoryManager->allocate
  482. (
  483. newCapacity * sizeof(PrefMapElem)
  484. );//new PrefMapElem[newCapacity];
  485. //
  486. // Copy over the old stuff. We DON'T have to zero out the new stuff
  487. // since this is a by value map and the current map index controls what
  488. // is relevant.
  489. //
  490. memcpy(newMap, toExpand->fMap, oldCap * sizeof(PrefMapElem));
  491. // Delete the old map and store the new stuff
  492. fMemoryManager->deallocate(toExpand->fMap);//delete [] toExpand->fMap;
  493. toExpand->fMap = newMap;
  494. toExpand->fMapCapacity = newCapacity;
  495. }
  496. void ElemStack::expandStack()
  497. {
  498. // Expand the capacity by 25% and allocate a new buffer
  499. const unsigned int newCapacity = (unsigned int)(fStackCapacity * 1.25);
  500. StackElem** newStack = (StackElem**) fMemoryManager->allocate
  501. (
  502. newCapacity * sizeof(StackElem*)
  503. );//new StackElem*[newCapacity];
  504. // Copy over the old stuff
  505. memcpy(newStack, fStack, fStackCapacity * sizeof(StackElem*));
  506. //
  507. // And zero out the new stuff. Though we use a stack top, we reuse old
  508. // stack contents so we need to know if elements have been initially
  509. // allocated or not as we push new stuff onto the stack.
  510. //
  511. memset
  512. (
  513. &newStack[fStackCapacity]
  514. , 0
  515. , (newCapacity - fStackCapacity) * sizeof(StackElem*)
  516. );
  517. // Delete the old array and update our members
  518. fMemoryManager->deallocate(fStack);//delete [] fStack;
  519. fStack = newStack;
  520. fStackCapacity = newCapacity;
  521. }
  522. // ---------------------------------------------------------------------------
  523. // WFElemStack: Constructors and Destructor
  524. // ---------------------------------------------------------------------------
  525. WFElemStack::WFElemStack(MemoryManager* const manager) :
  526. fEmptyNamespaceId(0)
  527. , fGlobalPoolId(0)
  528. , fStackCapacity(32)
  529. , fStackTop(0)
  530. , fUnknownNamespaceId(0)
  531. , fXMLNamespaceId(0)
  532. , fXMLPoolId(0)
  533. , fXMLNSNamespaceId(0)
  534. , fXMLNSPoolId(0)
  535. , fMapCapacity(0)
  536. , fMap(0)
  537. , fStack(0)
  538. , fPrefixPool(109, manager)
  539. , fMemoryManager(manager)
  540. {
  541. // Do an initial allocation of the stack and zero it out
  542. fStack = (StackElem**) fMemoryManager->allocate
  543. (
  544. fStackCapacity * sizeof(StackElem*)
  545. );//new StackElem*[fStackCapacity];
  546. memset(fStack, 0, fStackCapacity * sizeof(StackElem*));
  547. }
  548. WFElemStack::~WFElemStack()
  549. {
  550. //
  551. // Start working from the bottom of the stack and clear it out as we
  552. // go up. Once we hit an uninitialized one, we can break out.
  553. //
  554. for (unsigned int stackInd = 0; stackInd < fStackCapacity; stackInd++)
  555. {
  556. // If this entry has been set, then lets clean it up
  557. if (!fStack[stackInd])
  558. break;
  559. fMemoryManager->deallocate(fStack[stackInd]->fThisElement);//delete [] fStack[stackInd]->fThisElement;
  560. delete fStack[stackInd];
  561. }
  562. if (fMap)
  563. fMemoryManager->deallocate(fMap);//delete [] fMap;
  564. // Delete the stack array itself now
  565. fMemoryManager->deallocate(fStack);//delete [] fStack;
  566. }
  567. // ---------------------------------------------------------------------------
  568. // WFElemStack: Stack access
  569. // ---------------------------------------------------------------------------
  570. unsigned int WFElemStack::addLevel()
  571. {
  572. // See if we need to expand the stack
  573. if (fStackTop == fStackCapacity)
  574. expandStack();
  575. // If this element has not been initialized yet, then initialize it
  576. if (!fStack[fStackTop])
  577. {
  578. fStack[fStackTop] = new (fMemoryManager) StackElem;
  579. fStack[fStackTop]->fThisElement = 0;
  580. fStack[fStackTop]->fElemMaxLength = 0;
  581. }
  582. // Set up the new top row
  583. fStack[fStackTop]->fReaderNum = 0xFFFFFFFF;
  584. fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId;
  585. fStack[fStackTop]->fTopPrefix = -1;
  586. if (fStackTop != 0)
  587. fStack[fStackTop]->fTopPrefix = fStack[fStackTop - 1]->fTopPrefix;
  588. // Bump the top of stack
  589. fStackTop++;
  590. return fStackTop-1;
  591. }
  592. unsigned int
  593. WFElemStack::addLevel(const XMLCh* const toSet,
  594. const unsigned int toSetLen,
  595. const unsigned int readerNum)
  596. {
  597. // See if we need to expand the stack
  598. if (fStackTop == fStackCapacity)
  599. expandStack();
  600. // If this element has not been initialized yet, then initialize it
  601. if (!fStack[fStackTop])
  602. {
  603. fStack[fStackTop] = new (fMemoryManager) StackElem;
  604. fStack[fStackTop]->fThisElement = 0;
  605. fStack[fStackTop]->fElemMaxLength = 0;
  606. }
  607. // Set up the new top row
  608. fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId;
  609. fStack[fStackTop]->fTopPrefix = -1;
  610. // And store the new stuff
  611. if (toSetLen > fStack[fStackTop]->fElemMaxLength) {
  612. fMemoryManager->deallocate(fStack[fStackTop]->fThisElement);//delete [] fStack[fStackTop]->fThisElement;
  613. fStack[fStackTop]->fElemMaxLength = toSetLen;
  614. fStack[fStackTop]->fThisElement = (XMLCh*) fMemoryManager->allocate
  615. (
  616. (toSetLen + 1) * sizeof(XMLCh)
  617. );//new XMLCh[toSetLen + 1];
  618. }
  619. XMLString::moveChars(fStack[fStackTop]->fThisElement, toSet, toSetLen + 1);
  620. fStack[fStackTop]->fReaderNum = readerNum;
  621. if (fStackTop != 0)
  622. fStack[fStackTop]->fTopPrefix = fStack[fStackTop - 1]->fTopPrefix;
  623. // Bump the top of stack
  624. fStackTop++;
  625. return fStackTop-1;
  626. }
  627. const WFElemStack::StackElem* WFElemStack::popTop()
  628. {
  629. // Watch for an underflow error
  630. if (!fStackTop)
  631. ThrowXML(EmptyStackException, XMLExcepts::ElemStack_StackUnderflow);
  632. fStackTop--;
  633. return fStack[fStackTop];
  634. }
  635. void
  636. WFElemStack::setElement(const XMLCh* const toSet,
  637. const unsigned int toSetLen,
  638. const unsigned int readerNum)
  639. {
  640. if (!fStackTop)
  641. ThrowXML(EmptyStackException, XMLExcepts::ElemStack_EmptyStack);
  642. if (toSetLen > fStack[fStackTop - 1]->fElemMaxLength) {
  643. fMemoryManager->deallocate(fStack[fStackTop - 1]->fThisElement);//delete [] fStack[fStackTop - 1]->fThisElement;
  644. fStack[fStackTop - 1]->fElemMaxLength = toSetLen;
  645. fStack[fStackTop - 1]->fThisElement = (XMLCh*) fMemoryManager->allocate
  646. (
  647. (toSetLen + 1) * sizeof(XMLCh)
  648. );//new XMLCh[toSetLen + 1];
  649. }
  650. XMLString::moveChars(fStack[fStackTop - 1]->fThisElement, toSet, toSetLen + 1);
  651. fStack[fStackTop - 1]->fReaderNum = readerNum;
  652. }
  653. // ---------------------------------------------------------------------------
  654. // WFElemStack: Stack top access
  655. // ---------------------------------------------------------------------------
  656. const WFElemStack::StackElem* WFElemStack::topElement() const
  657. {
  658. if (!fStackTop)
  659. ThrowXML(EmptyStackException, XMLExcepts::ElemStack_EmptyStack);
  660. return fStack[fStackTop - 1];
  661. }
  662. // ---------------------------------------------------------------------------
  663. // WFElemStack: Prefix map methods
  664. // ---------------------------------------------------------------------------
  665. void WFElemStack::addPrefix( const XMLCh* const prefixToAdd
  666. , const unsigned int uriId)
  667. {
  668. if (!fStackTop)
  669. ThrowXML(EmptyStackException, XMLExcepts::ElemStack_EmptyStack);
  670. // Get a convenience pointer to the stack top row
  671. StackElem* curRow = fStack[fStackTop - 1];
  672. // Map the prefix to its unique id
  673. const unsigned int prefId = fPrefixPool.addOrFind(prefixToAdd);
  674. //
  675. // Add a new element to the prefix map for this element. If its full,
  676. // then expand it out.
  677. //
  678. if ((unsigned int)curRow->fTopPrefix + 1 == fMapCapacity)
  679. expandMap();
  680. //
  681. // And now add a new element for this prefix. Watch for the special case
  682. // of xmlns=="", and force it to ""=[globalid]
  683. //
  684. fMap[curRow->fTopPrefix + 1].fPrefId = prefId;
  685. if ((prefId == fGlobalPoolId) && (uriId == fEmptyNamespaceId))
  686. fMap[curRow->fTopPrefix + 1].fURIId = fEmptyNamespaceId;
  687. else
  688. fMap[curRow->fTopPrefix + 1].fURIId = uriId;
  689. // Bump the map count now
  690. curRow->fTopPrefix++;
  691. }
  692. unsigned int WFElemStack::mapPrefixToURI( const XMLCh* const prefixToMap
  693. , const MapModes mode
  694. , bool& unknown) const
  695. {
  696. // Assume we find it
  697. unknown = false;
  698. //
  699. // Map the prefix to its unique id, from the prefix string pool. If its
  700. // not a valid prefix, then its a failure.
  701. //
  702. unsigned int prefixId = fPrefixPool.getId(prefixToMap);
  703. if (!prefixId)
  704. {
  705. unknown = true;
  706. return fUnknownNamespaceId;
  707. }
  708. //
  709. // If the prefix is empty, and we are in attribute mode, then we assign
  710. // it to the empty namespace because the default namespace does not
  711. // apply to attributes.
  712. //
  713. if (!*prefixToMap && (mode == Mode_Attribute))
  714. return fEmptyNamespaceId;
  715. //
  716. // Check for the special prefixes 'xml' and 'xmlns' since they cannot
  717. // be overridden.
  718. //
  719. if (prefixId == fXMLPoolId)
  720. return fXMLNamespaceId;
  721. else if (prefixId == fXMLNSPoolId)
  722. return fXMLNSNamespaceId;
  723. //
  724. // Start at the stack top and work backwards until we come to some
  725. // element that mapped this prefix.
  726. //
  727. // Get a convenience pointer to the stack top row
  728. StackElem* curRow = fStack[fStackTop - 1];
  729. for (int mapIndex = curRow->fTopPrefix; mapIndex >=0; mapIndex--)
  730. {
  731. if (fMap[mapIndex].fPrefId == prefixId)
  732. return fMap[mapIndex].fURIId;
  733. }
  734. //
  735. // If the prefix is an empty string, then we will return the special
  736. // global namespace id. This can be overridden, but no one has or we
  737. // would have not gotten here.
  738. //
  739. if (!*prefixToMap)
  740. return fEmptyNamespaceId;
  741. // Oh well, don't have a clue so return the unknown id
  742. unknown = true;
  743. return fUnknownNamespaceId;
  744. }
  745. // ---------------------------------------------------------------------------
  746. // WFElemStack: Miscellaneous methods
  747. // ---------------------------------------------------------------------------
  748. void WFElemStack::reset( const unsigned int emptyId
  749. , const unsigned int unknownId
  750. , const unsigned int xmlId
  751. , const unsigned int xmlNSId)
  752. {
  753. // Reset the stack top to clear the stack
  754. fStackTop = 0;
  755. // if first time, put in the standard prefixes
  756. if (fXMLPoolId == 0) {
  757. fGlobalPoolId = fPrefixPool.addOrFind(XMLUni::fgZeroLenString);
  758. fXMLPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLString);
  759. fXMLNSPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLNSString);
  760. }
  761. // And store the new special URI ids
  762. fEmptyNamespaceId = emptyId;
  763. fUnknownNamespaceId = unknownId;
  764. fXMLNamespaceId = xmlId;
  765. fXMLNSNamespaceId = xmlNSId;
  766. }
  767. // ---------------------------------------------------------------------------
  768. // WFElemStack: Private helpers
  769. // ---------------------------------------------------------------------------
  770. void WFElemStack::expandMap()
  771. {
  772. //
  773. // Expand the capacity by 25%, or initialize it to 16 if its currently
  774. // empty. Then allocate a new temp buffer.
  775. //
  776. const unsigned int newCapacity = fMapCapacity ?
  777. (unsigned int)(fMapCapacity * 1.25) : 16;
  778. PrefMapElem* newMap = (PrefMapElem*) fMemoryManager->allocate
  779. (
  780. newCapacity * sizeof(PrefMapElem)
  781. );//new PrefMapElem[newCapacity];
  782. //
  783. // Copy over the old stuff. We DON'T have to zero out the new stuff
  784. // since this is a by value map and the current map index controls what
  785. // is relevant.
  786. //
  787. if (fMapCapacity) {
  788. memcpy(newMap, fMap, fMapCapacity * sizeof(PrefMapElem));
  789. fMemoryManager->deallocate(fMap);//delete [] fMap;
  790. }
  791. fMap = newMap;
  792. fMapCapacity = newCapacity;
  793. }
  794. void WFElemStack::expandStack()
  795. {
  796. // Expand the capacity by 25% and allocate a new buffer
  797. const unsigned int newCapacity = (unsigned int)(fStackCapacity * 1.25);
  798. StackElem** newStack = (StackElem**) fMemoryManager->allocate
  799. (
  800. newCapacity * sizeof(StackElem*)
  801. );//new StackElem*[newCapacity];
  802. // Copy over the old stuff
  803. memcpy(newStack, fStack, fStackCapacity * sizeof(StackElem*));
  804. //
  805. // And zero out the new stuff. Though we use a stack top, we reuse old
  806. // stack contents so we need to know if elements have been initially
  807. // allocated or not as we push new stuff onto the stack.
  808. //
  809. memset
  810. (
  811. &newStack[fStackCapacity]
  812. , 0
  813. , (newCapacity - fStackCapacity) * sizeof(StackElem*)
  814. );
  815. // Delete the old array and update our members
  816. fMemoryManager->deallocate(fStack);//delete [] fStack;
  817. fStack = newStack;
  818. fStackCapacity = newCapacity;
  819. }
  820. XERCES_CPP_NAMESPACE_END