• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "SegmentedString.h"
30 
31 namespace WebCore {
32 
33 // The InputStream is made up of a sequence of SegmentedStrings:
34 //
35 // [--current--][--next--][--next--] ... [--next--]
36 //            /\                         (also called m_last)
37 //            L_ current insertion point
38 //
39 // The current segmented string is stored in InputStream.  Each of the
40 // afterInsertionPoint buffers are stored in InsertionPointRecords on the
41 // stack.
42 //
43 // We remove characters from the "current" string in the InputStream.
44 // document.write() will add characters at the current insertion point,
45 // which appends them to the "current" string.
46 //
47 // m_last is a pointer to the last of the afterInsertionPoint strings.
48 // The network adds data at the end of the InputStream, which appends
49 // them to the "last" string.
50 class HTMLInputStream {
51     WTF_MAKE_NONCOPYABLE(HTMLInputStream);
52 public:
HTMLInputStream()53     HTMLInputStream()
54         : m_last(&m_first)
55     {
56     }
57 
appendToEnd(const SegmentedString & string)58     void appendToEnd(const SegmentedString& string)
59     {
60         m_last->append(string);
61     }
62 
insertAtCurrentInsertionPoint(const SegmentedString & string)63     void insertAtCurrentInsertionPoint(const SegmentedString& string)
64     {
65         m_first.append(string);
66     }
67 
hasInsertionPoint()68     bool hasInsertionPoint() const
69     {
70         return &m_first != m_last;
71     }
72 
markEndOfFile()73     void markEndOfFile()
74     {
75         // FIXME: This should use InputStreamPreprocessor::endOfFileMarker
76         // once InputStreamPreprocessor is split off into its own header.
77         static const UChar endOfFileMarker = 0;
78         m_last->append(SegmentedString(String(&endOfFileMarker, 1)));
79         m_last->close();
80     }
81 
haveSeenEndOfFile()82     bool haveSeenEndOfFile() const
83     {
84         return m_last->isClosed();
85     }
86 
current()87     SegmentedString& current() { return m_first; }
current()88     const SegmentedString& current() const { return m_first; }
89 
splitInto(SegmentedString & next)90     void splitInto(SegmentedString& next)
91     {
92         next = m_first;
93         m_first = SegmentedString();
94         if (m_last == &m_first) {
95             // We used to only have one SegmentedString in the InputStream
96             // but now we have two.  That means m_first is no longer also
97             // the m_last string, |next| is now the last one.
98             m_last = &next;
99         }
100     }
101 
mergeFrom(SegmentedString & next)102     void mergeFrom(SegmentedString& next)
103     {
104         m_first.append(next);
105         if (m_last == &next) {
106             // The string |next| used to be the last SegmentedString in
107             // the InputStream.  Now that it's been merged into m_first,
108             // that makes m_first the last one.
109             m_last = &m_first;
110         }
111         if (next.isClosed()) {
112             // We also need to merge the "closed" state from next to
113             // m_first.  Arguably, this work could be done in append().
114             m_first.close();
115         }
116     }
117 
118 private:
119     SegmentedString m_first;
120     SegmentedString* m_last;
121 };
122 
123 class InsertionPointRecord {
124     WTF_MAKE_NONCOPYABLE(InsertionPointRecord);
125 public:
InsertionPointRecord(HTMLInputStream & inputStream)126     explicit InsertionPointRecord(HTMLInputStream& inputStream)
127         : m_inputStream(&inputStream)
128     {
129         m_line = m_inputStream->current().currentLine();
130         m_column = m_inputStream->current().currentColumn();
131         m_inputStream->splitInto(m_next);
132         // We 'fork' current position and use it for the generated script part.
133         // This is a bit weird, because generated part does not have positions within an HTML document.
134         m_inputStream->current().setCurrentPosition(m_line, m_column, 0);
135     }
136 
~InsertionPointRecord()137     ~InsertionPointRecord()
138     {
139         // Some inserted text may have remained in input stream. E.g. if script has written "&amp" or "<table",
140         // it stays in buffer because it cannot be properly tokenized before we see next part.
141         int unparsedRemainderLength = m_inputStream->current().length();
142         m_inputStream->mergeFrom(m_next);
143         // We restore position for the character that goes right after unparsed remainder.
144         m_inputStream->current().setCurrentPosition(m_line, m_column, unparsedRemainderLength);
145     }
146 
147 private:
148     HTMLInputStream* m_inputStream;
149     SegmentedString m_next;
150     WTF::ZeroBasedNumber m_line;
151     WTF::ZeroBasedNumber m_column;
152 };
153 
154 }
155 
156 #endif
157