Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / html / parser / HTMLInputStream.h
1 /*
2  * Copyright (C) 2010 Google, Inc. All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #ifndef HTMLInputStream_h
27 #define HTMLInputStream_h
28
29 #include "core/html/parser/InputStreamPreprocessor.h"
30 #include "platform/text/SegmentedString.h"
31
32 namespace blink {
33
34 // The InputStream is made up of a sequence of SegmentedStrings:
35 //
36 // [--current--][--next--][--next--] ... [--next--]
37 //            /\                         (also called m_last)
38 //            L_ current insertion point
39 //
40 // The current segmented string is stored in InputStream.  Each of the
41 // afterInsertionPoint buffers are stored in InsertionPointRecords on the
42 // stack.
43 //
44 // We remove characters from the "current" string in the InputStream.
45 // document.write() will add characters at the current insertion point,
46 // which appends them to the "current" string.
47 //
48 // m_last is a pointer to the last of the afterInsertionPoint strings.
49 // The network adds data at the end of the InputStream, which appends
50 // them to the "last" string.
51 class HTMLInputStream {
52     WTF_MAKE_NONCOPYABLE(HTMLInputStream);
53 public:
54     HTMLInputStream()
55         : m_last(&m_first)
56     {
57     }
58
59     void appendToEnd(const SegmentedString& string)
60     {
61         m_last->append(string);
62     }
63
64     void insertAtCurrentInsertionPoint(const SegmentedString& string)
65     {
66         m_first.append(string);
67     }
68
69     bool hasInsertionPoint() const
70     {
71         return &m_first != m_last;
72     }
73
74     void markEndOfFile()
75     {
76         m_last->append(SegmentedString(String(&kEndOfFileMarker, 1)));
77         m_last->close();
78     }
79
80     void closeWithoutMarkingEndOfFile()
81     {
82         m_last->close();
83     }
84
85     bool haveSeenEndOfFile() const
86     {
87         return m_last->isClosed();
88     }
89
90     SegmentedString& current() { return m_first; }
91     const SegmentedString& current() const { return m_first; }
92
93     void splitInto(SegmentedString& next)
94     {
95         next = m_first;
96         m_first = SegmentedString();
97         if (m_last == &m_first) {
98             // We used to only have one SegmentedString in the InputStream
99             // but now we have two.  That means m_first is no longer also
100             // the m_last string, |next| is now the last one.
101             m_last = &next;
102         }
103     }
104
105     void mergeFrom(SegmentedString& next)
106     {
107         m_first.append(next);
108         if (m_last == &next) {
109             // The string |next| used to be the last SegmentedString in
110             // the InputStream.  Now that it's been merged into m_first,
111             // that makes m_first the last one.
112             m_last = &m_first;
113         }
114         if (next.isClosed()) {
115             // We also need to merge the "closed" state from next to
116             // m_first.  Arguably, this work could be done in append().
117             m_first.close();
118         }
119     }
120
121 private:
122     SegmentedString m_first;
123     SegmentedString* m_last;
124 };
125
126 class InsertionPointRecord {
127     WTF_MAKE_NONCOPYABLE(InsertionPointRecord);
128 public:
129     explicit InsertionPointRecord(HTMLInputStream& inputStream)
130         : m_inputStream(&inputStream)
131     {
132         m_line = m_inputStream->current().currentLine();
133         m_column = m_inputStream->current().currentColumn();
134         m_inputStream->splitInto(m_next);
135         // We 'fork' current position and use it for the generated script part.
136         // This is a bit weird, because generated part does not have positions within an HTML document.
137         m_inputStream->current().setCurrentPosition(m_line, m_column, 0);
138     }
139
140     ~InsertionPointRecord()
141     {
142         // Some inserted text may have remained in input stream. E.g. if script has written "&amp" or "<table",
143         // it stays in buffer because it cannot be properly tokenized before we see next part.
144         int unparsedRemainderLength = m_inputStream->current().length();
145         m_inputStream->mergeFrom(m_next);
146         // We restore position for the character that goes right after unparsed remainder.
147         m_inputStream->current().setCurrentPosition(m_line, m_column, unparsedRemainderLength);
148     }
149
150 private:
151     HTMLInputStream* m_inputStream;
152     SegmentedString m_next;
153     OrdinalNumber m_line;
154     OrdinalNumber m_column;
155 };
156
157 }
158
159 #endif