1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 #ifndef INCLUDED_OOX_MATHML_IMPORTUTILS_HXX
10 #define INCLUDED_OOX_MATHML_IMPORTUTILS_HXX
13 #include <string_view>
16 #include <com/sun/star/uno/Reference.hxx>
17 #include <oox/dllapi.h>
18 #include <oox/token/tokens.hxx>
19 #include <rtl/ustring.hxx>
20 #include <sal/types.h>
22 namespace com::sun::star
26 class XFastAttributeList
;
30 namespace oox::formulaimport
32 // used to differentiate between tags that opening or closing
33 const int TAG_OPENING
= 1 << 29;
34 const int TAG_CLOSING
= 1 << 30;
36 // you probably want to #define these to something shorter in the .cxx file,
37 // but they must be done as macros, otherwise they wouldn't be usable for case values,
38 // and macros cannot be namespaced
39 #define XML_STREAM_OPENING(token) (TAG_OPENING | token)
40 #define XML_STREAM_CLOSING(token) (TAG_CLOSING | token)
43 Class for storing a stream of xml tokens.
45 A part of an XML file can be parsed and stored in this stream, from which it can be read
46 as if parsed linearly. The purpose of this class is to allow simpler handling of XML
47 files, unlike the usual LO way of using callbacks, context handlers and similar needlessly
48 complicated stuff (YMMV).
50 The advantages of this approach is easy to read and debug code (as it is just functions
51 reading tokens one by one and calling other functions, compared to having to use callbacks
52 and temporary storage). The disadvantage is that the XML structure needs to be handled
55 Note that tag identifiers are simply int values and the API does not care besides matching
56 their values to XML stream contents and requiring that the values are not as high as TAG_OPENING.
57 Be prepared for the fact that some of the functions may throw exceptions if the input
58 stream does not match the required token (TBD).
60 The API tries to make the common idioms as simple as possible, see the following examples.
62 Parse <tagone attr="value"><tagtwo>text</tagtwo></tagone> , where tagtwo is optional:
64 XmlStream::Tag tagoneTag = stream.ensureOpeningTag( tagone );
65 if( attributeTag.hasAttribute( attr ))
66 ... = attributeTag.attribute( attr, defaultValueOfTheRightType );
67 if( XmlStream::Tag tagtwoTag = stream.checkOpeningTag( tagtwo ))
70 stream.ensureClosingTag( tagtwo );
72 stream.ensureClosingTag( tagone );
75 Parse an element that may contain several sub-elements of different types in random order:
77 stream.ensureOpeningTag( element );
78 while( !stream.atEnd() && stream.currentToken() != CLOSING( element ))
80 switch( stream.currentToken())
82 case OPENING( subelement1 ):
85 case OPENING( subelement2 ):
86 ... process subelement2;
89 stream.handleUnexpectedTag();
92 stream.ensureClosingTag( element );
95 If there may not be a zero number of sub-elements, use a helper bool variable or use a do-while loop.
97 Parse an element that may contain an unknown number of sub-elements of the same type:
99 stream.ensureOpeningTag( element );
100 while( !stream.atEnd() && stream.findTag( OPENING( subelement )))
104 stream.ensureClosingTag( element );
107 If there may not be a zero number of sub-elements, use a helper bool variable or use a do-while loop.
111 class OOX_DLLPUBLIC XmlStream
116 Structure representing a list of attributes.
118 // One could theoretically use oox::AttributeList, but that complains if the passed reference is empty,
119 // which would be complicated to avoid here. Also, parsers apparently reuse the same instance of XFastAttributeList,
120 // which means using oox::AttributeList would make them all point to the one instance.
121 struct OOX_DLLPUBLIC AttributeList
123 OUString
& operator[](int token
);
124 OUString
attribute(int token
, const OUString
& def
) const;
125 bool attribute(int token
, bool def
) const;
126 sal_Unicode
attribute(int token
, sal_Unicode def
) const;
127 // when adding more attribute() overloads, add also to XmlStream itself
129 std::map
<int, OUString
> attrs
;
132 Structure representing a tag, including its attributes and content text immediately following it.
134 struct OOX_DLLPUBLIC Tag
136 Tag(int token
= XML_TOKEN_INVALID
,
137 const css::uno::Reference
<css::xml::sax::XFastAttributeList
>& attributes
138 = css::uno::Reference
<css::xml::sax::XFastAttributeList
>());
139 Tag(int token
, AttributeList attribs
);
140 int token
; ///< tag type, or XML_TOKEN_INVALID
141 AttributeList attributes
;
144 This function returns value of the given attribute, or the passed default value if not found.
145 The type of the default value selects the return type (OUString here).
147 OUString
attribute(int token
, const OUString
& def
= OUString()) const;
151 bool attribute(int token
, bool def
) const;
155 sal_Unicode
attribute(int token
, sal_Unicode def
) const;
156 // when adding more attribute() overloads, add also to XmlStream::AttributeList and inline below
158 Converts to true if the tag has a valid token, false otherwise. Allows simple
159 usage in if(), for example 'if( XmlStream::Tag foo = stream.checkOpeningTag( footoken ))'.
161 operator bool() const;
164 @return true if current position is at the end of the XML stream
168 @return data about the current tag
170 Tag
currentTag() const;
172 @return the token for the current tag
174 int currentToken() const;
176 Moves position to the next tag.
178 void moveToNextTag();
180 Ensures that an opening tag with the given token is read. If the current tag does not match,
181 writes out a warning and tries to recover by skipping tags until found (or until the current element would end).
182 If found, the position in the stream is afterwards moved to the next tag.
183 @return the matching found opening tag, or empty tag if not found
185 Tag
ensureOpeningTag(int token
);
187 Tries to find an opening tag with the given token. Works similarly like ensureOpeningTag(),
188 but if a matching tag is not found, the position in the stream is not altered. The primary
189 use of this function is to check for optional elements.
190 @return the matching found opening tag, or empty tag if not found
192 Tag
checkOpeningTag(int token
);
194 Ensures that a closing tag with the given token is read. Like ensureOpeningTag(),
195 if not, writes out a warning and tries to recover by skipping tags until found (or until the current element would end).
196 If found, the position in the stream is afterwards moved to the next tag.
198 void ensureClosingTag(int token
);
200 Tries to find the given token, until either found (returns true) or end of current element.
201 Position in the stream is set to make the tag current (i.e. it will be the next one read).
203 bool findTag(int token
);
205 Handle the current (unexpected) tag.
207 void handleUnexpectedTag();
210 Tag
checkTag(int token
, bool optional
);
211 bool findTagInternal(int token
, bool silent
);
212 void skipElementInternal(int token
, bool silent
);
213 std::vector
<Tag
> tags
;
218 This class is used for creating XmlStream.
220 Simply use this class and then pass it as XmlStream to the consumer.
224 class OOX_DLLPUBLIC XmlStreamBuilder
: public XmlStream
227 void appendOpeningTag(int token
,
228 const css::uno::Reference
<css::xml::sax::XFastAttributeList
>& attributes
229 = css::uno::Reference
<css::xml::sax::XFastAttributeList
>());
230 void appendOpeningTag(int token
, const AttributeList
& attribs
);
231 void appendClosingTag(int token
);
232 // appends the characters after the last appended token
233 void appendCharacters(std::u16string_view characters
);
236 inline OUString
XmlStream::Tag::attribute(int t
, const OUString
& def
) const
238 return attributes
.attribute(t
, def
);
241 inline bool XmlStream::Tag::attribute(int t
, bool def
) const
243 return attributes
.attribute(t
, def
);
246 inline sal_Unicode
XmlStream::Tag::attribute(int t
, sal_Unicode def
) const
248 return attributes
.attribute(t
, def
);
255 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */