| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef ReadableStreamImpl_h |
| #define ReadableStreamImpl_h |
| |
| #include "bindings/core/v8/ExceptionState.h" |
| #include "bindings/core/v8/ScriptState.h" |
| #include "bindings/core/v8/ScriptValue.h" |
| #include "bindings/core/v8/V8Binding.h" |
| #include "core/streams/ReadableStream.h" |
| #include "wtf/ArrayBuffer.h" |
| #include "wtf/Deque.h" |
| #include "wtf/Forward.h" |
| #include "wtf/OwnPtr.h" |
| #include "wtf/RefPtr.h" |
| #include "wtf/text/WTFString.h" |
| |
| namespace blink { |
| |
| // We define the default ChunkTypeTraits for frequently used types. |
| template<typename ChunkType> |
| class ReadableStreamChunkTypeTraits { }; |
| |
| template<> |
| class ReadableStreamChunkTypeTraits<String> { |
| public: |
| typedef String HoldType; |
| typedef const String& PassType; |
| |
| static size_t size(const String& value) { return value.length(); } |
| static ScriptValue toScriptValue(ScriptState* scriptState, const HoldType& value) |
| { |
| return ScriptValue(scriptState, v8String(scriptState->isolate(), value)); |
| } |
| }; |
| |
| template<> |
| class ReadableStreamChunkTypeTraits<ArrayBuffer> { |
| public: |
| typedef RefPtr<ArrayBuffer> HoldType; |
| typedef PassRefPtr<ArrayBuffer> PassType; |
| |
| static size_t size(PassType value) { return value->byteLength(); } |
| static size_t size(const HoldType& value) { return value->byteLength(); } |
| static ScriptValue toScriptValue(ScriptState* scriptState, const HoldType& value) |
| { |
| return ScriptValue(scriptState, toV8NoInline(value.get(), scriptState->context()->Global(), scriptState->isolate())); |
| } |
| }; |
| |
| // ReadableStreamImpl<ChunkTypeTraits> is a ReadableStream subtype. It has a |
| // queue whose type depends on ChunkTypeTraits and it implements queue-related |
| // ReadableStream pure virtual methods. |
| template <typename ChunkTypeTraits> |
| class ReadableStreamImpl : public ReadableStream { |
| public: |
| ReadableStreamImpl(ScriptState* scriptState, UnderlyingSource* source, ExceptionState* exceptionState) |
| : ReadableStream(scriptState, source, exceptionState) |
| , m_totalQueueSize(0) { } |
| virtual ~ReadableStreamImpl() { } |
| |
| // ReadableStream methods |
| virtual ScriptValue read(ScriptState*, ExceptionState*) OVERRIDE; |
| |
| bool enqueue(typename ChunkTypeTraits::PassType); |
| |
| virtual void trace(Visitor* visitor) OVERRIDE |
| { |
| ReadableStream::trace(visitor); |
| } |
| |
| private: |
| // ReadableStream methods |
| virtual bool isQueueEmpty() const OVERRIDE { return m_queue.isEmpty(); } |
| virtual void clearQueue() OVERRIDE |
| { |
| m_queue.clear(); |
| m_totalQueueSize = 0; |
| } |
| |
| Deque<typename ChunkTypeTraits::HoldType> m_queue; |
| size_t m_totalQueueSize; |
| }; |
| |
| template <typename ChunkTypeTraits> |
| bool ReadableStreamImpl<ChunkTypeTraits>::enqueue(typename ChunkTypeTraits::PassType chunk) |
| { |
| size_t size = ChunkTypeTraits::size(chunk); |
| if (!enqueuePreliminaryCheck(size)) |
| return false; |
| m_queue.append(chunk); |
| m_totalQueueSize += size; |
| return enqueuePostAction(m_totalQueueSize); |
| } |
| |
| template <typename ChunkTypeTraits> |
| ScriptValue ReadableStreamImpl<ChunkTypeTraits>::read(ScriptState* scriptState, ExceptionState* exceptionState) |
| { |
| readPreliminaryCheck(exceptionState); |
| if (exceptionState->hadException()) |
| return ScriptValue(); |
| ASSERT(state() == Readable); |
| ASSERT(!m_queue.isEmpty()); |
| typename ChunkTypeTraits::HoldType chunk = m_queue.takeFirst(); |
| m_totalQueueSize -= ChunkTypeTraits::size(chunk); |
| readPostAction(); |
| return ChunkTypeTraits::toScriptValue(scriptState, chunk); |
| } |
| |
| } // namespace blink |
| |
| #endif // ReadableStreamImpl_h |
| |