// balxml_utf8readerwrapper.h -*-C++-*- // ---------------------------------------------------------------------------- // NOTICE // // This component is not up to date with current BDE coding standards, and // should not be used as an example for new development. // ---------------------------------------------------------------------------- #ifndef INCLUDED_BALXML_UTF8READERWRAPPER #define INCLUDED_BALXML_UTF8READERWRAPPER #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide wrapper for 'Reader' to check input UTF-8 validity. // //@CLASSES: // balxml::Utf8ReaderWrapper: Wrap a 'Reader', check UTF-8 input. // //@SEE_ALSO: balxml_reader // balxml_errorinfo // bdlde_utf8streambufinputwrapper // //@DESCRIPTION: This component supplies a mechanism, // 'balxml::Utf8ReaderWrapper', which holds another object of type // 'balxml::Reader' and forwards operations to the held object. The held // object is to operate on a 'bsl::streambuf', which is in fact a // 'bdlde::Utf8CheckingInStreamBufWrapper' contained in the object, which holds // another 'bsl::streambuf' and forward actions to that held 'bsl::streambuf'. // // The 'bdlde_Utf8StreamBufInputWrapper' detects invalid UTF-8. If the input // contains nothing but valid UTF-8, the 'bdlde_Utf8StreamBufInputWrapper' // simply forwards all operations to the 'bsl::streambuf' it holds, and the // wrapper has no influence on behavior. // // Similarly, if the input contains nothing but valid UTF-8, the reader wrapper // simply forwards all operations to the held 'Reader' and has no influence on // behavior. // // If invalid UTF-8 occurs in the input, 'errorInfo().message()' will reflect // the nature of the UTF-8 error. // ///Usage ///----- // This section illustrates intended use of this component. // ///Example 1: Routine Parsing: /// - - - - - - - - - - - - - // Utility function to skip past white space. //.. // int advancePastWhiteSpace(balxml::Reader& reader) // { // static const char whiteSpace[] = "\n\r\t "; // const char *value = 0; // int type = 0; // int rc = 0; // // do { // rc = reader.advanceToNextNode(); // value = reader.nodeValue(); // type = reader.nodeType(); // } while ((0 == rc && type == balxml::Reader::e_NODE_TYPE_WHITESPACE) || // (type == balxml::Reader::e_NODE_TYPE_TEXT && // bsl::strlen(value) == bsl::strspn(value, whiteSpace))); // // assert( reader.nodeType() != balxml::Reader::e_NODE_TYPE_WHITESPACE); // // return rc; // } //.. // Then, in 'main', we parse an XML string using the UTF-8 reader wrapper: // // The following string describes xml for a very simple user directory. The // top level element contains one xml namespace attribute, with one embedded // entry describing a user. The person's name contains some non-ascii UTF-8. //.. // static const char TEST_XML_STRING[] = // "<?xml version='1.0' encoding='UTF-8'?>\n" // "<directory-entry xmlns:dir='http://bloomberg.com/schemas/directory'>\n" // " <name>John Smith\xe7\x8f\x8f</name>\n" // " <phone dir:phonetype='cell'>212-318-2000</phone>\n" // " <address/>\n" // "</directory-entry>\n"; //.. // In order to read the XML, we first need to construct a // 'balxml::NamespaceRegistry' object, a 'balxml::PrefixStack' object, and a // 'Utf8ReaderWrapper' object. //.. // balxml::NamespaceRegistry namespaces; // balxml::PrefixStack prefixStack(&namespaces); // balxml::MiniReader miniReader; // balxml::Utf8ReaderWrapper reader(&miniReader); // // assert(!reader.isOpen()); //.. // The reader uses a 'balxml::PrefixStack' to manage namespace prefixes so we // need to set it before we call open. //.. // reader.setPrefixStack(&prefixStack); // assert(reader.prefixStack()); // assert(reader.prefixStack() == &prefixStack); //.. // Now we call the 'open' method to setup the reader for parsing using the data // contained in the in the XML string. //.. // reader.open(TEST_XML_STRING, sizeof(TEST_XML_STRING) -1, 0, "UTF-8"); //.. // Confirm that the 'bdem::Reader' has opened properly //.. // assert( reader.isOpen()); // assert(!bsl::strncmp(reader.documentEncoding(), "UTF-8", 5)); // assert( reader.nodeType() == balxml::Reader::e_NODE_TYPE_NONE); // assert(!reader.nodeName()); // assert(!reader.nodeHasValue()); // assert(!reader.nodeValue()); // assert(!reader.nodeDepth()); // assert(!reader.numAttributes()); // assert(!reader.isEmptyElement()); //.. // Advance through all the nodes and assert all information contained at each // node is correct. // // Assert the next node's document type is xml. //.. // int rc = advancePastWhiteSpace(reader); // assert( 0 == rc); // assert( reader.nodeType() == // balxml::Reader::e_NODE_TYPE_XML_DECLARATION); // assert(!bsl::strcmp(reader.nodeName(), "xml")); // assert( reader.nodeHasValue()); // assert(!bsl::strcmp(reader.nodeValue(), "version='1.0' encoding='UTF-8'")); // assert( reader.nodeDepth() == 1); // assert(!reader.numAttributes()); // assert(!reader.isEmptyElement()); // assert( 0 == rc); // assert( reader.nodeDepth() == 1); //.. // Advance to the top level element, which has one attribute, the xml // namespace. Assert the namespace information has been added correctly to the // prefix stack. //.. // rc = advancePastWhiteSpace(reader); // assert( 0 == rc); // assert( reader.nodeType() == balxml::Reader::e_NODE_TYPE_ELEMENT); // assert(!bsl::strcmp(reader.nodeName(), "directory-entry")); // assert(!reader.nodeHasValue()); // assert( reader.nodeDepth() == 1); // assert( reader.numAttributes() == 1); // assert(!reader.isEmptyElement()); // // assert(!bsl::strcmp(prefixStack.lookupNamespacePrefix("dir"), "dir")); // assert(prefixStack.lookupNamespaceId("dir") == 0); // assert(!bsl::strcmp(prefixStack.lookupNamespaceUri("dir"), // "http://bloomberg.com/schemas/directory")); //.. // The XML being read contains one entry describing a user, advance the users // name name and assert all information can be read correctly. //.. // rc = advancePastWhiteSpace(reader); // assert( 0 == rc); // assert( reader.nodeType() == balxml::Reader::e_NODE_TYPE_ELEMENT); // assert(!bsl::strcmp(reader.nodeName(), "name")); // assert(!reader.nodeHasValue()); // assert( reader.nodeDepth() == 2); // assert( reader.numAttributes() == 0); // assert(!reader.isEmptyElement()); // // rc = reader.advanceToNextNode(); // assert( 0 == rc); // assert( reader.nodeType() == balxml::Reader::e_NODE_TYPE_TEXT); // assert( reader.nodeHasValue()); // assert(!bsl::strcmp(reader.nodeValue(), "John Smith\xe7\x8f\x8f")); // assert( reader.nodeDepth() == 3); // assert( reader.numAttributes() == 0); // assert(!reader.isEmptyElement()); // // rc = reader.advanceToNextNode(); // assert( 0 == rc); // assert( reader.nodeType() == balxml::Reader::e_NODE_TYPE_END_ELEMENT); // assert(!bsl::strcmp(reader.nodeName(), "name")); // assert(!reader.nodeHasValue()); // assert( reader.nodeDepth() == 2); // assert( reader.numAttributes() == 0); // assert(!reader.isEmptyElement()); //.. // Advance to the user's phone number and assert all information can be read // correctly. //.. // rc = advancePastWhiteSpace(reader); // assert( 0 == rc); // assert( reader.nodeType() == balxml::Reader::e_NODE_TYPE_ELEMENT); // assert(!bsl::strcmp(reader.nodeName(), "phone")); // assert(!reader.nodeHasValue()); // assert( reader.nodeDepth() == 2); // assert( reader.numAttributes() == 1); // assert(!reader.isEmptyElement()); //.. // The phone node has one attribute, look it up and assert the // 'balxml::ElementAttribute' contains valid information and that the prefix // returns the correct namespace URI from the prefix stack. //.. // balxml::ElementAttribute elemAttr; // // rc = reader.lookupAttribute(&elemAttr, 0); // assert( 0 == rc); // assert(!elemAttr.isNull()); // assert(!bsl::strcmp(elemAttr.qualifiedName(), "dir:phonetype")); // assert(!bsl::strcmp(elemAttr.value(), "cell")); // assert(!bsl::strcmp(elemAttr.prefix(), "dir")); // assert(!bsl::strcmp(elemAttr.localName(), "phonetype")); // assert(!bsl::strcmp(elemAttr.namespaceUri(), // "http://bloomberg.com/schemas/directory")); // assert( elemAttr.namespaceId() == 0); // // assert(!bsl::strcmp(prefixStack.lookupNamespaceUri(elemAttr.prefix()), // elemAttr.namespaceUri())); // // rc = advancePastWhiteSpace(reader); // assert( 0 == rc); // assert( reader.nodeType() == balxml::Reader::e_NODE_TYPE_TEXT); // assert( reader.nodeHasValue()); // assert(!bsl::strcmp(reader.nodeValue(), "212-318-2000")); // assert( reader.nodeDepth() == 3); // assert( reader.numAttributes() == 0); // assert(!reader.isEmptyElement()); // // rc = advancePastWhiteSpace(reader); // assert( 0 == rc); // assert( reader.nodeType() == balxml::Reader::e_NODE_TYPE_END_ELEMENT); // assert(!bsl::strcmp(reader.nodeName(), "phone")); // assert(!reader.nodeHasValue()); // assert( reader.nodeDepth() == 2); // assert( reader.numAttributes() == 0); // assert(!reader.isEmptyElement()); //.. // Advance to the user's address and assert all information can be read // correctly. //.. // rc = advancePastWhiteSpace(reader); // assert( 0 == rc); // assert( reader.nodeType() == balxml::Reader::e_NODE_TYPE_ELEMENT); // assert(!bsl::strcmp(reader.nodeName(), "address")); // assert(!reader.nodeHasValue()); // assert( reader.nodeDepth() == 2); // assert( reader.numAttributes() == 0); // assert( reader.isEmptyElement()); //.. // Advance to the end element. //.. // rc = advancePastWhiteSpace(reader); // assert( 0 == rc); // assert( reader.nodeType() == balxml::Reader::e_NODE_TYPE_END_ELEMENT); // assert(!bsl::strcmp(reader.nodeName(), "directory-entry")); // assert(!reader.nodeHasValue()); // assert( reader.nodeDepth() == 1); // assert( reader.numAttributes() == 0); // assert(!reader.isEmptyElement()); //.. // Close the reader. //.. // reader.close(); // assert(!reader.isOpen()); // // return 0; //.. #include <balscm_version.h> #include <balxml_errorinfo.h> #include <balxml_reader.h> #include <bdlde_utf8checkinginstreambufwrapper.h> #include <bdlsb_fixedmeminstreambuf.h> #include <bslmf_nestedtraitdeclaration.h> #include <bsls_keyword.h> #include <bsl_cstddef.h> // for size_t #include <bsl_functional.h> #include <bsl_fstream.h> #include <bsl_streambuf.h> namespace BloombergLP { namespace balxml { class ElementAttribute; class ErrorInfo; class PrefixStack; // ======================= // class Utf8ReaderWrapper // ======================= class Utf8ReaderWrapper : public Reader { // This class "has a" pointer to a held and wrapped 'Reader' object, and // operations on this object are passed to the held reader. The held // reader is passed a 'Utf8CheckingInStreamBufWrapper', which holds and // wraps a normal 'streambuf'. The 'Utf8CheckingInStreamBufWrapper' checks // input for invalid UTF-8, and if it detects any, makes the diagnosis of // the problem available through the 'errorInfo' accessor. // DATA bdlde::Utf8CheckingInStreamBufWrapper d_utf8StreamBuf; bdlsb::FixedMemInStreamBuf d_fixedStreamBuf; bsl::ifstream d_stream; Reader * d_reader_p; ErrorInfo d_errorInfo; bool d_useHeldErrorInfo; private: // NOT IMPLEMENTED Utf8ReaderWrapper(const Utf8ReaderWrapper&); Utf8ReaderWrapper& operator=(const Utf8ReaderWrapper&); public: // TRAITS BSLMF_NESTED_TRAIT_DECLARATION(Utf8ReaderWrapper, bslma::UsesBslmaAllocator); private: // PRIVATE MANIPULATORS int doOpen(const char *url, const char *encoding); // Open the held reader with 'd_utf8StreamBuf', as well as the // specified 'url' and 'encoding'. Note that all public 'open' // functions of this class prepare 'd_utf8StreamBuf' and then delegate // to this function as part of their implementation. Reader *heldReader(); // Return a pointer providing modifiable access to the held 'Reader'. void reportUtf8Error(int utf8Rc); // Called when a UTF-8 error is encountered, to make 'd_errorInfo' into // a combination of 'heldReader()->errorInfo()' and the nature of the // UTF-8 error as reported by the specified 'utf8Rc'. The behavior is // undefined unless 'utf8Rc < 0' and 'utf8Rc' is one of the values // enumerated by 'Utf8Util::ErrorStatus'. // PRIVATE ACCESSORS const Reader *heldReader() const; // Return a pointer providing non-modifiable access to the held // 'Reader'. public: // CREATORS explicit Utf8ReaderWrapper(Reader *reader, bslma::Allocator *basicAllocator = 0); // Create a 'Utf8ReaderWrapper' that holds the specified 'reader'. // Optionally specify a 'basicAllocator' used to supply memory. If // 'basicAllocator' is 0, the currently installed default allocator is // used. The behavior is undefined unless 'reader' has never been // opened or closed. ~Utf8ReaderWrapper(); // Close the held reader and destroy this object. // MANIPULATORS // ** setup methods ** void setOptions(unsigned int flags) BSLS_KEYWORD_OVERRIDE; // Set the options of the held reader to the flags in the specified // 'flags'. The options for the reader are persistent, i.e., the // options are not reset by 'close'. The behavior is undefined if this // method is called after calling 'open' and before calling 'close'; // except that derived classes are permitted to specify valid behavior // for calling this function for specific arguments while the reader is // open. void setPrefixStack(PrefixStack *prefixes) BSLS_KEYWORD_OVERRIDE; // Set the prefix stack to the stack at the optionally specified // 'prefixes' address or disable prefix stack support if 'prefixes' is // null. This stack is used to push and pop namespace prefixes as the // parse progresses, so that, at any point, the stack will reflect the // set of active prefixes for the current node. It is legitimate to // pass a stack that already contains prefixes, these prefixes shall be // preserved when 'close' is called, i.e., the prefix stack shall be // returned to the stack depth it had when 'setPrefixStack' was called. // The behavior is undefined if this method is called after calling // 'open' and before calling 'close'. void setResolver(XmlResolverFunctor resolver) BSLS_KEYWORD_OVERRIDE; // Set the external XML resource resolver to the specified 'resolver'. // The XML resource resolver is used by the 'balxml_reader' to find and // open an external resources (See the 'XmlResolverFunctor' typedef for // more details). The XML resource resolver remains valid; it is not // affected by a call to 'close' and should be available until the // reader is destroyed. The behavior is undefined if this method is // called after calling 'open' and before calling 'close'. // ** open/close methods ** int open(const char *filename, const char *encoding = 0) BSLS_KEYWORD_OVERRIDE; // Set up the reader for parsing using the data contained in the XML // file described by the specified 'filename', and set the encoding // value to the optionally specified 'encoding' ("ASCII", "UTF-8", // etc). Returns 0 on success and non-zero otherwise. The encoding // passed to 'Reader::open' will take effect only when there is no // encoding information in the original document, i.e., the encoding // information obtained from the XML file described by the 'filename' // trumps all. If there is no encoding provided within the document // and 'encoding' is null or a blank string is passed, then set the // encoding to the default "UTF-8". It is an error to 'open' a reader // that is already open. Note that the reader will not be on a valid // node until 'advanceToNextNode' is called. int open(const char *buffer, bsl::size_t size, const char *url = 0, const char *encoding = 0) BSLS_KEYWORD_OVERRIDE; // Set up the reader for parsing using the data contained in the // specified (XML) 'buffer' of the specified 'size', set the base URL // to the optionally specified 'url' and set the encoding value to the // optionally specified 'encoding' ("ASCII", "UTF-8", etc). Return 0 // on success and non-zero otherwise. If 'url' is null or a blank // string is passed, then base URL will be empty. The encoding passed // to 'Reader::open' will take effect only when there is no encoding // information in the original document, i.e., the encoding information // obtained from the (XML) 'buffer' trumps all. If there is no // encoding provided within the document and 'encoding' is null or a // blank string is passed, then set the encoding to the default // "UTF-8". It is an error to 'open' a reader that is already open. // Note that the reader will not be on a valid node until // 'advanceToNextNode' is called. int open(bsl::streambuf *stream, const char *url = 0, const char *encoding = 0) BSLS_KEYWORD_OVERRIDE; // Set up the reader for parsing using the data contained in the // specified (XML) 'stream', set the base URL to the optionally // specified 'url' and set the encoding value to the optionally // specified 'encoding' ("ASCII", "UTF-8", etc). Return 0 on success // and non-zero otherwise. If 'url' is null or a blank string is // passed, then base URL will be empty. The encoding passed to // 'Reader::open' will take effect only when there is no encoding // information in the original document, i.e., the encoding information // obtained from the (XML) 'stream' trumps all. If there is no // encoding provided within the document and 'encoding' is null or a // blank string is passed, then set the encoding to the default // "UTF-8". It is an error to 'open' a reader that is already open. // Note that the reader will not be on a valid node until // 'advanceToNextNode' is called. void close() BSLS_KEYWORD_OVERRIDE; // Close the reader. Most, but not all state is reset. Specifically, // the XML resource resolver and the prefix stack remain. The prefix // stack shall be returned to the stack depth it had when // 'setPrefixStack' was called. Call the method 'open' to reuse the // reader. Note that 'close' invalidates all strings and data // structures obtained via 'Reader' accessors. E.g., the pointer // returned from 'nodeName' for this node will not be valid once // 'close' is called. // ** navigation method ** int advanceToNextNode() BSLS_KEYWORD_OVERRIDE; // Move to the next node in the data steam created by 'open' thus // allowing the node's properties to be queried via the 'Reader' // accessors. Return 0 on successful read, 1 if there are no more // nodes to read, and a negative number otherwise. Note that each call // to 'advanceToNextNode' invalidates strings and data structures // returned when 'Reader' accessors where call for the "prior node". // E.g., the pointer returned from 'nodeName' for this node will not be // valid once 'advanceToNextNode' is called. Note that the reader will // not be on a valid node until the first call to 'advanceToNextNode' // after the reader is opened. // ACCESSORS bslma::Allocator *allocator() const; // Return the allocator used by this object to allocate memory. const char *documentEncoding() const BSLS_KEYWORD_OVERRIDE; // Return the document encoding or NULL on error. The returned poiner // is owned by this object and must not be modified or deallocated by // the caller. The returned pointer becomes invalid when 'close' is // called or the reader is destroyed. const ErrorInfo& errorInfo() const BSLS_KEYWORD_OVERRIDE; // Return a reference to the non-modifiable error information for this // reader. The returned value becomes invalid when 'close' is called // or the reader is destroyed. int getColumnNumber() const BSLS_KEYWORD_OVERRIDE; // Return the current column number within the input stream. The // current column number is the number of characters since the last // newline was read by the reader plus one, i.e., the first column of // each line is column number one. Return 0 if not available. Note // that a derived-class implementation is not required to count // columns and may just return 0. int getLineNumber() const BSLS_KEYWORD_OVERRIDE; // Return the current line number within the input stream. The current // line is the last line for which the reader has not yet seen a // newline. Lines are counted starting at one from the time a stream // is provided to 'open'. Return 0 if not available. Note that a // derived-class implementation is not required to count lines and may // just return 0. bool isEmptyElement() const BSLS_KEYWORD_OVERRIDE; // Return true if the current node is an element (i.e., node type is // 'BAEXML_NODE_TYPE_ELEMENT') that ends with '/>'; and false // otherwise. Note that '<a/>' will be considered empty but '<a></a>' // will not. bool isOpen() const BSLS_KEYWORD_OVERRIDE; // Return true if 'open' was called successfully and 'close' has not // yet been called and false otherwise. int lookupAttribute(ElementAttribute *attribute, int index) const BSLS_KEYWORD_OVERRIDE; // Find the attribute at the specified 'index' in the current node, and // fill in the specified 'attribute' structure. Return 0 on success, 1 // if no attribute is found at the 'index', and an a negative value // otherwise. The strings that were filled into the 'attribute' // structure are invalid upon the next 'advanceToNextNode' or 'close' // is called. int lookupAttribute(ElementAttribute *attribute, const char *qname) const BSLS_KEYWORD_OVERRIDE; // Find the attribute with the specified 'qname' (qualified name) in // the current node, and fill in the specified 'attribute' structure. // Return 0 on success, 1 if there is no attribute found with 'qname', // and a negative value otherwise. The strings that were filled into // the 'attribute' structure are invalid upon the next // 'advanceToNextNode' or 'close' is called. int lookupAttribute( ElementAttribute *attribute, const char *localName, const char *namespaceUri) const BSLS_KEYWORD_OVERRIDE; // Find the attribute with the specified 'localName' and specified // 'namespaceUri' in the current node, and fill in the specified // 'attribute' structure. Return 0 on success, 1 if there is no // attribute found with 'localName' and 'namespaceUri', and a negative // value otherwise. If 'namespaceUri' == 0 or a blank string is // passed, then the document's default namespace will be used. The // strings that were filled into the 'attribute' structure are invalid // upon the next 'advanceToNextNode' or 'close' is called. int lookupAttribute( ElementAttribute *attribute, const char *localName, int namespaceId) const BSLS_KEYWORD_OVERRIDE; // Find the attribute with the specified 'localName' and specified // 'namespaceId' in the current node, and fill in the specified // 'attribute' structure. Return 0 on success, 1 if there is no // attribute found with 'localName' and 'namespaceId', and a negative // value otherwise. If 'namespaceId' == -1, then the document's // default namespace will be used. The strings that were filled into // the 'attribute' structure are invalid upon the next // 'advanceToNextNode' or 'close' is called. const char *nodeBaseUri() const BSLS_KEYWORD_OVERRIDE; // Return the base URI name of the current node if the current node has // a base URI and NULL otherwise. The returned pointer is owned by // this object and must not be modified or deallocated by the caller. // The returned pointer becomes invalid upon the next // 'advanceToNextNode', when 'close' is called or the reader is // destroyed. int nodeDepth() const BSLS_KEYWORD_OVERRIDE; // Return the nesting depth of the current node in the XML document. // The root node has depth 0. const char *nodeLocalName() const BSLS_KEYWORD_OVERRIDE; // Return the local name of the current node if the current node has a // local name and NULL otherwise. The returned pointer is owned by // this object and must not be modified or deallocated by the caller. // The returned pointer becomes invalid upon the next // 'advanceToNextNode', when 'close' is called or the reader is // destroyed. bool nodeHasValue() const BSLS_KEYWORD_OVERRIDE; // Return true if the current node has a value and false otherwise. const char *nodeName() const BSLS_KEYWORD_OVERRIDE; // Return the qualified name of the current node if the current node // has a name and NULL otherwise. The returned pointer is owned by // this object and must not be modified or deallocated by the caller. // The returned pointer becomes invalid upon the next // 'advanceToNextNode', when 'close' is called or the reader is // destroyed. int nodeNamespaceId() const BSLS_KEYWORD_OVERRIDE; // Return the namespace ID of the current node if the current node has // a namespace id and a negative number otherwise. const char *nodeNamespaceUri() const BSLS_KEYWORD_OVERRIDE; // Return the namespace URI name of the current node if the current // node has a namespace URI and NULL otherwise. The returned pointer // is owned by this object and must not be modified or deallocated by // the caller. The returned pointer becomes invalid upon the next // 'advanceToNextNode', when 'close' is called or the reader is // destroyed. const char *nodePrefix() const BSLS_KEYWORD_OVERRIDE; // Return the prefix name of the current node if the correct node has a // prefix name and NULL otherwise. The returned pointer is owned by // this object and must not be modified or deallocated by the caller. // The returned pointer becomes invalid upon the next // 'advanceToNextNode', when 'close' is called or the reader is // destroyed. NodeType nodeType() const BSLS_KEYWORD_OVERRIDE; // Return the node type of the current node if the reader 'isOpen' and // has not encounter an error and 'Reader::NONE' otherwise. const char *nodeValue() const BSLS_KEYWORD_OVERRIDE; // Return the value of the current node if the current node has a value // and NULL otherwise. The returned pointer is owned by this object // and must not be modified or deallocated by the caller. The returned // pointer becomes invalid upon the next 'advanceToNextNode', when // 'close' is called or the reader is destroyed. int numAttributes() const BSLS_KEYWORD_OVERRIDE; // Return the number of attributes for the current node if that node // has attributes and 0 otherwise. unsigned int options() const BSLS_KEYWORD_OVERRIDE; // Return the option flags. PrefixStack *prefixStack() const BSLS_KEYWORD_OVERRIDE; // Return a pointer to the modifiable prefix stack that is used by this // reader to manage namespace prefixes or 0 if namespace support is // disabled. The behavior is undefined if the returned prefix stack is // augmented in any way after calling 'open' and before calling // 'close'. XmlResolverFunctor resolver() const BSLS_KEYWORD_OVERRIDE; // Return the external XML resource resolver. }; // ============================================================================ // INLINE DEFINITIONS // ============================================================================ // ------------ // class Reader // ------------ // PRIVATE MANIPULATORS inline Reader *Utf8ReaderWrapper::heldReader() { return d_reader_p; } // PRIVATE ACCESSORS inline const Reader *Utf8ReaderWrapper::heldReader() const { return d_reader_p; } } // close package namespace } // close enterprise namespace #endif // INCLUDED_BALXML_UTF8READERWRAPPER // ---------------------------------------------------------------------------- // Copyright 2020 Bloomberg Finance L.P. // // 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. // ----------------------------- END-OF-FILE ----------------------------------