Newer
Older
* Copyright 1999-2000,2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id$
*/
// ---------------------------------------------------------------------------
// Includes
// ---------------------------------------------------------------------------
#include <xercesc/util/BinMemInputStream.hpp>
#include <xercesc/util/Janitor.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/RuntimeException.hpp>
#include <xercesc/util/UnexpectedEOFException.hpp>
#include <xercesc/util/XMLURL.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
#include <xercesc/util/XMLUni.hpp>
PeiYong Zhang
committed
#include <xercesc/util/XMLUri.hpp>
#include <xercesc/sax/InputSource.hpp>
#include <xercesc/framework/LocalFileInputSource.hpp>
#include <xercesc/framework/URLInputSource.hpp>
#include <xercesc/framework/XMLBuffer.hpp>
#include <xercesc/framework/XMLDocumentHandler.hpp>
#include <xercesc/framework/XMLEntityDecl.hpp>
#include <xercesc/framework/XMLEntityHandler.hpp>
#include <xercesc/internal/EndOfEntityException.hpp>
#include <xercesc/internal/ReaderMgr.hpp>
Neil Graham
committed
#include <xercesc/util/OutOfMemoryException.hpp>
#include <xercesc/util/XMLResourceIdentifier.hpp>
// ---------------------------------------------------------------------------
// ReaderMgr: Constructors and Destructor
// ---------------------------------------------------------------------------
ReaderMgr::ReaderMgr(MemoryManager* const manager) :
fCurEntity(0)
, fCurReader(0)
, fEntityHandler(0)
, fEntityStack(0)
, fNextReaderNum(1)
, fReaderStack(0)
, fThrowEOE(false)
, fStandardUriConformant(false)
, fMemoryManager(manager)
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
{
}
ReaderMgr::~ReaderMgr()
{
//
// Clean up the reader and entity stacks. Note that we don't own the
// entities, so we don't delete the current entity (and the entity stack
// does not own its elements either, so deleting it will not delete the
// entities it still references!)
//
delete fCurReader;
delete fReaderStack;
delete fEntityStack;
}
// ---------------------------------------------------------------------------
// ReaderMgr: Getter methods
// ---------------------------------------------------------------------------
bool ReaderMgr::isEmpty() const
{
return fReaderStack->empty();
}
// ---------------------------------------------------------------------------
// ReaderMgr: Scanning APIs
// ---------------------------------------------------------------------------
XMLCh ReaderMgr::getNextChar()
{
XMLCh chRet;
if (fCurReader->getNextChar(chRet))
return chRet;
//
// Didn't get anything back so this reader is hosed. So lets move to
// the next reader on the stack. If this fails, it will be because
// its the end of the original file, and we just return zero.
//
// If its the end of an entity and fThrowEOE is set, it will throw out
// of here. Otherwise, it will take us down to the next reader and
// we'll have more chars.
//
if (!popReader())
return XMLCh(0);
// Else try again and return the new character
fCurReader->getNextChar(chRet);
return chRet;
}
void ReaderMgr::getSpaces(XMLBuffer& toFill)
{
// Reset the buffer before we start
toFill.reset();
while (true)
{
//
// Get all the spaces from the current reader. If it returns true,
// it hit a non-space and we are done. Else we have to pop a reader
// and keep going.
//
if (fCurReader->getSpaces(toFill))
break;
// We wore that one out, so lets pop a reader and try again
if (!popReader())
break;
}
}
void ReaderMgr::getUpToCharOrWS(XMLBuffer& toFill, const XMLCh toCheck)
{
// Reset the target buffer before we start
toFill.reset();
//
// Ok, enter a loop where we ask the current reader to get chars until
// it meets the criteria. It returns false if it came back due to eating
// up all of its data. Else it returned because something matched, and
// we are done.
//
while (true)
{
if (fCurReader->getUpToCharOrWS(toFill, toCheck))
break;
// We ate that one up, lets try to pop another. If not, break out
if (!popReader())
break;
}
}
XMLCh ReaderMgr::peekNextChar()
{
XMLCh chRet;
if (fCurReader->peekNextChar(chRet))
return chRet;
//
// Didn't get anything back so this reader is hosed. So lets move to
// the next reader on the stack. If this fails, it will be because
// its the end of the original file, and we just return zero.
//
if (!popReader())
return XMLCh(0);
// Else peek again and return the character
fCurReader->peekNextChar(chRet);
return chRet;
}
bool ReaderMgr::skippedChar(const XMLCh toCheck)
{
while (true)
{
// If we get it, then just return true now
if (fCurReader->skippedChar(toCheck))
return true;
//
// Check to see if we hit end of input on this reader. If so, then
// lets pop and try again. Else, we failed. If we cannot pop another
// then we failed.
//
if (!fCurReader->getNoMoreFlag())
break;
if (!popReader())
break;
}
return false;
}
bool ReaderMgr::skippedSpace()
{
while (true)
{
// If we get it, then just return true now
if (fCurReader->skippedSpace())
return true;
//
// Check to see if we hit end of input on this reader. If so, then
// lets pop and try again. Else, we failed. If we cannot pop another
// then we failed.
//
if (!fCurReader->getNoMoreFlag())
break;
if (!popReader())
break;
}
return false;
}
bool ReaderMgr::skipIfQuote(XMLCh& chGotten)
{
while (true)
{
// If we get it, then just return true now
if (fCurReader->skipIfQuote(chGotten))
return true;
//
// Check to see if we hit end of input on this reader. If so, then
// lets pop and try again. Else, we failed. If we cannot pop another
// then we failed.
//
if (!fCurReader->getNoMoreFlag())
break;
if (!popReader())
break;
}
return false;
}
bool ReaderMgr::skipPastSpaces(bool inDecl)
{
bool skippedSomething = false;
bool tmpFlag;
while (true)
{
//
// Skip all the spaces in the current reader. If it returned because
// it hit a non-space, break out. Else we have to pop another entity
// and keep going.
//
if (fCurReader->skipSpaces(tmpFlag, inDecl))
break;
if (tmpFlag)
skippedSomething = true;
// Try to pop another enitity. If we can't then we are done
if (!popReader())
break;
}
return (tmpFlag || skippedSomething);
}
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
void ReaderMgr::skipQuotedString(const XMLCh quoteCh)
{
XMLCh nextCh;
while (true)
{
nextCh = getNextChar();
// If we get an end of file char, then return
if (!nextCh)
break;
// If we get the quote char, then break out
if (nextCh == quoteCh)
break;
}
}
XMLCh ReaderMgr::skipUntilIn(const XMLCh* const listToSkip)
{
XMLCh nextCh;
while (true)
{
nextCh = peekNextChar();
if (!nextCh)
break;
if (XMLString::indexOf(listToSkip, nextCh) != -1)
break;
// Its one of ours so eat it
getNextChar();
}
return nextCh;
}
XMLCh ReaderMgr::skipUntilInOrWS(const XMLCh* const listToSkip)
{
XMLCh nextCh;
while (true)
{
nextCh = peekNextChar();
if (!nextCh)
break;
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
break;
if (XMLString::indexOf(listToSkip, nextCh) != -1)
break;
// Its one of ours, so eat it
getNextChar();
}
return nextCh;
}
// ---------------------------------------------------------------------------
// ReaderMgr: Control methods
// ---------------------------------------------------------------------------
//
// If the reader stack is empty, then there is only the original main XML
// entity left. If its empty, then we have no more input.
//
bool ReaderMgr::atEOF() const
{
return fReaderStack->empty() && fCurReader->getNoMoreFlag();
}
//
// This method is called in the case of errors to clean up the stack when
// entities have been incorrectly left on the stack due to syntax errors.
// It just cleans back the stack, and sends no entity events.
//
void ReaderMgr::cleanStackBackTo(const unsigned int readerNum)
{
//
// Just start popping readers until we find the one with the indicated
// reader number.
//
while (true)
{
if (fCurReader->getReaderNum() == readerNum)
break;
if (fReaderStack->empty())
David Abram Cargill
committed
ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::RdrMgr_ReaderIdNotFound, fMemoryManager);
delete fCurReader;
fCurReader = fReaderStack->pop();
fCurEntity = fEntityStack->pop();
}
}
XMLReader* ReaderMgr::createReader( const InputSource& src
David Abram Cargill
committed
, const bool
, const XMLReader::RefFrom refFrom
, const XMLReader::Types type
, const XMLReader::Sources source
, const bool calcSrcOfs)
{
//
// Ask the input source to create us an input stream. The particular
// type of input source will know what kind to create.
//
BinInputStream* newStream = src.makeStream();
if (!newStream)
return 0;
//
// Create a new reader and return it. If the source has an encoding that
// it wants to force, then we call the constructor that does that.
// Otherwise, we just call the one that provides the provisional encoding
// to be possibly updated later by the encoding="" setting.
//
XMLReader* retVal = 0;
// XMLReader ctor invokes refreshRawBuffer() which calls
// This readBytes() may throw exception, which neither
// refresRawBuffer(), nor XMLReader ctor catches.
// We need to handle this exception to avoid leak on newStream.
try {
if (src.getEncoding())
{
retVal = new (fMemoryManager) XMLReader
(
src.getPublicId()
, src.getSystemId()
, newStream
, src.getEncoding()
, refFrom
, type
, source
Khaled Noaman
committed
, fMemoryManager
retVal = new (fMemoryManager) XMLReader
(
src.getPublicId()
, src.getSystemId()
, newStream
, refFrom
, type
, source
Khaled Noaman
committed
, fMemoryManager
Neil Graham
committed
catch(const OutOfMemoryException&)
{
throw;
}
catch (...) //NetAccessorException&
{
delete newStream;
throw;
}
// If it failed for any reason, then return zero.
if (!retVal) {
delete newStream;
return 0;
}
// Set the next available reader number on this reader
retVal->setReaderNum(fNextReaderNum++);
return retVal;
}
XMLReader* ReaderMgr::createReader( const XMLCh* const sysId
, const XMLCh* const pubId
, const bool xmlDecl
, const XMLReader::RefFrom refFrom
, const XMLReader::Types type
, const XMLReader::Sources source
, InputSource*& srcToFill
, const bool calcSrcOfs)
//Normalize sysId
XMLBuffer normalizedSysId(1023, fMemoryManager);
PeiYong Zhang
committed
XMLString::removeChar(sysId, 0xFFFF, normalizedSysId);
const XMLCh* normalizedURI = normalizedSysId.getRawBuffer();
// Create a buffer for expanding the system id
XMLBuffer expSysId(1023, fMemoryManager);
//
// Allow the entity handler to expand the system id if they choose
// to do so.
//
if (fEntityHandler)
{
PeiYong Zhang
committed
if (!fEntityHandler->expandSystemId(normalizedURI, expSysId))
expSysId.set(normalizedURI);
PeiYong Zhang
committed
expSysId.set(normalizedURI);
}
// Call the entity resolver interface to get an input source
srcToFill = 0;
if (fEntityHandler)
{
LastExtEntityInfo lastInfo;
getLastExtEntityInfo(lastInfo);
XMLResourceIdentifier resourceIdentifier(XMLResourceIdentifier::ExternalEntity,
expSysId.getRawBuffer(), XMLUni::fgZeroLenString, pubId, lastInfo.systemId);
srcToFill = fEntityHandler->resolveEntity(&resourceIdentifier);
}
//
// If they didn't create a source via the entity resolver, then we
// have to create one on our own.
//
if (!srcToFill)
{
LastExtEntityInfo lastInfo;
getLastExtEntityInfo(lastInfo);
David Abram Cargill
committed
// Keep this #if 0 block as it was exposing a threading problem on AIX.
// Got rid of the problem by changing XMLURL to not throw malformedurl
// exceptions.
#if 0
David Abram Cargill
committed
XMLURL urlTmp(lastInfo.systemId, expSysId.getRawBuffer(), fMemoryManager);
David Abram Cargill
committed
ThrowXMLwithMemMgr
(
MalformedURLException
, XMLExcepts::URL_NoProtocolPresent
David Abram Cargill
committed
, fMemoryManager
else {
if (fStandardUriConformant && urlTmp.hasInvalidChar())
David Abram Cargill
committed
ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager);
Khaled Noaman
committed
srcToFill = new (fMemoryManager) URLInputSource(urlTmp, fMemoryManager);
}
catch(const MalformedURLException& e)
// Its not a URL, so lets assume its a local file name if non-standard uri is allowed
if (!fStandardUriConformant)
srcToFill = new (fMemoryManager) LocalFileInputSource
(
lastInfo.systemId
, expSysId.getRawBuffer()
Khaled Noaman
committed
, fMemoryManager
);
else
throw e;
David Abram Cargill
committed
#else
XMLURL urlTmp(fMemoryManager);
if ((!urlTmp.setURL(lastInfo.systemId, expSysId.getRawBuffer(), urlTmp)) ||
(urlTmp.isRelative()))
{
if (!fStandardUriConformant)
PeiYong Zhang
committed
{
XMLBuffer resolvedSysId(1023, fMemoryManager);
XMLUri::normalizeURI(expSysId.getRawBuffer(), resolvedSysId);
David Abram Cargill
committed
srcToFill = new (fMemoryManager) LocalFileInputSource
(
lastInfo.systemId
PeiYong Zhang
committed
, resolvedSysId.getRawBuffer()
David Abram Cargill
committed
, fMemoryManager
);
PeiYong Zhang
committed
}
David Abram Cargill
committed
else
ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager);
}
else
{
if (fStandardUriConformant && urlTmp.hasInvalidChar())
ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager);
srcToFill = new (fMemoryManager) URLInputSource(urlTmp, fMemoryManager);
}
#endif
}
// Put a janitor on the input source
Janitor<InputSource> janSrc(srcToFill);
//
// Now call the other version with the input source that we have, and
// return the resulting reader.
//
XMLReader* retVal = createReader
(
*srcToFill
, xmlDecl
, refFrom
, type
, source
);
// Either way, we can release the input source now
janSrc.orphan();
// If it failed for any reason, then return zero.
if (!retVal)
return 0;
// Give this reader the next available reader number and return it
retVal->setReaderNum(fNextReaderNum++);
return retVal;
}
XMLReader* ReaderMgr::createReader( const XMLCh* const baseURI
, const XMLCh* const sysId
, const XMLCh* const pubId
, const bool xmlDecl
, const XMLReader::RefFrom refFrom
, const XMLReader::Types type
, const XMLReader::Sources source
, InputSource*& srcToFill
, const bool calcSrcOfs)
//Normalize sysId
XMLBuffer normalizedSysId(1023, fMemoryManager);
XMLString::removeChar(sysId, 0xFFFF, normalizedSysId);
const XMLCh* normalizedURI = normalizedSysId.getRawBuffer();
// Create a buffer for expanding the system id
Khaled Noaman
committed
XMLBuffer expSysId(1023, fMemoryManager);
//
// Allow the entity handler to expand the system id if they choose
// to do so.
//
if (fEntityHandler)
{
PeiYong Zhang
committed
if (!fEntityHandler->expandSystemId(normalizedURI, expSysId))
expSysId.set(normalizedURI);
PeiYong Zhang
committed
expSysId.set(normalizedURI);
}
// Call the entity resolver interface to get an input source
srcToFill = 0;
if (fEntityHandler)
{
XMLResourceIdentifier resourceIdentifier(XMLResourceIdentifier::ExternalEntity,
expSysId.getRawBuffer(), XMLUni::fgZeroLenString, pubId, baseURI);
srcToFill = fEntityHandler->resolveEntity(&resourceIdentifier);
}
//
// If they didn't create a source via the entity resolver, then we
// have to create one on our own.
//
if (!srcToFill)
{
LastExtEntityInfo lastInfo;
Alberto Massari
committed
const XMLCh* baseuri=baseURI;
if(!baseuri || !*baseuri)
{
getLastExtEntityInfo(lastInfo);
baseuri = lastInfo.systemId;
}
David Abram Cargill
committed
XMLURL urlTmp(fMemoryManager);
Alberto Massari
committed
if ((!urlTmp.setURL(baseuri, expSysId.getRawBuffer(), urlTmp)) ||
David Abram Cargill
committed
(urlTmp.isRelative()))
if (!fStandardUriConformant)
PeiYong Zhang
committed
{
XMLBuffer resolvedSysId(1023, fMemoryManager);
XMLUri::normalizeURI(expSysId.getRawBuffer(), resolvedSysId);
srcToFill = new (fMemoryManager) LocalFileInputSource
(
Alberto Massari
committed
baseuri
PeiYong Zhang
committed
, resolvedSysId.getRawBuffer()
Khaled Noaman
committed
, fMemoryManager
);
PeiYong Zhang
committed
}
else
David Abram Cargill
committed
ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager);
David Abram Cargill
committed
else
{
if (fStandardUriConformant && urlTmp.hasInvalidChar())
ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager);
srcToFill = new (fMemoryManager) URLInputSource(urlTmp, fMemoryManager);
}
}
// Put a janitor on the input source
Janitor<InputSource> janSrc(srcToFill);
//
// Now call the other version with the input source that we have, and
// return the resulting reader.
//
XMLReader* retVal = createReader
(
*srcToFill
, xmlDecl
, refFrom
, type
, source
);
// Either way, we can release the input source now
janSrc.orphan();
// If it failed for any reason, then return zero.
if (!retVal)
return 0;
// Give this reader the next available reader number and return it
retVal->setReaderNum(fNextReaderNum++);
return retVal;
}
XMLReader*
ReaderMgr::createIntEntReader( const XMLCh* const sysId
, const XMLReader::RefFrom refFrom
, const XMLReader::Types type
, const XMLCh* const dataBuf
, const unsigned int dataLen
, const bool copyBuf
, const bool calcSrcOfs)
{
//
// This one is easy, we just create an input stream for the data and
// provide a few extra goodies.
//
// NOTE: We use a special encoding string that will be recognized
// as a 'do nothing' transcoder for the already internalized XMLCh
// data that makes up an internal entity.
//
BinMemInputStream* newStream = new (fMemoryManager) BinMemInputStream
(
(const XMLByte*)dataBuf
, dataLen * sizeof(XMLCh)
, copyBuf ? BinMemInputStream::BufOpt_Copy
: BinMemInputStream::BufOpt_Reference
, fMemoryManager
);
if (!newStream)
return 0;
XMLReader* retVal = new (fMemoryManager) XMLReader
Khaled Noaman
committed
, fMemoryManager
// If it failed for any reason, then return zero.
if (!retVal) {
delete newStream;
return 0;
}
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
// Set the reader number to the next available number
retVal->setReaderNum(fNextReaderNum++);
return retVal;
}
const XMLCh* ReaderMgr::getCurrentEncodingStr() const
{
const XMLEntityDecl* theEntity;
const XMLReader* theReader = getLastExtEntity(theEntity);
return theReader->getEncodingStr();
}
const XMLEntityDecl* ReaderMgr::getCurrentEntity() const
{
return fCurEntity;
}
XMLEntityDecl* ReaderMgr::getCurrentEntity()
{
return fCurEntity;
}
unsigned int ReaderMgr::getReaderDepth() const
{
// If the stack doesn't exist, its obviously zero
if (!fEntityStack)
return 0;
//
// The return is the stack size, plus one if there is a current
// reader. So if there is no current reader and none on the stack,
// its zero, else its some non-zero value.
//
unsigned int retVal = fEntityStack->size();
if (fCurReader)
retVal++;
return retVal;
}
void ReaderMgr::getLastExtEntityInfo(LastExtEntityInfo& lastInfo) const
{
//
// If the reader stack never got created or we've not managed to open any
// main entity yet, then we can't give this information.
//
if (!fReaderStack || !fCurReader)
{
lastInfo.systemId = XMLUni::fgZeroLenString;
lastInfo.publicId = XMLUni::fgZeroLenString;
lastInfo.lineNumber = 0;
lastInfo.colNumber = 0;
return;
}
// We have at least one entity so get the data
const XMLEntityDecl* theEntity;
const XMLReader* theReader = getLastExtEntity(theEntity);
// Fill in the info structure with the reader we found
lastInfo.systemId = theReader->getSystemId();
lastInfo.publicId = theReader->getPublicId();
lastInfo.lineNumber = theReader->getLineNumber();
lastInfo.colNumber = theReader->getColumnNumber();
}
bool ReaderMgr::isScanningPERefOutOfLiteral() const
{
// If the current reader is not for an entity, then definitely not
if (!fCurEntity)
return false;
//
// If this is a PE entity, and its not being expanded in a literal
// then its true.
//
if ((fCurReader->getType() == XMLReader::Type_PE)
&& (fCurReader->getRefFrom() == XMLReader::RefFrom_NonLiteral))
{
return true;
}
return false;
}
bool ReaderMgr::pushReader( XMLReader* const reader
, XMLEntityDecl* const entity)
{
//
// First, if an entity was passed, we have to confirm that this entity
// is not already on the entity stack. If so, then this is a recursive
// entity expansion, so we issue an error and refuse to put the reader
// on the stack.
//
// If there is no entity passed, then its not an entity being pushed, so
// nothing to do. If there is no entity stack yet, then of coures it
// cannot already be there.
//
if (entity && fEntityStack)
{
const unsigned int count = fEntityStack->size();
const XMLCh* const theName = entity->getName();
for (unsigned int index = 0; index < count; index++)
{
const XMLEntityDecl* curDecl = fEntityStack->elementAt(index);
if (curDecl)
{
if (XMLString::equals(theName, curDecl->getName()))
{
// Oops, already there so delete reader and return
delete reader;
return false;
}
}
}
}
//
// Fault in the reader stack. Give it an initial capacity of 16, and
// tell it it does own its elements.
//
if (!fReaderStack)
fReaderStack = new (fMemoryManager) RefStackOf<XMLReader>(16, true, fMemoryManager);
// And the entity stack, which does not own its elements
if (!fEntityStack)
fEntityStack = new (fMemoryManager) RefStackOf<XMLEntityDecl>(16, false, fMemoryManager);
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
//
// Push the current reader and entity onto their respective stacks.
// Note that the the current entity can be null if the current reader
// is not for an entity.
//
if (fCurReader)
{
fReaderStack->push(fCurReader);
fEntityStack->push(fCurEntity);
}
//
// Make the passed reader and entity the current top of stack. The
// passed entity can (and often is) null.
//
fCurReader = reader;
fCurEntity = entity;
return true;
}
void ReaderMgr::reset()
{
// Reset all of the flags
fThrowEOE = false;
// Delete the current reader and flush the reader stack
delete fCurReader;
fCurReader = 0;
if (fReaderStack)
fReaderStack->removeAllElements();
//
// And do the same for the entity stack, but don't delete the current
// entity (if any) since we don't own them.
//
fCurEntity = 0;
if (fEntityStack)
fEntityStack->removeAllElements();
}
// ---------------------------------------------------------------------------
// ReaderMgr: Implement the SAX Locator interface
// ---------------------------------------------------------------------------
const XMLCh* ReaderMgr::getPublicId() const
{
if (!fReaderStack && !fCurReader)
return XMLUni::fgZeroLenString;
const XMLEntityDecl* theEntity;
return getLastExtEntity(theEntity)->getPublicId();
}
const XMLCh* ReaderMgr::getSystemId() const
{
if (!fReaderStack && !fCurReader)
return XMLUni::fgZeroLenString;
const XMLEntityDecl* theEntity;
return getLastExtEntity(theEntity)->getSystemId();
}
Tinny Ng
committed
XMLSSize_t ReaderMgr::getColumnNumber() const
{
if (!fReaderStack && !fCurReader)
return 0;
const XMLEntityDecl* theEntity;
return getLastExtEntity(theEntity)->getColumnNumber();
}
Tinny Ng
committed
XMLSSize_t ReaderMgr::getLineNumber() const
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
{
if (!fReaderStack && !fCurReader)
return 0;
const XMLEntityDecl* theEntity;
return getLastExtEntity(theEntity)->getLineNumber();
}
// ---------------------------------------------------------------------------
// ReaderMgr: Private helper methods
// ---------------------------------------------------------------------------
const XMLReader*
ReaderMgr::getLastExtEntity(const XMLEntityDecl*& itsEntity) const
{
//
// Scan down the reader stack until we find a reader for an entity that
// is external. First check that there is anything in the stack at all,
// in which case the current reader is the main file and that's the one
// that we want.
//
const XMLReader* theReader = fCurReader;
//