| /* |
| * Copyright (C) 2010 Google, Inc. All Rights Reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_HTML_INPUT_STREAM_H_ |
| #define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_HTML_INPUT_STREAM_H_ |
| |
| #include "base/macros.h" |
| #include "third_party/blink/renderer/core/html/parser/input_stream_preprocessor.h" |
| #include "third_party/blink/renderer/platform/text/segmented_string.h" |
| #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" |
| |
| namespace blink { |
| |
| // The InputStream is made up of a sequence of SegmentedStrings: |
| // |
| // [--current--][--next--][--next--] ... [--next--] |
| // /\ (also called last_) |
| // L_ current insertion point |
| // |
| // The current segmented string is stored in InputStream. Each of the |
| // afterInsertionPoint buffers are stored in InsertionPointRecords on the stack. |
| // |
| // We remove characters from the "current" string in the InputStream. |
| // document.write() will add characters at the current insertion point, which |
| // appends them to the "current" string. |
| // |
| // last_ is a pointer to the last of the afterInsertionPoint strings. The |
| // network adds data at the end of the InputStream, which appends them to the |
| // "last" string. |
| class HTMLInputStream { |
| DISALLOW_NEW(); |
| |
| public: |
| HTMLInputStream() : last_(&first_) {} |
| |
| void AppendToEnd(const SegmentedString& string) { last_->Append(string); } |
| |
| void InsertAtCurrentInsertionPoint(const SegmentedString& string) { |
| first_.Append(string); |
| } |
| |
| bool HasInsertionPoint() const { return &first_ != last_; } |
| |
| void MarkEndOfFile() { |
| last_->Append(SegmentedString(String(&kEndOfFileMarker, 1))); |
| last_->Close(); |
| } |
| |
| void CloseWithoutMarkingEndOfFile() { last_->Close(); } |
| |
| bool HaveSeenEndOfFile() const { return last_->IsClosed(); } |
| |
| SegmentedString& Current() { return first_; } |
| const SegmentedString& Current() const { return first_; } |
| |
| void SplitInto(SegmentedString& next) { |
| next = first_; |
| first_ = SegmentedString(); |
| if (last_ == &first_) { |
| // We used to only have one SegmentedString in the InputStream but now we |
| // have two. That means first_ is no longer also the last_ string, |
| // |next| is now the last one. |
| last_ = &next; |
| } |
| } |
| |
| void MergeFrom(SegmentedString& next) { |
| first_.Append(next); |
| if (last_ == &next) { |
| // The string |next| used to be the last SegmentedString in |
| // the InputStream. Now that it's been merged into first_, |
| // that makes first_ the last one. |
| last_ = &first_; |
| } |
| if (next.IsClosed()) { |
| // We also need to merge the "closed" state from next to first_. |
| // Arguably, this work could be done in Append(). |
| first_.Close(); |
| } |
| } |
| |
| private: |
| SegmentedString first_; |
| SegmentedString* last_; |
| |
| DISALLOW_COPY_AND_ASSIGN(HTMLInputStream); |
| }; |
| |
| class InsertionPointRecord { |
| STACK_ALLOCATED(); |
| |
| public: |
| explicit InsertionPointRecord(HTMLInputStream& input_stream) |
| : input_stream_(&input_stream) { |
| line_ = input_stream_->Current().CurrentLine(); |
| column_ = input_stream_->Current().CurrentColumn(); |
| input_stream_->SplitInto(next_); |
| // We 'fork' current position and use it for the generated script part. This |
| // is a bit weird, because generated part does not have positions within an |
| // HTML document. |
| input_stream_->Current().SetCurrentPosition(line_, column_, 0); |
| } |
| |
| ~InsertionPointRecord() { |
| // Some inserted text may have remained in input stream. E.g. if script has |
| // written "&" or "<table", it stays in buffer because it cannot be |
| // properly tokenized before we see next part. |
| int unparsed_remainder_length = input_stream_->Current().length(); |
| input_stream_->MergeFrom(next_); |
| // We restore position for the character that goes right after unparsed |
| // remainder. |
| input_stream_->Current().SetCurrentPosition(line_, column_, |
| unparsed_remainder_length); |
| } |
| |
| private: |
| HTMLInputStream* input_stream_; |
| SegmentedString next_; |
| OrdinalNumber line_; |
| OrdinalNumber column_; |
| |
| DISALLOW_COPY_AND_ASSIGN(InsertionPointRecord); |
| }; |
| |
| } // namespace blink |
| |
| #endif // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_HTML_INPUT_STREAM_H_ |