/*
* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
* 2018, 2019
* Jonathan Schleifer <js@heap.zone>
*
* All rights reserved.
*
* This file is part of ObjFW. It may be distributed under the terms of the
* Q Public License 1.0, which can be found in the file LICENSE.QPL included in
* the packaging of this file.
*
* Alternatively, it may be distributed under the terms of the GNU General
* Public License, either version 2 or 3, which can be found in the file
* LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
* file.
*/
#import "OFObject.h"
#import "OFString.h"
#import "OFXMLAttribute.h"
OF_ASSUME_NONNULL_BEGIN
@class OFArray OF_GENERIC(ObjectType);
@class OFMutableData;
@class OFMutableArray OF_GENERIC(ObjectType);
@class OFMutableDictionary OF_GENERIC(KeyType, ObjectType);
@class OFStream;
@class OFXMLParser;
/*!
* @protocol OFXMLParserDelegate OFXMLParser.h ObjFW/OFXMLParser.h
*
* @brief A protocol that needs to be implemented by delegates for OFXMLParser.
*/
@protocol OFXMLParserDelegate <OFObject>
@optional
/*!
* @brief This callback is called when the XML parser found processing
* instructions.
*
* @param parser The parser which found processing instructions
* @param processingInstructions The processing instructions
*/
- (void)parser: (OFXMLParser *)parser
foundProcessingInstructions: (OFString *)processingInstructions;
/*!
* @brief This callback is called when the XML parser found the start of a new
* tag.
*
* @param parser The parser which found a new tag
* @param name The name of the tag which just started
* @param prefix The prefix of the tag which just started or `nil`
* @param ns The namespace of the tag which just started or `nil`
* @param attributes The attributes included in the tag which just started or
* `nil`
*/
- (void)parser: (OFXMLParser *)parser
didStartElement: (OFString *)name
prefix: (nullable OFString *)prefix
namespace: (nullable OFString *)ns
attributes: (nullable OFArray OF_GENERIC(OFXMLAttribute *) *)attributes;
/*!
* @brief This callback is called when the XML parser found the end of a tag.
*
* @param parser The parser which found the end of a tag
* @param name The name of the tag which just ended
* @param prefix The prefix of the tag which just ended or `nil`
* @param ns The namespace of the tag which just ended or `nil`
*/
- (void)parser: (OFXMLParser *)parser
didEndElement: (OFString *)name
prefix: (nullable OFString *)prefix
namespace: (nullable OFString *)ns;
/*!
* @brief This callback is called when the XML parser found characters.
*
* In case there are comments or CDATA, it is possible that this callback is
* called multiple times in a row.
*
* @param parser The parser which found a string
* @param characters The characters the XML parser found
*/
- (void)parser: (OFXMLParser *)parser
foundCharacters: (OFString *)characters;
/*!
* @brief This callback is called when the XML parser found CDATA.
*
* @param parser The parser which found a string
* @param CDATA The CDATA the XML parser found
*/
- (void)parser: (OFXMLParser *)parser
foundCDATA: (OFString *)CDATA;
/*!
* @brief This callback is called when the XML parser found a comment.
*
* @param parser The parser which found a comment
* @param comment The comment the XML parser found
*/
- (void)parser: (OFXMLParser *)parser
foundComment: (OFString *)comment;
/*!
* @brief This callback is called when the XML parser found an entity it
* doesn't know.
*
* The callback is supposed to return a substitution for the entity or `nil` if
* it is not known to the callback as well, in which case an exception will be
* risen.
*
* @param parser The parser which found an unknown entity
* @param entity The name of the entity the XML parser didn't know
* @return A substitution for the entity or `nil`
*/
- (nullable OFString *)parser: (OFXMLParser *)parser
foundUnknownEntityNamed: (OFString *)entity;
@end
/*!
* @class OFXMLParser OFXMLParser.h ObjFW/OFXMLParser.h
*
* @brief An event-based XML parser.
*
* OFXMLParser is an event-based XML parser which calls the delegate's callbacks
* as soon as it finds something, thus suitable for streams as well.
*/
@interface OFXMLParser: OFObject
{
id <OFXMLParserDelegate> _Nullable _delegate;
enum of_xml_parser_state {
OF_XMLPARSER_IN_BYTE_ORDER_MARK,
OF_XMLPARSER_OUTSIDE_TAG,
OF_XMLPARSER_TAG_OPENED,
OF_XMLPARSER_IN_PROCESSING_INSTRUCTIONS,
OF_XMLPARSER_IN_TAG_NAME,
OF_XMLPARSER_IN_CLOSE_TAG_NAME,
OF_XMLPARSER_IN_TAG,
OF_XMLPARSER_IN_ATTRIBUTE_NAME,
OF_XMLPARSER_EXPECT_ATTRIBUTE_EQUAL_SIGN,
OF_XMLPARSER_EXPECT_ATTRIBUTE_DELIMITER,
OF_XMLPARSER_IN_ATTRIBUTE_VALUE,
OF_XMLPARSER_EXPECT_TAG_CLOSE,
OF_XMLPARSER_EXPECT_SPACE_OR_TAG_CLOSE,
OF_XMLPARSER_IN_EXCLAMATION_MARK,
OF_XMLPARSER_IN_CDATA_OPENING,
OF_XMLPARSER_IN_CDATA,
OF_XMLPARSER_IN_COMMENT_OPENING,
OF_XMLPARSER_IN_COMMENT_1,
OF_XMLPARSER_IN_COMMENT_2,
OF_XMLPARSER_IN_DOCTYPE,
OF_XMLPARSER_NUM_STATES
} _state;
size_t _i, _last;
const char *_Nullable _data;
OFMutableData *_buffer;
OFString *_Nullable _name, *_Nullable _prefix;
OFMutableArray
OF_GENERIC(OFMutableDictionary OF_GENERIC(OFString *, OFString *) *)
*_namespaces;
OFMutableArray OF_GENERIC(OFXMLAttribute *) *_attributes;
OFString *_Nullable _attributeName, *_Nullable _attributePrefix;
char _delimiter;
OFMutableArray OF_GENERIC(OFString *) *_previous;
size_t _level;
bool _acceptProlog;
size_t _lineNumber;
bool _lastCarriageReturn, _finishedParsing;
of_string_encoding_t _encoding;
size_t _depthLimit;
}
/*!
* @brief The delegate that is used by the XML parser.
*/
@property OF_NULLABLE_PROPERTY (assign, nonatomic)
id <OFXMLParserDelegate> delegate;
/*!
* @brief The current line number.
*/
@property (readonly, nonatomic) size_t lineNumber;
/*!
* @brief Whether the XML parser has finished parsing.
*/
@property (readonly, nonatomic) bool hasFinishedParsing;
/*!
* @brief The depth limit for the XML parser.
*
* If the depth limit is exceeded, an OFMalformedXMLException is thrown.
*
* The default is 32. 0 means unlimited (insecure!).
*/
@property (nonatomic) size_t depthLimit;
/*!
* @brief Creates a new XML parser.
*
* @return A new, autoreleased OFXMLParser
*/
+ (instancetype)parser;
/*!
* @brief Parses the specified buffer with the specified size.
*
* @param buffer The buffer to parse
* @param length The length of the buffer
*/
- (void)parseBuffer: (const char *)buffer
length: (size_t)length;
/*!
* @brief Parses the specified string.
*
* @param string The string to parse
*/
- (void)parseString: (OFString *)string;
/*!
* @brief Parses the specified stream.
*
* @param stream The stream to parse
*/
- (void)parseStream: (OFStream *)stream;
#ifdef OF_HAVE_FILES
/*!
* @brief Parses the specified file.
*
* @param path The path to the file to parse
*/
- (void)parseFile: (OFString *)path;
#endif
@end
OF_ASSUME_NONNULL_END