Thu, 15 Jan 2015 21:03:48 +0100
Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /*
7 * nsIContentSerializer implementation that can be used with an
8 * nsIDocumentEncoder to convert an XML DOM to an XML string that
9 * could be parsed into more or less the original DOM.
10 */
12 #ifndef nsXMLContentSerializer_h__
13 #define nsXMLContentSerializer_h__
15 #include "mozilla/Attributes.h"
16 #include "nsIContentSerializer.h"
17 #include "nsISupportsUtils.h"
18 #include "nsCOMPtr.h"
19 #include "nsTArray.h"
20 #include "nsString.h"
22 #define kIndentStr NS_LITERAL_STRING(" ")
23 #define kEndTag NS_LITERAL_STRING("</")
25 class nsIAtom;
26 class nsIDOMNode;
27 class nsINode;
29 class nsXMLContentSerializer : public nsIContentSerializer {
30 public:
31 nsXMLContentSerializer();
32 virtual ~nsXMLContentSerializer();
34 NS_DECL_ISUPPORTS
36 NS_IMETHOD Init(uint32_t flags, uint32_t aWrapColumn,
37 const char* aCharSet, bool aIsCopying,
38 bool aRewriteEncodingDeclaration) MOZ_OVERRIDE;
40 NS_IMETHOD AppendText(nsIContent* aText, int32_t aStartOffset,
41 int32_t aEndOffset, nsAString& aStr) MOZ_OVERRIDE;
43 NS_IMETHOD AppendCDATASection(nsIContent* aCDATASection,
44 int32_t aStartOffset, int32_t aEndOffset,
45 nsAString& aStr) MOZ_OVERRIDE;
47 NS_IMETHOD AppendProcessingInstruction(nsIContent* aPI,
48 int32_t aStartOffset,
49 int32_t aEndOffset,
50 nsAString& aStr) MOZ_OVERRIDE;
52 NS_IMETHOD AppendComment(nsIContent* aComment, int32_t aStartOffset,
53 int32_t aEndOffset, nsAString& aStr) MOZ_OVERRIDE;
55 NS_IMETHOD AppendDoctype(nsIContent *aDoctype,
56 nsAString& aStr) MOZ_OVERRIDE;
58 NS_IMETHOD AppendElementStart(mozilla::dom::Element* aElement,
59 mozilla::dom::Element* aOriginalElement,
60 nsAString& aStr) MOZ_OVERRIDE;
62 NS_IMETHOD AppendElementEnd(mozilla::dom::Element* aElement,
63 nsAString& aStr) MOZ_OVERRIDE;
65 NS_IMETHOD Flush(nsAString& aStr) MOZ_OVERRIDE { return NS_OK; }
67 NS_IMETHOD AppendDocumentStart(nsIDocument *aDocument,
68 nsAString& aStr) MOZ_OVERRIDE;
70 protected:
72 /**
73 * Appends a char16_t character and increments the column position
74 */
75 void AppendToString(const char16_t aChar,
76 nsAString& aOutputStr);
78 /**
79 * Appends a nsAString string and increments the column position
80 */
81 void AppendToString(const nsAString& aStr,
82 nsAString& aOutputStr);
84 /**
85 * Appends a string by replacing all line-endings
86 * by mLineBreak, except in the case of raw output.
87 * It increments the column position.
88 */
89 void AppendToStringConvertLF(const nsAString& aStr,
90 nsAString& aOutputStr);
92 /**
93 * Appends a string by wrapping it when necessary.
94 * It updates the column position.
95 */
96 void AppendToStringWrapped(const nsASingleFragmentString& aStr,
97 nsAString& aOutputStr);
99 /**
100 * Appends a string by formating and wrapping it when necessary
101 * It updates the column position.
102 */
103 void AppendToStringFormatedWrapped(const nsASingleFragmentString& aStr,
104 nsAString& aOutputStr);
106 // used by AppendToStringWrapped
107 void AppendWrapped_WhitespaceSequence(
108 nsASingleFragmentString::const_char_iterator &aPos,
109 const nsASingleFragmentString::const_char_iterator aEnd,
110 const nsASingleFragmentString::const_char_iterator aSequenceStart,
111 nsAString &aOutputStr);
113 // used by AppendToStringFormatedWrapped
114 void AppendFormatedWrapped_WhitespaceSequence(
115 nsASingleFragmentString::const_char_iterator &aPos,
116 const nsASingleFragmentString::const_char_iterator aEnd,
117 const nsASingleFragmentString::const_char_iterator aSequenceStart,
118 bool &aMayIgnoreStartOfLineWhitespaceSequence,
119 nsAString &aOutputStr);
121 // used by AppendToStringWrapped and AppendToStringFormatedWrapped
122 void AppendWrapped_NonWhitespaceSequence(
123 nsASingleFragmentString::const_char_iterator &aPos,
124 const nsASingleFragmentString::const_char_iterator aEnd,
125 const nsASingleFragmentString::const_char_iterator aSequenceStart,
126 bool &aMayIgnoreStartOfLineWhitespaceSequence,
127 bool &aSequenceStartAfterAWhiteSpace,
128 nsAString &aOutputStr);
130 /**
131 * add mLineBreak to the string
132 * It updates the column position and other flags.
133 */
134 void AppendNewLineToString(nsAString& aOutputStr);
137 /**
138 * Appends a string by translating entities
139 * It doesn't increment the column position
140 */
141 virtual void AppendAndTranslateEntities(const nsAString& aStr,
142 nsAString& aOutputStr);
144 /**
145 * retrieve the text content of the node and append it to the given string
146 * It doesn't increment the column position
147 */
148 nsresult AppendTextData(nsIContent* aNode,
149 int32_t aStartOffset,
150 int32_t aEndOffset,
151 nsAString& aStr,
152 bool aTranslateEntities);
154 virtual nsresult PushNameSpaceDecl(const nsAString& aPrefix,
155 const nsAString& aURI,
156 nsIContent* aOwner);
157 void PopNameSpaceDeclsFor(nsIContent* aOwner);
159 /**
160 * The problem that ConfirmPrefix fixes is that anyone can insert nodes
161 * through the DOM that have a namespace URI and a random or empty or
162 * previously existing prefix that's totally unrelated to the prefixes
163 * declared at that point through xmlns attributes. So what ConfirmPrefix
164 * does is ensure that we can map aPrefix to the namespace URI aURI (for
165 * example, that the prefix is not already mapped to some other namespace).
166 * aPrefix will be adjusted, if necessary, so the value of the prefix
167 * _after_ this call is what should be serialized.
168 * @param aPrefix the prefix that may need adjusting
169 * @param aURI the namespace URI we want aPrefix to point to
170 * @param aElement the element we're working with (needed for proper default
171 * namespace handling)
172 * @param aIsAttribute true if we're confirming a prefix for an attribute.
173 * @return true if we need to push the (prefix, uri) pair on the namespace
174 * stack (note that this can happen even if the prefix is
175 * empty).
176 */
177 bool ConfirmPrefix(nsAString& aPrefix,
178 const nsAString& aURI,
179 nsIContent* aElement,
180 bool aIsAttribute);
181 /**
182 * GenerateNewPrefix generates a new prefix and writes it to aPrefix
183 */
184 void GenerateNewPrefix(nsAString& aPrefix);
186 uint32_t ScanNamespaceDeclarations(nsIContent* aContent,
187 nsIContent *aOriginalElement,
188 const nsAString& aTagNamespaceURI);
190 virtual void SerializeAttributes(nsIContent* aContent,
191 nsIContent *aOriginalElement,
192 nsAString& aTagPrefix,
193 const nsAString& aTagNamespaceURI,
194 nsIAtom* aTagName,
195 nsAString& aStr,
196 uint32_t aSkipAttr,
197 bool aAddNSAttr);
199 void SerializeAttr(const nsAString& aPrefix,
200 const nsAString& aName,
201 const nsAString& aValue,
202 nsAString& aStr,
203 bool aDoEscapeEntities);
205 bool IsJavaScript(nsIContent * aContent,
206 nsIAtom* aAttrNameAtom,
207 int32_t aAttrNamespaceID,
208 const nsAString& aValueString);
210 /**
211 * This method can be redefined to check if the element can be serialized.
212 * It is called when the serialization of the start tag is asked
213 * (AppendElementStart)
214 * In this method you can also force the formating
215 * by setting aForceFormat to true.
216 * @return boolean true if the element can be output
217 */
218 virtual bool CheckElementStart(nsIContent * aContent,
219 bool & aForceFormat,
220 nsAString& aStr);
222 /**
223 * this method is responsible to finish the start tag,
224 * in particulary to append the "greater than" sign
225 */
226 virtual void AppendEndOfElementStart(nsIContent *aOriginalElement,
227 nsIAtom * aName,
228 int32_t aNamespaceID,
229 nsAString& aStr);
231 /**
232 * This method can be redefine to serialize additional things just after
233 * after the serialization ot the start tag.
234 * (called at the end of AppendElementStart)
235 */
236 virtual void AfterElementStart(nsIContent * aContent,
237 nsIContent *aOriginalElement,
238 nsAString& aStr) { };
240 /**
241 * This method can be redefined to check if the element can be serialized.
242 * It is called when the serialization of the end tag is asked
243 * (AppendElementEnd)
244 * In this method you can also force the formating
245 * by setting aForceFormat to true.
246 * @return boolean true if the element can be output
247 */
248 virtual bool CheckElementEnd(nsIContent * aContent,
249 bool & aForceFormat,
250 nsAString& aStr);
252 /**
253 * This method can be redefine to serialize additional things just after
254 * after the serialization ot the end tag.
255 * (called at the end of AppendElementStart)
256 */
257 virtual void AfterElementEnd(nsIContent * aContent,
258 nsAString& aStr) { };
260 /**
261 * Returns true if a line break should be inserted before an element open tag
262 */
263 virtual bool LineBreakBeforeOpen(int32_t aNamespaceID, nsIAtom* aName);
265 /**
266 * Returns true if a line break should be inserted after an element open tag
267 */
268 virtual bool LineBreakAfterOpen(int32_t aNamespaceID, nsIAtom* aName);
270 /**
271 * Returns true if a line break should be inserted after an element close tag
272 */
273 virtual bool LineBreakBeforeClose(int32_t aNamespaceID, nsIAtom* aName);
275 /**
276 * Returns true if a line break should be inserted after an element close tag
277 */
278 virtual bool LineBreakAfterClose(int32_t aNamespaceID, nsIAtom* aName);
280 /**
281 * add intendation. Call only in the case of formating and if the current
282 * position is at 0. It updates the column position.
283 */
284 void AppendIndentation(nsAString& aStr);
285 void IncrIndentation(nsIAtom* aName);
286 void DecrIndentation(nsIAtom* aName);
288 // Functions to check for newlines that needs to be added between nodes in
289 // the root of a document. See mAddNewlineForRootNode
290 void MaybeAddNewlineForRootNode(nsAString& aStr);
291 void MaybeFlagNewlineForRootNode(nsINode* aNode);
293 // Functions to check if we enter in or leave from a preformated content
294 virtual void MaybeEnterInPreContent(nsIContent* aNode);
295 virtual void MaybeLeaveFromPreContent(nsIContent* aNode);
297 int32_t mPrefixIndex;
299 struct NameSpaceDecl {
300 nsString mPrefix;
301 nsString mURI;
302 nsIContent* mOwner;
303 };
305 nsTArray<NameSpaceDecl> mNameSpaceStack;
307 // nsIDocumentEncoder flags
308 uint32_t mFlags;
310 // characters to use for line break
311 nsString mLineBreak;
313 // The charset that was passed to Init()
314 nsCString mCharset;
316 // current column position on the current line
317 uint32_t mColPos;
319 // true = pretty formating should be done (OutputFormated flag)
320 bool mDoFormat;
322 // true = no formatting,(OutputRaw flag)
323 // no newline convertion and no rewrap long lines even if OutputWrap is set.
324 bool mDoRaw;
326 // true = wrapping should be done (OutputWrap flag)
327 bool mDoWrap;
329 // number of maximum column in a line, in the wrap mode
330 uint32_t mMaxColumn;
332 // current indent value
333 nsString mIndent;
335 // this is the indentation level after the indentation reached
336 // the maximum length of indentation
337 int32_t mIndentOverflow;
339 // says if the indentation has been already added on the current line
340 bool mIsIndentationAddedOnCurrentLine;
342 // the string which is currently added is in an attribute
343 bool mInAttribute;
345 // true = a newline character should be added. It's only
346 // useful when serializing root nodes. see MaybeAddNewlineForRootNode and
347 // MaybeFlagNewlineForRootNode
348 bool mAddNewlineForRootNode;
350 // Indicates that a space will be added if and only if content is
351 // continued on the same line while serializing source. Otherwise,
352 // the newline character acts as the whitespace and no space is needed.
353 // used when mDoFormat = true
354 bool mAddSpace;
356 // says that if the next string to add contains a newline character at the
357 // begining, then this newline character should be ignored, because a
358 // such character has already been added into the output string
359 bool mMayIgnoreLineBreakSequence;
361 bool mBodyOnly;
362 int32_t mInBody;
364 // number of nested elements which have preformated content
365 int32_t mPreLevel;
366 };
368 nsresult
369 NS_NewXMLContentSerializer(nsIContentSerializer** aSerializer);
371 #endif