Quick Links: |
#include <balxml_minireader.h>
Classes | |
struct | Node |
Public Types | |
enum | NodeType { e_NODE_TYPE_NONE = 0, e_NODE_TYPE_ELEMENT = 1, e_NODE_TYPE_TEXT = 2, e_NODE_TYPE_CDATA = 3, e_NODE_TYPE_ENTITY_REFERENCE = 4, e_NODE_TYPE_ENTITY = 5, e_NODE_TYPE_PROCESSING_INSTRUCTION = 6, e_NODE_TYPE_COMMENT = 7, e_NODE_TYPE_DOCUMENT = 8, e_NODE_TYPE_DOCUMENT_TYPE = 9, e_NODE_TYPE_DOCUMENT_FRAGMENT = 10, e_NODE_TYPE_NOTATION = 11, e_NODE_TYPE_WHITESPACE = 12, e_NODE_TYPE_SIGNIFICANT_WHITESPACE = 13, e_NODE_TYPE_END_ELEMENT = 14, e_NODE_TYPE_END_ENTITY = 15, e_NODE_TYPE_XML_DECLARATION = 16, BAEXML_NODE_TYPE_NONE = e_NODE_TYPE_NONE, BAEXML_NODE_TYPE_ELEMENT = e_NODE_TYPE_ELEMENT, BAEXML_NODE_TYPE_TEXT = e_NODE_TYPE_TEXT, BAEXML_NODE_TYPE_CDATA = e_NODE_TYPE_CDATA, BAEXML_NODE_TYPE_ENTITY_REFERENCE = e_NODE_TYPE_ENTITY_REFERENCE, BAEXML_NODE_TYPE_ENTITY = e_NODE_TYPE_ENTITY, BAEXML_NODE_TYPE_PROCESSING_INSTRUCTION, BAEXML_NODE_TYPE_COMMENT = e_NODE_TYPE_COMMENT, BAEXML_NODE_TYPE_DOCUMENT = e_NODE_TYPE_DOCUMENT, BAEXML_NODE_TYPE_DOCUMENT_TYPE = e_NODE_TYPE_DOCUMENT_TYPE, BAEXML_NODE_TYPE_DOCUMENT_FRAGMENT = e_NODE_TYPE_DOCUMENT_FRAGMENT, BAEXML_NODE_TYPE_NOTATION = e_NODE_TYPE_NOTATION, BAEXML_NODE_TYPE_WHITESPACE = e_NODE_TYPE_WHITESPACE, BAEXML_NODE_TYPE_SIGNIFICANT_WHITESPACE, BAEXML_NODE_TYPE_END_ELEMENT = e_NODE_TYPE_END_ELEMENT, BAEXML_NODE_TYPE_END_ENTITY = e_NODE_TYPE_END_ENTITY, BAEXML_NODE_TYPE_XML_DECLARATION = e_NODE_TYPE_XML_DECLARATION, NODE_TYPE_NONE = e_NODE_TYPE_NONE, NODE_TYPE_ELEMENT = e_NODE_TYPE_ELEMENT, NODE_TYPE_TEXT = e_NODE_TYPE_TEXT, NODE_TYPE_CDATA = e_NODE_TYPE_CDATA, NODE_TYPE_ENTITY_REFERENCE = e_NODE_TYPE_ENTITY_REFERENCE, NODE_TYPE_ENTITY = e_NODE_TYPE_ENTITY, NODE_TYPE_PROCESSING_INSTRUCTION, NODE_TYPE_COMMENT = e_NODE_TYPE_COMMENT, NODE_TYPE_DOCUMENT = e_NODE_TYPE_DOCUMENT, NODE_TYPE_DOCUMENT_TYPE = e_NODE_TYPE_DOCUMENT_TYPE, NODE_TYPE_DOCUMENT_FRAGMENT = e_NODE_TYPE_DOCUMENT_FRAGMENT, NODE_TYPE_NOTATION = e_NODE_TYPE_NOTATION, NODE_TYPE_WHITESPACE = e_NODE_TYPE_WHITESPACE, NODE_TYPE_SIGNIFICANT_WHITESPACE, NODE_TYPE_END_ELEMENT = e_NODE_TYPE_END_ELEMENT, NODE_TYPE_END_ENTITY = e_NODE_TYPE_END_ENTITY, NODE_TYPE_XML_DECLARATION = e_NODE_TYPE_XML_DECLARATION } |
typedef bslma::ManagedPtr < bsl::streambuf > | StreamBufPtr |
typedef bsl::function < StreamBufPtr(const char *location, const char *namespaceUri) | XmlResolverFunctor ) |
Public Member Functions | |
virtual | ~MiniReader () |
MiniReader (bslma::Allocator *basicAllocator=0) | |
MiniReader (int bufSize, bslma::Allocator *basicAllocator=0) | |
virtual void | setPrefixStack (PrefixStack *prefixes) |
virtual void | setResolver (XmlResolverFunctor resolver) |
virtual int | open (const char *filename, const char *encoding=0) |
virtual int | open (const char *buffer, bsl::size_t size, const char *url=0, const char *encoding=0) |
virtual int | open (bsl::streambuf *stream, const char *url=0, const char *encoding=0) |
virtual void | close () |
virtual int | advanceToEndNode () |
virtual int | advanceToEndNodeRaw () |
virtual int | advanceToEndNodeRawBare () |
virtual int | advanceToNextNode () |
virtual int | lookupAttribute (ElementAttribute *attribute, int index) const |
virtual int | lookupAttribute (ElementAttribute *attribute, const char *qname) const |
virtual int | lookupAttribute (ElementAttribute *attribute, const char *localName, const char *namespaceUri) const |
virtual int | lookupAttribute (ElementAttribute *attribute, const char *localName, int namespaceId) const |
virtual void | setOptions (unsigned int flags) |
virtual const char * | documentEncoding () const |
virtual XmlResolverFunctor | resolver () const |
virtual bool | isOpen () const |
virtual const ErrorInfo & | errorInfo () const |
virtual int | getLineNumber () const |
virtual int | getColumnNumber () const |
virtual PrefixStack * | prefixStack () const |
virtual NodeType | nodeType () const |
virtual const char * | nodeName () const |
virtual const char * | nodeLocalName () const |
virtual const char * | nodePrefix () const |
virtual int | nodeNamespaceId () const |
virtual const char * | nodeNamespaceUri () const |
virtual const char * | nodeBaseUri () const |
virtual bool | nodeHasValue () const |
virtual const char * | nodeValue () const |
virtual int | nodeDepth () const |
virtual int | numAttributes () const |
virtual bool | isEmptyElement () const |
virtual unsigned int | options () const |
int | getCurrentPosition () const |
int | nodeStartPosition () const |
int | nodeEndPosition () const |
void | dumpNode (bsl::ostream &os) const |
bool | isFatalError () const |
bool | isError () const |
bool | isWarning () const |
Static Public Member Functions | |
static const char * | nodeTypeAsString (NodeType nodeType) |
Friends | |
struct | Node |
This class
provides a concrete and efficient implementation of the Reader
protocol.
See Component balxml_minireader
typedef bslma::ManagedPtr<bsl::streambuf> balxml::Reader::StreamBufPtr [inherited] |
typedef bsl::function<StreamBufPtr(const char *location, const char *namespaceUri) balxml::Reader::XmlResolverFunctor) [inherited] |
Type for a user supplied functor that finds and opens an external resource for the specified location
and/or namespaceUri
and returns that resource as a managed pointer to a stream. The location
argument specifies the location of the external resource and is typically a filename or a URI, depending on the context. The namespaceUri
argument always refers to the XML namespace of the entity to be resolved. A conforming functor returns an empty managed pointer if it cannot resolve the resource. For example, the reader may use a resolver to open an external entity, even if the reader does not do validation (see definition of <!ENTITY>
in the XML standard). Note that either argument can be NULL in situations where its value is not needed or can be computed from the other argument.
enum balxml::Reader::NodeType [inherited] |
Node types, returned by nodeType
method, which represent a XML syntactic construct within a document. Note: Not every implementation of Reader
will distinguish among all of the node types.
virtual balxml::MiniReader::~MiniReader | ( | ) | [virtual] |
balxml::MiniReader::MiniReader | ( | bslma::Allocator * | basicAllocator = 0 |
) | [explicit] |
balxml::MiniReader::MiniReader | ( | int | bufSize, | |
bslma::Allocator * | basicAllocator = 0 | |||
) | [explicit] |
Construct a reader with the optionally specified bufSize
. The instantiated MiniReader will utilize a memory buffer of bufSize
while reading the input document. Optionally specify a basicAllocator
used to supply memory. If basicAllocator
is 0, the currently installed default allocator is used. Note that bufSize
is a hint, which may be modified or ignored if it is not within a "sane" range.
virtual void balxml::MiniReader::setPrefixStack | ( | PrefixStack * | prefixes | ) | [virtual] |
Set the prefix stack to the stack at the specified prefixes
address or disable prefix stack support if prefixes
== 0. 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
.
Implements balxml::Reader.
virtual void balxml::MiniReader::setResolver | ( | XmlResolverFunctor | resolver | ) | [virtual] |
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
.
Implements balxml::Reader.
virtual int balxml::MiniReader::open | ( | const char * | filename, | |
const char * | encoding = 0 | |||
) | [virtual] |
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.
Implements balxml::Reader.
virtual int balxml::MiniReader::open | ( | const char * | buffer, | |
bsl::size_t | size, | |||
const char * | url = 0 , |
|||
const char * | encoding = 0 | |||
) | [virtual] |
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 0 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.
Implements balxml::Reader.
virtual int balxml::MiniReader::open | ( | bsl::streambuf * | stream, | |
const char * | url = 0 , |
|||
const char * | encoding = 0 | |||
) | [virtual] |
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.
Implements balxml::Reader.
virtual void balxml::MiniReader::close | ( | ) | [virtual] |
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.
Implements balxml::Reader.
virtual int balxml::MiniReader::advanceToEndNode | ( | ) | [virtual] |
Skip all the sub elements of the current node and position the reader on its corresponding end node. While skipping ensure that the elements being skipped are well-formed and do not contain any parsing errors. Return 0 on successful skip, and a negative number otherwise (error). The behavior is undefined unless baexml_Reader::BAEXML_NODE_TYPE_ELEMENT == node.type()
. Note that each call to advanceToEndNode
invalidates strings and data structures returned when Reader
accessors were called for the "prior node". E.g., the pointer returned from nodeName
for this node won't be valid once advanceToEndNode
is called. Note that this method leaves the reader pointing to an end node, so calling one of the advanceToEndNode
immediately after will not advance the reader further (first call advanceToNextNode
before calling the advanceToEndNode
function again).
virtual int balxml::MiniReader::advanceToEndNodeRaw | ( | ) | [virtual] |
Skip all the sub elements of the current node and position the reader on its corresponding end node, and (unlike advanceToNextNode
) perform no checks to ensure that the elements being skipped are well-formed and that they do not contain any parsing errors. Return 0 on successful skip, and a negative number otherwise (error). The behavior is undefined unless baexml_Reader::BAEXML_NODE_TYPE_ELEMENT == node.type()
. Note that each call to advanceToEndNodeRaw
invalidates strings and data structures returned when Reader
accessors were called for the "prior node". E.g., the pointer returned from nodeName
for this node will not be valid once advanceToEndNodeRaw
is called. Note that this method leaves the reader pointing to an end node, so calling one of the advanceToEndNodeRaw
immediately after will not advance the reader further (first call advanceToNextNode
before calling the advanceToEndNodeRaw
function again).
virtual int balxml::MiniReader::advanceToEndNodeRawBare | ( | ) | [virtual] |
Skip all the sub elements of the current node and position the reader on its corresponding end node, and (unlike advanceToNextNode
) perform no checks to ensure that the elements being skipped are well-formed and that they do not contain any parsing errors. Unlike advanceToEndNodeRaw
this method does not expect (allow) comments or CDATA nodes in the input XML, in other words it is expecting "bare" XML. Return 0 on successful skip, and a negative number otherwise (error). The behavior is undefined unless baexml_Reader::BAEXML_NODE_TYPE_ELEMENT == node.type()
. The behavior is also undefined if the input XML contains comment or CDATA nodes. Note that each call to advanceToEndNodeRawBare
invalidates strings and data structures returned when Reader
accessors were called for the "prior node". E.g., the pointer returned from nodeName
for this node will not be valid once advanceToEndNodeRawBare
is called. Note that this method leaves the reader pointing to an end node, so calling one of the advanceToEndNodeRawBare
immediately after will not advance the reader further (first call advanceToNextNode
before calling the advanceToEndNodeRawBare
function again).
virtual int balxml::MiniReader::advanceToNextNode | ( | ) | [virtual] |
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 were called 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.
Implements balxml::Reader.
virtual int balxml::MiniReader::lookupAttribute | ( | ElementAttribute * | attribute, | |
int | index | |||
) | const [virtual] |
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.
Implements balxml::Reader.
virtual int balxml::MiniReader::lookupAttribute | ( | ElementAttribute * | attribute, | |
const char * | qname | |||
) | const [virtual] |
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.
Implements balxml::Reader.
virtual int balxml::MiniReader::lookupAttribute | ( | ElementAttribute * | attribute, | |
const char * | localName, | |||
const char * | namespaceUri | |||
) | const [virtual] |
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.
Implements balxml::Reader.
virtual int balxml::MiniReader::lookupAttribute | ( | ElementAttribute * | attribute, | |
const char * | localName, | |||
int | namespaceId | |||
) | const [virtual] |
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.
Implements balxml::Reader.
virtual void balxml::MiniReader::setOptions | ( | unsigned int | flags | ) | [virtual] |
Set the options 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
.
Implements balxml::Reader.
virtual const char* balxml::MiniReader::documentEncoding | ( | ) | const [virtual] |
Return the document encoding or NULL on error. The returned pointer 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.
Implements balxml::Reader.
virtual XmlResolverFunctor balxml::MiniReader::resolver | ( | ) | const [virtual] |
Return the external XML resource resolver.
Implements balxml::Reader.
virtual bool balxml::MiniReader::isOpen | ( | ) | const [virtual] |
Return true if open
was called successfully and close
has not yet been called and false otherwise.
Implements balxml::Reader.
virtual const ErrorInfo& balxml::MiniReader::errorInfo | ( | ) | const [virtual] |
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.
Implements balxml::Reader.
virtual int balxml::MiniReader::getLineNumber | ( | ) | const [virtual] |
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 provide to open
. Return 0 if not available. Note that a derived-class implementation is not required to count lines and may just return 0.
Implements balxml::Reader.
virtual int balxml::MiniReader::getColumnNumber | ( | ) | const [virtual] |
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.
Implements balxml::Reader.
virtual PrefixStack* balxml::MiniReader::prefixStack | ( | ) | const [virtual] |
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
.
Implements balxml::Reader.
virtual NodeType balxml::MiniReader::nodeType | ( | ) | const [virtual] |
Return the node type of the current node if the reader isOpen
and has not encounter an error and Reader::NONE
otherwise.
Implements balxml::Reader.
virtual const char* balxml::MiniReader::nodeName | ( | ) | const [virtual] |
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.
Implements balxml::Reader.
virtual const char* balxml::MiniReader::nodeLocalName | ( | ) | const [virtual] |
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.
Implements balxml::Reader.
virtual const char* balxml::MiniReader::nodePrefix | ( | ) | const [virtual] |
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.
Implements balxml::Reader.
virtual int balxml::MiniReader::nodeNamespaceId | ( | ) | const [virtual] |
Return the namespace ID of the current node if the current node has a namespace id and a negative number otherwise.
Implements balxml::Reader.
virtual const char* balxml::MiniReader::nodeNamespaceUri | ( | ) | const [virtual] |
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.
Implements balxml::Reader.
virtual const char* balxml::MiniReader::nodeBaseUri | ( | ) | const [virtual] |
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.
Implements balxml::Reader.
virtual bool balxml::MiniReader::nodeHasValue | ( | ) | const [virtual] |
Return true if the current node has a value and false otherwise.
Implements balxml::Reader.
virtual const char* balxml::MiniReader::nodeValue | ( | ) | const [virtual] |
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.
Implements balxml::Reader.
virtual int balxml::MiniReader::nodeDepth | ( | ) | const [virtual] |
Return the nesting depth of the current node in the XML document. The root node has depth 0.
Implements balxml::Reader.
virtual int balxml::MiniReader::numAttributes | ( | ) | const [virtual] |
Return the number of attributes for the current node if that node has attributes and 0 otherwise.
Implements balxml::Reader.
virtual bool balxml::MiniReader::isEmptyElement | ( | ) | const [virtual] |
Return true if the current node is an element (i.e., node type is NODE_TYPE_ELEMENT
) that ends with />
; and false otherwise. Note that <a/>
will be considered empty but <a></a>
will not.
Implements balxml::Reader.
virtual unsigned int balxml::MiniReader::options | ( | ) | const [virtual] |
Return the option flags.
Implements balxml::Reader.
int balxml::MiniReader::getCurrentPosition | ( | ) | const |
Return the current scanner position as offset from the beginning of document.
int balxml::MiniReader::nodeStartPosition | ( | ) | const |
Return the byte position within the document corresponding to the first byte of the current node.
int balxml::MiniReader::nodeEndPosition | ( | ) | const |
Return the byte position within the document corresponding to the byte following after the last byte of the current node.
static const char* balxml::Reader::nodeTypeAsString | ( | NodeType | nodeType | ) | [static, inherited] |
Return a string representation for the specified nodeType
code or "(* UNKNOWN NODE TYPE *)" if nodeType
is not one of the values enumerated in NodeType
.
void balxml::Reader::dumpNode | ( | bsl::ostream & | os | ) | const [inherited] |
Print the information about the current node to the specified output os
stream.
bool balxml::Reader::isFatalError | ( | ) | const [inherited] |
Return true
if the derived object encountered a fatal error. This method is equivalent to a call to errorInfo().isFatalError();
bool balxml::Reader::isError | ( | ) | const [inherited] |
Return true
if the derived object encountered a error. This method is equivalent to a call to errorInfo().isError();
bool balxml::Reader::isWarning | ( | ) | const [inherited] |
Return true
if the derived object encountered a warning. This method is equivalent to a call to errorInfo().isWarning();
friend struct Node [friend] |