https://bugs.webkit.org/show_bug.cgi?id=170956
Reviewed by Andreas Kling.
Source/JavaScriptCore:
* runtime/ArrayBuffer.h:
Source/WebCore:
SharedBuffer was a mess of different data structures added over the years.
SharedBuffer::append would allocate large Vector<char>s and call memcpy, and that
is inefficient and causes crashes when large allocations fail, and the allocations
and copies aren't even necessary. There were also const correctness problems in
ResourceLoader::addDataOrBuffer, and iterating a SharedBuffer was strange because
sometimes we don't want to add unnecessary copies.
These problems are solved by making SharedBuffer a Vector of read-only data segments,
which can be contained in various ways but we don't care because all we want to do is
read them. Appending SharedBuffers is now const correct because we just add to a
Vector<Ref<DataSegment>> and neither SharedBuffer can write to the data. Sometimes,
though, we want all the data to be in continuous memory, and if there are multiple
segments then the data needs to be copied once to a new segment. We should audit the
call sites of SharedBuffer::data and see if this is really necessary.
No change in functional behavior. Fewer copies of the data are made when buffering
data in the NetworkProcess. No extra memory is allocated for bytes we think we might
need to append in the future. Data is now only copied into one buffer lazily as needed,
which could slightly change when small delays from memcpy happen, but it's an overall
improvement. We could have a performance hit if we were to call append() then data()
then append() then data() etc. but that doesn't happen in WebKit because we call append
repeatedly when buffering the data then call data() once when reading the data.
* editing/cocoa/EditorCocoa.mm:
(WebCore::archivedDataForAttributedString):
(WebCore::Editor::selectionInWebArchiveFormat):
(WebCore::Editor::dataInRTFDFormat):
(WebCore::Editor::dataInRTFFormat):
* editing/ios/EditorIOS.mm:
(WebCore::Editor::WebContentReader::readURL):
* editing/mac/EditorMac.mm:
(WebCore::Editor::imageInWebArchiveFormat):
* loader/TextTrackLoader.cpp:
(WebCore::TextTrackLoader::processNewCueData):
* loader/archive/cf/LegacyWebArchive.cpp:
(WebCore::LegacyWebArchive::createResource):
* loader/cache/CachedResource.cpp:
(WebCore::CachedResource::tryReplaceEncodedData):
* loader/cocoa/DiskCacheMonitorCocoa.mm:
(WebCore::DiskCacheMonitor::tryGetFileBackedSharedBufferFromCFURLCachedResponse):
* platform/SharedBuffer.cpp:
(WebCore::SharedBuffer::SharedBuffer):
(WebCore::SharedBuffer::create):
(WebCore::SharedBuffer::combineToOneSegment):
(WebCore::SharedBuffer::data):
(WebCore::SharedBuffer::createArrayBuffer):
(WebCore::SharedBuffer::append):
(WebCore::SharedBuffer::clear):
(WebCore::SharedBuffer::copy):
(WebCore::SharedBuffer::DataSegment::data):
(WebCore::SharedBuffer::DataSegment::size):
(WebCore::segmentIndex): Deleted.
(WebCore::offsetInSegment): Deleted.
(WebCore::allocateSegment): Deleted.
(WebCore::freeSegment): Deleted.
(WebCore::SharedBuffer::~SharedBuffer): Deleted.
(WebCore::SharedBuffer::size): Deleted.
(WebCore::SharedBuffer::duplicateDataBufferIfNecessary): Deleted.
(WebCore::SharedBuffer::appendToDataBuffer): Deleted.
(WebCore::SharedBuffer::clearDataBuffer): Deleted.
(WebCore::SharedBuffer::copyBufferAndClear): Deleted.
(WebCore::SharedBuffer::buffer): Deleted.
(WebCore::SharedBuffer::getSomeData): Deleted.
(WebCore::SharedBuffer::maybeTransferMappedFileData): Deleted.
(WebCore::SharedBuffer::clearPlatformData): Deleted.
(WebCore::SharedBuffer::maybeTransferPlatformData): Deleted.
(WebCore::SharedBuffer::hasPlatformData): Deleted.
(WebCore::SharedBuffer::platformData): Deleted.
(WebCore::SharedBuffer::maybeAppendPlatformData): Deleted.
* platform/SharedBuffer.h:
(WebCore::SharedBuffer::create): Deleted.
(WebCore::SharedBuffer::isEmpty): Deleted.
* platform/SharedBufferChunkReader.cpp:
(WebCore::SharedBufferChunkReader::nextChunk):
(WebCore::SharedBufferChunkReader::peek):
* platform/SharedBufferChunkReader.h:
* platform/URLParser.cpp:
(WebCore::URLParser::URLParser):
* platform/cf/KeyedEncoderCF.cpp:
(WebCore::KeyedEncoderCF::finishEncoding):
* platform/cf/SharedBufferCF.cpp:
(WebCore::SharedBuffer::SharedBuffer):
(WebCore::SharedBuffer::createCFData):
(WebCore::SharedBuffer::create):
(WebCore::SharedBuffer::hintMemoryNotNeededSoon):
(WebCore::SharedBuffer::append):
(WebCore::SharedBuffer::wrapCFData): Deleted.
(WebCore::SharedBuffer::hasPlatformData): Deleted.
(WebCore::SharedBuffer::platformData): Deleted.
(WebCore::SharedBuffer::platformDataSize): Deleted.
(WebCore::SharedBuffer::maybeTransferPlatformData): Deleted.
(WebCore::SharedBuffer::clearPlatformData): Deleted.
(WebCore::SharedBuffer::tryReplaceContentsWithPlatformBuffer): Deleted.
(WebCore::SharedBuffer::maybeAppendPlatformData): Deleted.
(WebCore::SharedBuffer::copyBufferAndClear): Deleted.
(WebCore::SharedBuffer::copySomeDataFromDataArray): Deleted.
(WebCore::SharedBuffer::singleDataArrayBuffer): Deleted.
(WebCore::SharedBuffer::maybeAppendDataArray): Deleted.
* platform/cocoa/NetworkExtensionContentFilter.mm:
(WebCore::NetworkExtensionContentFilter::replacementData):
* platform/cocoa/ParentalControlsContentFilter.mm:
(WebCore::ParentalControlsContentFilter::replacementData):
* platform/cocoa/SharedBufferCocoa.mm:
(-[WebCoreSharedBufferData initWithSharedBufferDataSegment:]):
(-[WebCoreSharedBufferData length]):
(-[WebCoreSharedBufferData bytes]):
(WebCore::SharedBuffer::create):
(WebCore::SharedBuffer::createCFData):
(WebCore::SharedBuffer::createFromReadingFile):
(WebCore::SharedBuffer::createNSDataArray):
(-[WebCoreSharedBufferData initWithSharedBufferDataBuffer:]): Deleted.
(WebCore::SharedBuffer::wrapNSData): Deleted.
(WebCore::SharedBuffer::existingCFData): Deleted.
* platform/graphics/avfoundation/objc/WebCoreAVFResourceLoader.mm:
(WebCore::WebCoreAVFResourceLoader::fulfillRequestWithResource):
* platform/graphics/cocoa/FontPlatformDataCocoa.mm:
(WebCore::FontPlatformData::openTypeTable):
* platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp:
(ResourceHandleStreamingClient::didReceiveBuffer):
* platform/graphics/mac/ImageMac.mm:
(WebCore::Image::loadPlatformResource):
* platform/image-decoders/ImageDecoder.cpp:
(WebCore::ImageDecoder::create):
* platform/image-decoders/png/PNGImageDecoder.cpp:
(WebCore::PNGImageReader::decode):
* platform/ios/PlatformPasteboardIOS.mm:
(WebCore::PlatformPasteboard::readBuffer):
* platform/mac/PasteboardMac.mm:
(WebCore::writeFileWrapperAsRTFDAttachment):
(WebCore::Pasteboard::write):
* platform/mac/PlatformPasteboardMac.mm:
(WebCore::PlatformPasteboard::bufferForType):
* platform/network/BlobResourceHandle.cpp:
(WebCore::BlobResourceHandle::notifyReceiveData):
* platform/network/MIMEHeader.cpp:
* platform/network/MIMEHeader.h:
* platform/network/cf/ResourceHandleCFURLConnectionDelegateWithOperationQueue.cpp:
(WebCore::ResourceHandleCFURLConnectionDelegateWithOperationQueue::didReceiveData):
* platform/network/cf/SynchronousResourceHandleCFURLConnectionDelegate.cpp:
(WebCore::SynchronousResourceHandleCFURLConnectionDelegate::didReceiveData):
* platform/network/mac/WebCoreResourceHandleAsDelegate.mm:
(-[WebCoreResourceHandleAsDelegate connection:didReceiveData:lengthReceived:]):
* platform/network/mac/WebCoreResourceHandleAsOperationQueueDelegate.mm:
(-[WebCoreResourceHandleAsOperationQueueDelegate connection:didReceiveData:lengthReceived:]):
* platform/soup/SharedBufferSoup.cpp:
(WebCore::SharedBuffer::SharedBuffer):
(WebCore::SharedBuffer::createSoupBuffer):
(WebCore::SharedBuffer::clearPlatformData): Deleted.
(WebCore::SharedBuffer::maybeTransferPlatformData): Deleted.
(WebCore::SharedBuffer::hasPlatformData): Deleted.
(WebCore::SharedBuffer::platformData): Deleted.
(WebCore::SharedBuffer::platformDataSize): Deleted.
(WebCore::SharedBuffer::maybeAppendPlatformData): Deleted.
(WebCore::SharedBuffer::tryReplaceContentsWithPlatformBuffer): Deleted.
Source/WebKit/mac:
* WebView/WebArchive.mm:
(-[WebArchive initWithData:]):
* WebView/WebFrame.mm:
(-[WebFrame _loadData:MIMEType:textEncodingName:baseURL:unreachableURL:]):
* WebView/WebResource.mm:
(-[WebResource initWithCoder:]):
(-[WebResource _initWithData:URL:MIMEType:textEncodingName:frameName:response:copyData:]):
Source/WebKit2:
* NetworkProcess/cocoa/NetworkSessionCocoa.mm:
(-[WKNetworkSessionDelegate URLSession:dataTask:didReceiveData:]):
* Platform/IPC/DataReference.cpp:
(IPC::SharedBufferDataReference::encode):
* Shared/ShareableResource.cpp:
(WebKit::ShareableResource::wrapInSharedBuffer):
* UIProcess/API/Cocoa/WKURLSchemeHandlerTask.mm:
(-[WKURLSchemeHandlerTaskImpl didReceiveData:]):
* WebProcess/InjectedBundle/API/mac/WKWebProcessPlugInBrowserContextController.mm:
(-[WKWebProcessPlugInBrowserContextController _setEditingDelegate:]):
* WebProcess/Plugins/PDF/PDFPlugin.mm:
(WebKit::PDFPlugin::addArchiveResource):
(WebKit::PDFPlugin::liveResourceData):
(WebKit::PDFPlugin::writeItemsToPasteboard):
* WebProcess/Plugins/PluginView.cpp:
(WebKit::PluginView::redeliverManualStream):
* WebProcess/WebCoreSupport/mac/WebDragClientMac.mm:
(WebKit::WebDragClient::declareAndWriteDragImage):
* WebProcess/WebPage/mac/WebPageMac.mm:
(WebKit::WebPage::cachedResponseDataForURL):
Tools:
* TestWebKitAPI/Tests/WebCore/cocoa/SharedBuffer.mm:
(TestWebKitAPI::TEST_F):
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@215686
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2017-04-24 Alex Christensen <achristensen@webkit.org>
+
+ Reduce copies and allocations in SharedBuffer::append
+ https://bugs.webkit.org/show_bug.cgi?id=170956
+
+ Reviewed by Andreas Kling.
+
+ * runtime/ArrayBuffer.h:
+
2017-04-24 Carlos Garcia Campos <cgarcia@igalia.com>
[GTK] Switch to use ENABLE_REMOTE_INSPECTOR instead of ENABLE_INSPECTOR_SERVER for the remote inspector
JS_EXPORT_PRIVATE static RefPtr<ArrayBuffer> tryCreate(ArrayBuffer&);
JS_EXPORT_PRIVATE static RefPtr<ArrayBuffer> tryCreate(const void* source, unsigned byteLength);
- // Only for use by Uint8ClampedArray::createUninitialized and SharedBuffer::createArrayBuffer.
+ // Only for use by Uint8ClampedArray::createUninitialized and SharedBuffer::tryCreateArrayBuffer.
JS_EXPORT_PRIVATE static Ref<ArrayBuffer> createUninitialized(unsigned numElements, unsigned elementByteSize);
JS_EXPORT_PRIVATE static RefPtr<ArrayBuffer> tryCreateUninitialized(unsigned numElements, unsigned elementByteSize);
+2017-04-24 Alex Christensen <achristensen@webkit.org>
+
+ Reduce copies and allocations in SharedBuffer::append
+ https://bugs.webkit.org/show_bug.cgi?id=170956
+
+ Reviewed by Andreas Kling.
+
+ SharedBuffer was a mess of different data structures added over the years.
+ SharedBuffer::append would allocate large Vector<char>s and call memcpy, and that
+ is inefficient and causes crashes when large allocations fail, and the allocations
+ and copies aren't even necessary. There were also const correctness problems in
+ ResourceLoader::addDataOrBuffer, and iterating a SharedBuffer was strange because
+ sometimes we don't want to add unnecessary copies.
+
+ These problems are solved by making SharedBuffer a Vector of read-only data segments,
+ which can be contained in various ways but we don't care because all we want to do is
+ read them. Appending SharedBuffers is now const correct because we just add to a
+ Vector<Ref<DataSegment>> and neither SharedBuffer can write to the data. Sometimes,
+ though, we want all the data to be in continuous memory, and if there are multiple
+ segments then the data needs to be copied once to a new segment. We should audit the
+ call sites of SharedBuffer::data and see if this is really necessary.
+
+ No change in functional behavior. Fewer copies of the data are made when buffering
+ data in the NetworkProcess. No extra memory is allocated for bytes we think we might
+ need to append in the future. Data is now only copied into one buffer lazily as needed,
+ which could slightly change when small delays from memcpy happen, but it's an overall
+ improvement. We could have a performance hit if we were to call append() then data()
+ then append() then data() etc. but that doesn't happen in WebKit because we call append
+ repeatedly when buffering the data then call data() once when reading the data.
+
+ * editing/cocoa/EditorCocoa.mm:
+ (WebCore::archivedDataForAttributedString):
+ (WebCore::Editor::selectionInWebArchiveFormat):
+ (WebCore::Editor::dataInRTFDFormat):
+ (WebCore::Editor::dataInRTFFormat):
+ * editing/ios/EditorIOS.mm:
+ (WebCore::Editor::WebContentReader::readURL):
+ * editing/mac/EditorMac.mm:
+ (WebCore::Editor::imageInWebArchiveFormat):
+ * loader/TextTrackLoader.cpp:
+ (WebCore::TextTrackLoader::processNewCueData):
+ * loader/archive/cf/LegacyWebArchive.cpp:
+ (WebCore::LegacyWebArchive::createResource):
+ * loader/cache/CachedResource.cpp:
+ (WebCore::CachedResource::tryReplaceEncodedData):
+ * loader/cocoa/DiskCacheMonitorCocoa.mm:
+ (WebCore::DiskCacheMonitor::tryGetFileBackedSharedBufferFromCFURLCachedResponse):
+ * platform/SharedBuffer.cpp:
+ (WebCore::SharedBuffer::SharedBuffer):
+ (WebCore::SharedBuffer::create):
+ (WebCore::SharedBuffer::combineToOneSegment):
+ (WebCore::SharedBuffer::data):
+ (WebCore::SharedBuffer::createArrayBuffer):
+ (WebCore::SharedBuffer::append):
+ (WebCore::SharedBuffer::clear):
+ (WebCore::SharedBuffer::copy):
+ (WebCore::SharedBuffer::DataSegment::data):
+ (WebCore::SharedBuffer::DataSegment::size):
+ (WebCore::segmentIndex): Deleted.
+ (WebCore::offsetInSegment): Deleted.
+ (WebCore::allocateSegment): Deleted.
+ (WebCore::freeSegment): Deleted.
+ (WebCore::SharedBuffer::~SharedBuffer): Deleted.
+ (WebCore::SharedBuffer::size): Deleted.
+ (WebCore::SharedBuffer::duplicateDataBufferIfNecessary): Deleted.
+ (WebCore::SharedBuffer::appendToDataBuffer): Deleted.
+ (WebCore::SharedBuffer::clearDataBuffer): Deleted.
+ (WebCore::SharedBuffer::copyBufferAndClear): Deleted.
+ (WebCore::SharedBuffer::buffer): Deleted.
+ (WebCore::SharedBuffer::getSomeData): Deleted.
+ (WebCore::SharedBuffer::maybeTransferMappedFileData): Deleted.
+ (WebCore::SharedBuffer::clearPlatformData): Deleted.
+ (WebCore::SharedBuffer::maybeTransferPlatformData): Deleted.
+ (WebCore::SharedBuffer::hasPlatformData): Deleted.
+ (WebCore::SharedBuffer::platformData): Deleted.
+ (WebCore::SharedBuffer::maybeAppendPlatformData): Deleted.
+ * platform/SharedBuffer.h:
+ (WebCore::SharedBuffer::create): Deleted.
+ (WebCore::SharedBuffer::isEmpty): Deleted.
+ * platform/SharedBufferChunkReader.cpp:
+ (WebCore::SharedBufferChunkReader::nextChunk):
+ (WebCore::SharedBufferChunkReader::peek):
+ * platform/SharedBufferChunkReader.h:
+ * platform/URLParser.cpp:
+ (WebCore::URLParser::URLParser):
+ * platform/cf/KeyedEncoderCF.cpp:
+ (WebCore::KeyedEncoderCF::finishEncoding):
+ * platform/cf/SharedBufferCF.cpp:
+ (WebCore::SharedBuffer::SharedBuffer):
+ (WebCore::SharedBuffer::createCFData):
+ (WebCore::SharedBuffer::create):
+ (WebCore::SharedBuffer::hintMemoryNotNeededSoon):
+ (WebCore::SharedBuffer::append):
+ (WebCore::SharedBuffer::wrapCFData): Deleted.
+ (WebCore::SharedBuffer::hasPlatformData): Deleted.
+ (WebCore::SharedBuffer::platformData): Deleted.
+ (WebCore::SharedBuffer::platformDataSize): Deleted.
+ (WebCore::SharedBuffer::maybeTransferPlatformData): Deleted.
+ (WebCore::SharedBuffer::clearPlatformData): Deleted.
+ (WebCore::SharedBuffer::tryReplaceContentsWithPlatformBuffer): Deleted.
+ (WebCore::SharedBuffer::maybeAppendPlatformData): Deleted.
+ (WebCore::SharedBuffer::copyBufferAndClear): Deleted.
+ (WebCore::SharedBuffer::copySomeDataFromDataArray): Deleted.
+ (WebCore::SharedBuffer::singleDataArrayBuffer): Deleted.
+ (WebCore::SharedBuffer::maybeAppendDataArray): Deleted.
+ * platform/cocoa/NetworkExtensionContentFilter.mm:
+ (WebCore::NetworkExtensionContentFilter::replacementData):
+ * platform/cocoa/ParentalControlsContentFilter.mm:
+ (WebCore::ParentalControlsContentFilter::replacementData):
+ * platform/cocoa/SharedBufferCocoa.mm:
+ (-[WebCoreSharedBufferData initWithSharedBufferDataSegment:]):
+ (-[WebCoreSharedBufferData length]):
+ (-[WebCoreSharedBufferData bytes]):
+ (WebCore::SharedBuffer::create):
+ (WebCore::SharedBuffer::createCFData):
+ (WebCore::SharedBuffer::createFromReadingFile):
+ (WebCore::SharedBuffer::createNSDataArray):
+ (-[WebCoreSharedBufferData initWithSharedBufferDataBuffer:]): Deleted.
+ (WebCore::SharedBuffer::wrapNSData): Deleted.
+ (WebCore::SharedBuffer::existingCFData): Deleted.
+ * platform/graphics/avfoundation/objc/WebCoreAVFResourceLoader.mm:
+ (WebCore::WebCoreAVFResourceLoader::fulfillRequestWithResource):
+ * platform/graphics/cocoa/FontPlatformDataCocoa.mm:
+ (WebCore::FontPlatformData::openTypeTable):
+ * platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp:
+ (ResourceHandleStreamingClient::didReceiveBuffer):
+ * platform/graphics/mac/ImageMac.mm:
+ (WebCore::Image::loadPlatformResource):
+ * platform/image-decoders/ImageDecoder.cpp:
+ (WebCore::ImageDecoder::create):
+ * platform/image-decoders/png/PNGImageDecoder.cpp:
+ (WebCore::PNGImageReader::decode):
+ * platform/ios/PlatformPasteboardIOS.mm:
+ (WebCore::PlatformPasteboard::readBuffer):
+ * platform/mac/PasteboardMac.mm:
+ (WebCore::writeFileWrapperAsRTFDAttachment):
+ (WebCore::Pasteboard::write):
+ * platform/mac/PlatformPasteboardMac.mm:
+ (WebCore::PlatformPasteboard::bufferForType):
+ * platform/network/BlobResourceHandle.cpp:
+ (WebCore::BlobResourceHandle::notifyReceiveData):
+ * platform/network/MIMEHeader.cpp:
+ * platform/network/MIMEHeader.h:
+ * platform/network/cf/ResourceHandleCFURLConnectionDelegateWithOperationQueue.cpp:
+ (WebCore::ResourceHandleCFURLConnectionDelegateWithOperationQueue::didReceiveData):
+ * platform/network/cf/SynchronousResourceHandleCFURLConnectionDelegate.cpp:
+ (WebCore::SynchronousResourceHandleCFURLConnectionDelegate::didReceiveData):
+ * platform/network/mac/WebCoreResourceHandleAsDelegate.mm:
+ (-[WebCoreResourceHandleAsDelegate connection:didReceiveData:lengthReceived:]):
+ * platform/network/mac/WebCoreResourceHandleAsOperationQueueDelegate.mm:
+ (-[WebCoreResourceHandleAsOperationQueueDelegate connection:didReceiveData:lengthReceived:]):
+ * platform/soup/SharedBufferSoup.cpp:
+ (WebCore::SharedBuffer::SharedBuffer):
+ (WebCore::SharedBuffer::createSoupBuffer):
+ (WebCore::SharedBuffer::clearPlatformData): Deleted.
+ (WebCore::SharedBuffer::maybeTransferPlatformData): Deleted.
+ (WebCore::SharedBuffer::hasPlatformData): Deleted.
+ (WebCore::SharedBuffer::platformData): Deleted.
+ (WebCore::SharedBuffer::platformDataSize): Deleted.
+ (WebCore::SharedBuffer::maybeAppendPlatformData): Deleted.
+ (WebCore::SharedBuffer::tryReplaceContentsWithPlatformBuffer): Deleted.
+
2017-04-24 Dan Bernstein <mitz@apple.com>
[Cocoa] Some ivars are needlessly @protected
// 2. Queue a task to create an event named message that does not bubble and is not cancellable using the MediaKeyMessageEvent
// interface with its type attribute set to message and its isTrusted attribute initialized to true, and dispatch it at the
// session.
- auto messageEvent = MediaKeyMessageEvent::create(eventNames().messageEvent, {messageType, message.createArrayBuffer()}, Event::IsTrusted::Yes);
+ auto messageEvent = MediaKeyMessageEvent::create(eventNames().messageEvent, {messageType, message.tryCreateArrayBuffer()}, Event::IsTrusted::Yes);
m_eventQueue.enqueueEvent(WTFMove(messageEvent));
}
if (!m_buffer)
return ArrayBuffer::tryCreate(nullptr, 0);
- auto arrayBuffer = m_buffer->createArrayBuffer();
+ auto arrayBuffer = m_buffer->tryCreateArrayBuffer();
m_buffer = nullptr;
return arrayBuffer;
}
RefPtr<SharedBuffer> data = m_bodyLoader->startStreaming();
if (data) {
- if (!m_readableStreamSource->enqueue(data->createArrayBuffer())) {
+ if (!m_readableStreamSource->enqueue(data->tryCreateArrayBuffer())) {
stop();
return;
}
37BAAE581980D1DD005DFE71 /* ProtectionSpace.h in Headers */ = {isa = PBXBuildFile; fileRef = 37BAAE571980D1DD005DFE71 /* ProtectionSpace.h */; settings = {ATTRIBUTES = (Private, ); }; };
37C238221098C84200EF9F72 /* ComplexTextControllerCoreText.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37C238201098C84200EF9F72 /* ComplexTextControllerCoreText.mm */; };
37D456FD1A9A50D8003330A1 /* LocalizableStrings.pm in Copy Scripts */ = {isa = PBXBuildFile; fileRef = 37D456FB1A9A50B6003330A1 /* LocalizableStrings.pm */; };
- 37DDCD9413844FD50008B793 /* MIMEHeader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 37DDCD9213844FD50008B793 /* MIMEHeader.cpp */; };
- 37DDCD9513844FD50008B793 /* MIMEHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 37DDCD9313844FD50008B793 /* MIMEHeader.h */; };
37DDCD9E13844FFA0008B793 /* Archive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 37DDCD9D13844FFA0008B793 /* Archive.cpp */; };
- 37DDCDA51384501C0008B793 /* MHTMLArchive.h in Headers */ = {isa = PBXBuildFile; fileRef = 37DDCDA11384501C0008B793 /* MHTMLArchive.h */; };
- 37DDCDA71384501C0008B793 /* MHTMLParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 37DDCDA31384501C0008B793 /* MHTMLParser.h */; };
37E3524B12450C5200BAF5D9 /* InputType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 37E3524A12450C5200BAF5D9 /* InputType.cpp */; };
37E3524D12450C6600BAF5D9 /* InputType.h in Headers */ = {isa = PBXBuildFile; fileRef = 37E3524C12450C6600BAF5D9 /* InputType.h */; settings = {ATTRIBUTES = (Private, ); }; };
37F567CE165358F400DDE92B /* PopupOpeningObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = 3772B09516535856000A49CA /* PopupOpeningObserver.h */; settings = {ATTRIBUTES = (Private, ); }; };
97AABD2714FA09D5007457AE /* WebSocketHandshake.h in Headers */ = {isa = PBXBuildFile; fileRef = 97AABD0C14FA09D5007457AE /* WebSocketHandshake.h */; };
97AABD2C14FA09D5007457AE /* WorkerThreadableWebSocketChannel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 97AABD1114FA09D5007457AE /* WorkerThreadableWebSocketChannel.cpp */; };
97AABD2D14FA09D5007457AE /* WorkerThreadableWebSocketChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 97AABD1214FA09D5007457AE /* WorkerThreadableWebSocketChannel.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 97B1F02E13B025CA00F5103F /* SharedBufferChunkReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 37569E0013AF172C00CDBA8E /* SharedBufferChunkReader.cpp */; };
- 97B1F02F13B025D200F5103F /* SharedBufferChunkReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 37569E0213AF172C00CDBA8E /* SharedBufferChunkReader.h */; };
97B38E27151C4271004622E9 /* DOMWindowNotifications.h in Headers */ = {isa = PBXBuildFile; fileRef = 97B38E24151C4264004622E9 /* DOMWindowNotifications.h */; };
97B38E28151C4273004622E9 /* DOMWindowNotifications.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 97B38E23151C4264004622E9 /* DOMWindowNotifications.cpp */; };
97B8FFD116AE7F960038388D /* CharacterReferenceParserInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 97B8FFCF16AE7F920038388D /* CharacterReferenceParserInlines.h */; };
372ADA39197F687600FC501E /* ProtectionSpaceCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ProtectionSpaceCocoa.mm; sourceTree = "<group>"; };
372C00C3129611F1005C9575 /* TextBoundaries.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextBoundaries.cpp; sourceTree = "<group>"; };
372C00D8129619F8005C9575 /* FindOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FindOptions.h; sourceTree = "<group>"; };
- 37569E0013AF172C00CDBA8E /* SharedBufferChunkReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SharedBufferChunkReader.cpp; sourceTree = "<group>"; };
- 37569E0213AF172C00CDBA8E /* SharedBufferChunkReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SharedBufferChunkReader.h; sourceTree = "<group>"; };
375CD231119D43C800A2A859 /* Hyphenation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Hyphenation.h; sourceTree = "<group>"; };
376DCCE013B4F966002EBEFC /* TextRun.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextRun.cpp; sourceTree = "<group>"; };
3772B09516535856000A49CA /* PopupOpeningObserver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PopupOpeningObserver.h; sourceTree = "<group>"; };
37BAAE571980D1DD005DFE71 /* ProtectionSpace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProtectionSpace.h; sourceTree = "<group>"; };
37C238201098C84200EF9F72 /* ComplexTextControllerCoreText.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ComplexTextControllerCoreText.mm; sourceTree = "<group>"; };
37D456FB1A9A50B6003330A1 /* LocalizableStrings.pm */ = {isa = PBXFileReference; lastKnownFileType = text.script.perl; path = LocalizableStrings.pm; sourceTree = "<group>"; };
- 37DDCD9213844FD50008B793 /* MIMEHeader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MIMEHeader.cpp; sourceTree = "<group>"; };
- 37DDCD9313844FD50008B793 /* MIMEHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MIMEHeader.h; sourceTree = "<group>"; };
37DDCD9D13844FFA0008B793 /* Archive.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Archive.cpp; sourceTree = "<group>"; };
- 37DDCDA11384501C0008B793 /* MHTMLArchive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MHTMLArchive.h; sourceTree = "<group>"; };
- 37DDCDA31384501C0008B793 /* MHTMLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MHTMLParser.h; sourceTree = "<group>"; };
37E3524A12450C5200BAF5D9 /* InputType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InputType.cpp; sourceTree = "<group>"; };
37E3524C12450C6600BAF5D9 /* InputType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InputType.h; sourceTree = "<group>"; };
37F818FB0D657606005E1F05 /* WebCoreURLResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebCoreURLResponse.h; sourceTree = "<group>"; };
path = opentype;
sourceTree = "<group>";
};
- 37DDCD9F1384501C0008B793 /* mhtml */ = {
- isa = PBXGroup;
- children = (
- 37DDCDA11384501C0008B793 /* MHTMLArchive.h */,
- 37DDCDA31384501C0008B793 /* MHTMLParser.h */,
- );
- path = mhtml;
- sourceTree = "<group>";
- };
4150F9ED12B6E0990008C860 /* shadow */ = {
isa = PBXGroup;
children = (
isa = PBXGroup;
children = (
512DD8E90D91E6AF000F89EE /* cf */,
- 37DDCD9F1384501C0008B793 /* mhtml */,
37DDCD9D13844FFA0008B793 /* Archive.cpp */,
512DD8EC0D91E6AF000F89EE /* Archive.h */,
512DD8F00D91E6AF000F89EE /* ArchiveFactory.cpp */,
41614A771DA64236004AD06F /* HTTPHeaderValues.h */,
514C765D0CE923A1007EF3CD /* HTTPParsers.cpp */,
514C765E0CE923A1007EF3CD /* HTTPParsers.h */,
- 37DDCD9213844FD50008B793 /* MIMEHeader.cpp */,
- 37DDCD9313844FD50008B793 /* MIMEHeader.h */,
628D214B12131ED10055DCFC /* NetworkingContext.h */,
8A81BF8411DCFD9000DA2B98 /* NetworkLoadMetrics.h */,
1A7FA61A0DDA3BBE0028F8A5 /* NetworkStateNotifier.cpp */,
077AF13E18F4AE400001ED61 /* SerializedPlatformRepresentation.h */,
1A4A954B0B4EDCCB002D8C3C /* SharedBuffer.cpp */,
1A4A954C0B4EDCCB002D8C3C /* SharedBuffer.h */,
- 37569E0013AF172C00CDBA8E /* SharedBufferChunkReader.cpp */,
- 37569E0213AF172C00CDBA8E /* SharedBufferChunkReader.h */,
93309EA0099EB78C0056E581 /* SharedTimer.h */,
4B3043C60AE0370300A82647 /* Sound.h */,
F587866202DE3B1101EA4122 /* SSLKeyGenerator.h */,
75793E840D0CE0B3007FC0AC /* MessageEvent.h in Headers */,
E1ADECBF0E76ACF1004A1A5E /* MessagePort.h in Headers */,
41BF700C0FE86F49005E8DEC /* MessagePortChannel.h in Headers */,
- 37DDCDA51384501C0008B793 /* MHTMLArchive.h in Headers */,
- 37DDCDA71384501C0008B793 /* MHTMLParser.h in Headers */,
53B895AF19DC7ED9009CAA93 /* Microtasks.h in Headers */,
- 37DDCD9513844FD50008B793 /* MIMEHeader.h in Headers */,
BC772C4F0C4EB3040083285F /* MIMETypeRegistry.h in Headers */,
52F10866162B6DA8009AC81E /* MixedContentChecker.h in Headers */,
CE1252491A16C3BC00864480 /* MobileGestaltSPI.h in Headers */,
FD45A952175D3F3E00C21EC8 /* ShapeOutsideInfo.h in Headers */,
FD1AF1501656F15100C6D4F7 /* ShapeValue.h in Headers */,
1A4A954E0B4EDCCB002D8C3C /* SharedBuffer.h in Headers */,
- 97B1F02F13B025D200F5103F /* SharedBufferChunkReader.h in Headers */,
93309EA3099EB78C0056E581 /* SharedTimer.h in Headers */,
E48944A3180B57D800F165D8 /* SimpleLineLayout.h in Headers */,
11E067EE1E6246E500162D16 /* SimpleLineLayoutCoverage.h in Headers */,
75793E830D0CE0B3007FC0AC /* MessageEvent.cpp in Sources */,
E1ADECC00E76ACF1004A1A5E /* MessagePort.cpp in Sources */,
CB8CF0181A9358D4000D510B /* Microtasks.cpp in Sources */,
- 37DDCD9413844FD50008B793 /* MIMEHeader.cpp in Sources */,
BC772C4E0C4EB3040083285F /* MIMETypeRegistry.cpp in Sources */,
C53D39341C978A45007F3AE9 /* MIMETypeRegistryCocoa.mm in Sources */,
52F10865162B6DA4009AC81E /* MixedContentChecker.cpp in Sources */,
1AB5EBD0194A1D170059AC70 /* ShapeValue.cpp in Sources */,
1A4A954D0B4EDCCB002D8C3C /* SharedBuffer.cpp in Sources */,
512DD8E30D91E2B4000F89EE /* SharedBufferCF.cpp in Sources */,
- 97B1F02E13B025CA00F5103F /* SharedBufferChunkReader.cpp in Sources */,
1A4A95520B4EDCFF002D8C3C /* SharedBufferCocoa.mm in Sources */,
163E88F7118A39D200ED9231 /* SimpleFontDataCoreText.cpp in Sources */,
E48944A2180B57D800F165D8 /* SimpleLineLayout.cpp in Sources */,
if (!attributedString.length)
return nullptr;
- return SharedBuffer::wrapNSData([NSKeyedArchiver archivedDataWithRootObject:attributedString]);
+ return SharedBuffer::create([NSKeyedArchiver archivedDataWithRootObject:attributedString]);
}
void Editor::writeSelectionToPasteboard(Pasteboard& pasteboard)
RefPtr<LegacyWebArchive> archive = LegacyWebArchive::createFromSelection(&m_frame);
if (!archive)
return nullptr;
- return SharedBuffer::wrapCFData(archive->rawDataRepresentation().get());
+ return SharedBuffer::create(archive->rawDataRepresentation().get());
}
// FIXME: Makes no sense that selectedTextForDataTransfer always includes alt text, but stringSelectionForPasteboard does not.
return nullptr;
BEGIN_BLOCK_OBJC_EXCEPTIONS;
- return SharedBuffer::wrapNSData([string RTFDFromRange:NSMakeRange(0, length) documentAttributes:@{ }]);
+ return SharedBuffer::create([string RTFDFromRange:NSMakeRange(0, length) documentAttributes:@{ }]);
END_BLOCK_OBJC_EXCEPTIONS;
return nullptr;
return nullptr;
BEGIN_BLOCK_OBJC_EXCEPTIONS;
- return SharedBuffer::wrapNSData([string RTFFromRange:NSMakeRange(0, length) documentAttributes:@{ }]);
+ return SharedBuffer::create([string RTFFromRange:NSMakeRange(0, length) documentAttributes:@{ }]);
END_BLOCK_OBJC_EXCEPTIONS;
return nullptr;
RetainPtr<NSString> fileType = adoptNS((NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (CFStringRef)[localPath pathExtension], NULL));
NSData *data = [NSData dataWithContentsOfFile:localPath];
if (UTTypeConformsTo((CFStringRef)fileType.get(), kUTTypePNG)) {
- addFragment(frame.editor().createFragmentForImageResourceAndAddResource(ArchiveResource::create(SharedBuffer::wrapNSData([[data copy] autorelease]), URL::fakeURLWithRelativePart("image.png"), @"image/png", emptyString(), emptyString())));
+ addFragment(frame.editor().createFragmentForImageResourceAndAddResource(ArchiveResource::create(SharedBuffer::create([[data copy] autorelease]), URL::fakeURLWithRelativePart("image.png"), @"image/png", emptyString(), emptyString())));
return fragment;
} else if (UTTypeConformsTo((CFStringRef)fileType.get(), kUTTypeJPEG)) {
- addFragment(frame.editor().createFragmentForImageResourceAndAddResource(ArchiveResource::create(SharedBuffer::wrapNSData([[data copy] autorelease]), URL::fakeURLWithRelativePart("image.jpg"), @"image/jpg", emptyString(), emptyString())));
+ addFragment(frame.editor().createFragmentForImageResourceAndAddResource(ArchiveResource::create(SharedBuffer::create([[data copy] autorelease]), URL::fakeURLWithRelativePart("image.jpg"), @"image/jpg", emptyString(), emptyString())));
return fragment;
}
} else {
RefPtr<LegacyWebArchive> archive = LegacyWebArchive::create(imageElement);
if (!archive)
return nullptr;
- return SharedBuffer::wrapCFData(archive->rawDataRepresentation().get());
+ return SharedBuffer::create(archive->rawDataRepresentation().get());
}
RefPtr<SharedBuffer> Editor::dataSelectionForPasteboard(const String& pasteboardType)
if (!m_cueParser)
m_cueParser = std::make_unique<WebVTTParser>(static_cast<WebVTTParserClient*>(this), m_scriptExecutionContext);
- const char* data;
- unsigned length;
-
- while ((length = buffer->getSomeData(data, m_parseOffset))) {
- m_cueParser->parseBytes(data, length);
- m_parseOffset += length;
+ auto bytesToSkip = m_parseOffset;
+ for (const auto& segment : *buffer) {
+ if (bytesToSkip > segment->size()) {
+ bytesToSkip -= segment->size();
+ continue;
+ }
+ m_cueParser->parseBytes(segment->data() + bytesToSkip, segment->size() - bytesToSkip);
+ bytesToSkip = 0;
+ m_parseOffset += segment->size();
}
}
response = createResourceResponseFromPropertyListData(resourceResponseData, resourceResponseVersion);
}
- return ArchiveResource::create(SharedBuffer::wrapCFData(resourceData), URL(URL(), url), mimeType, textEncoding, frameName, response);
+ return ArchiveResource::create(SharedBuffer::create(resourceData), URL(URL(), url), mimeType, textEncoding, frameName, response);
}
Ref<LegacyWebArchive> LegacyWebArchive::create()
if (m_data->size() != newBuffer.size() || memcmp(m_data->data(), newBuffer.data(), m_data->size()))
return;
- if (m_data->tryReplaceContentsWithPlatformBuffer(newBuffer))
- didReplaceSharedBufferContents();
+ m_data->clear();
+ m_data->append(newBuffer);
+ didReplaceSharedBufferContents();
}
#endif
if (!data)
return nullptr;
- return SharedBuffer::wrapCFData(data);
+ return SharedBuffer::create(data);
}
void DiskCacheMonitor::monitorFileBackingStoreCreation(const ResourceRequest& request, SessionID sessionID, CFCachedURLResponseRef cachedResponse)
#include <algorithm>
#include <wtf/unicode/UTF8.h>
-namespace WebCore {
-
-#if !USE(NETWORK_CFDATA_ARRAY_CALLBACK)
-
-static const unsigned segmentSize = 0x1000;
-static const unsigned segmentPositionMask = 0x0FFF;
-
-static inline unsigned segmentIndex(unsigned position)
-{
- return position / segmentSize;
-}
-
-static inline unsigned offsetInSegment(unsigned position)
-{
- return position & segmentPositionMask;
-}
-
-static inline char* allocateSegment() WARN_UNUSED_RETURN;
-static inline char* allocateSegment()
-{
- return static_cast<char*>(fastMalloc(segmentSize));
-}
-
-static inline void freeSegment(char* p)
-{
- fastFree(p);
-}
-
+#if USE(SOUP)
+#include "GUniquePtrSoup.h"
#endif
-SharedBuffer::SharedBuffer()
- : m_buffer(adoptRef(*new DataBuffer))
-{
-}
+namespace WebCore {
-SharedBuffer::SharedBuffer(const char* data, unsigned size)
- : m_buffer(adoptRef(*new DataBuffer))
+SharedBuffer::SharedBuffer(const char* data, size_t size)
{
append(data, size);
}
-SharedBuffer::SharedBuffer(const unsigned char* data, unsigned size)
- : m_buffer(adoptRef(*new DataBuffer))
+SharedBuffer::SharedBuffer(const unsigned char* data, size_t size)
{
append(reinterpret_cast<const char*>(data), size);
}
SharedBuffer::SharedBuffer(MappedFileData&& fileData)
- : m_buffer(adoptRef(*new DataBuffer))
- , m_fileData(WTFMove(fileData))
+ : m_size(fileData.size())
{
+ m_segments.append(DataSegment::create(WTFMove(fileData)));
}
-SharedBuffer::~SharedBuffer()
+SharedBuffer::SharedBuffer(Vector<char>&& data)
{
- clear();
+ append(WTFMove(data));
}
RefPtr<SharedBuffer> SharedBuffer::createWithContentsOfFile(const String& filePath)
Ref<SharedBuffer> SharedBuffer::create(Vector<char>&& vector)
{
- auto buffer = create();
- buffer->m_buffer->data = WTFMove(vector);
- buffer->m_size = buffer->m_buffer->data.size();
- return buffer;
+ return adoptRef(*new SharedBuffer(WTFMove(vector)));
}
-unsigned SharedBuffer::size() const
+void SharedBuffer::combineIntoOneSegment() const
{
- if (hasPlatformData())
- return platformDataSize();
-
- if (m_fileData)
- return m_fileData.size();
+ if (m_segments.size() <= 1)
+ return;
- return m_size;
+ Vector<char> combinedData;
+ combinedData.reserveInitialCapacity(m_size);
+ for (const auto& segment : m_segments)
+ combinedData.append(segment->data(), segment->size());
+ ASSERT(combinedData.size() == m_size);
+ m_segments.clear();
+ m_segments.append(DataSegment::create(WTFMove(combinedData)));
+ ASSERT(m_segments.size() == 1);
}
const char* SharedBuffer::data() const
{
- if (hasPlatformData())
- return platformData();
-
- if (m_fileData)
- return static_cast<const char*>(m_fileData.data());
-
-#if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
- if (const char* buffer = singleDataArrayBuffer())
- return buffer;
-#endif
-
- return this->buffer().data();
+ if (!m_segments.size())
+ return nullptr;
+ combineIntoOneSegment();
+ return m_segments[0]->data();
}
-RefPtr<ArrayBuffer> SharedBuffer::createArrayBuffer() const
+RefPtr<ArrayBuffer> SharedBuffer::tryCreateArrayBuffer() const
{
RefPtr<ArrayBuffer> arrayBuffer = ArrayBuffer::createUninitialized(static_cast<unsigned>(size()), sizeof(char));
if (!arrayBuffer) {
- WTFLogAlways("SharedBuffer::createArrayBuffer Unable to create buffer. Requested size was %d x %lu\n", size(), sizeof(char));
+ WTFLogAlways("SharedBuffer::tryCreateArrayBuffer Unable to create buffer. Requested size was %d x %lu\n", size(), sizeof(char));
return nullptr;
}
- const char* segment = 0;
- unsigned position = 0;
- while (unsigned segmentSize = getSomeData(segment, position)) {
- memcpy(static_cast<char*>(arrayBuffer->data()) + position, segment, segmentSize);
- position += segmentSize;
- }
-
- if (position != arrayBuffer->byteLength()) {
- ASSERT_NOT_REACHED();
- // Don't return the incomplete ArrayBuffer.
- return nullptr;
+ size_t position = 0;
+ for (const auto& segment : m_segments) {
+ memcpy(static_cast<char*>(arrayBuffer->data()) + position, segment->data(), segment->size());
+ position += segment->size();
}
+ ASSERT(position == m_size);
return arrayBuffer;
}
-void SharedBuffer::append(SharedBuffer& data)
+void SharedBuffer::append(const SharedBuffer& data)
{
- if (maybeAppendPlatformData(data))
- return;
-#if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
- if (maybeAppendDataArray(data))
- return;
-#endif
-
- const char* segment;
- size_t position = 0;
- while (size_t length = data.getSomeData(segment, position)) {
- append(segment, length);
- position += length;
- }
+ m_size += data.m_size;
+ m_segments.reserveCapacity(m_segments.size() + data.m_segments.size());
+ for (const auto& segment : data.m_segments)
+ m_segments.uncheckedAppend(segment.copyRef());
}
-void SharedBuffer::append(const char* data, unsigned length)
+void SharedBuffer::append(const char* data, size_t length)
{
- if (!length)
- return;
-
- maybeTransferMappedFileData();
- maybeTransferPlatformData();
-
-#if !USE(NETWORK_CFDATA_ARRAY_CALLBACK)
- unsigned positionInSegment = offsetInSegment(m_size - m_buffer->data.size());
- m_size += length;
-
- if (m_size <= segmentSize) {
- // No need to use segments for small resource data
- if (m_buffer->data.isEmpty())
- m_buffer->data.reserveInitialCapacity(length);
- appendToDataBuffer(data, length);
- return;
- }
-
- char* segment;
- if (!positionInSegment) {
- segment = allocateSegment();
- m_segments.append(segment);
- } else
- segment = m_segments.last() + positionInSegment;
-
- unsigned segmentFreeSpace = segmentSize - positionInSegment;
- unsigned bytesToCopy = std::min(length, segmentFreeSpace);
-
- for (;;) {
- memcpy(segment, data, bytesToCopy);
- if (static_cast<unsigned>(length) == bytesToCopy)
- break;
-
- length -= bytesToCopy;
- data += bytesToCopy;
- segment = allocateSegment();
- m_segments.append(segment);
- bytesToCopy = std::min(length, segmentSize);
- }
-#else
m_size += length;
- if (m_buffer->data.isEmpty())
- m_buffer->data.reserveInitialCapacity(length);
- appendToDataBuffer(data, length);
-#endif
+ Vector<char> vector;
+ vector.append(data, length);
+ m_segments.append(DataSegment::create(WTFMove(vector)));
}
void SharedBuffer::append(Vector<char>&& data)
{
- // This takes its argument as a rvalue reference because we intend to have a future
- // version take ownership of the vector rather than copying.
- append(data.data(), data.size());
+ m_size += data.size();
+ m_segments.append(DataSegment::create(WTFMove(data)));
}
void SharedBuffer::clear()
{
- m_fileData = { };
-
- clearPlatformData();
-
-#if !USE(NETWORK_CFDATA_ARRAY_CALLBACK)
- for (char* segment : m_segments)
- freeSegment(segment);
- m_segments.clear();
-#else
- m_dataArray.clear();
-#endif
-
m_size = 0;
- clearDataBuffer();
+ m_segments.clear();
}
Ref<SharedBuffer> SharedBuffer::copy() const
{
- Ref<SharedBuffer> clone { adoptRef(*new SharedBuffer) };
-
- if (hasPlatformData() || m_fileData) {
- clone->append(data(), size());
- return clone;
- }
-
+ Ref<SharedBuffer> clone = adoptRef(*new SharedBuffer);
clone->m_size = m_size;
- clone->m_buffer->data.reserveCapacity(m_size);
- clone->m_buffer->data.append(m_buffer->data.data(), m_buffer->data.size());
-
-#if !USE(NETWORK_CFDATA_ARRAY_CALLBACK)
- if (!m_segments.isEmpty()) {
- unsigned lastIndex = m_segments.size() - 1;
- for (unsigned i = 0; i < lastIndex; ++i)
- clone->m_buffer->data.append(m_segments[i], segmentSize);
-
- unsigned sizeOfLastSegment = m_size - m_buffer->data.size() - lastIndex * segmentSize;
- clone->m_buffer->data.append(m_segments.last(), sizeOfLastSegment);
- }
-#else
- for (auto& data : m_dataArray)
- clone->m_dataArray.append(data.get());
-#endif
- ASSERT(clone->size() == size());
-
+ clone->m_segments.reserveInitialCapacity(m_segments.size());
+ for (const auto& segment : m_segments)
+ clone->m_segments.uncheckedAppend(segment.copyRef());
return clone;
}
-void SharedBuffer::duplicateDataBufferIfNecessary() const
-{
- size_t currentCapacity = m_buffer->data.capacity();
- if (m_buffer->hasOneRef() || m_size <= currentCapacity)
- return;
-
- size_t newCapacity = std::max(static_cast<size_t>(m_size), currentCapacity * 2);
- auto newBuffer = adoptRef(*new DataBuffer);
- newBuffer->data.reserveInitialCapacity(newCapacity);
- newBuffer->data = m_buffer->data;
- m_buffer = WTFMove(newBuffer);
-}
-
-void SharedBuffer::appendToDataBuffer(const char *data, unsigned length) const
+const char* SharedBuffer::DataSegment::data() const
{
- duplicateDataBufferIfNecessary();
- m_buffer->data.append(data, length);
-}
-
-void SharedBuffer::clearDataBuffer()
-{
- if (!m_buffer->hasOneRef())
- m_buffer = adoptRef(*new DataBuffer);
- else
- m_buffer->data.clear();
+ auto visitor = WTF::makeVisitor(
+ [](const Vector<char>& data) { return data.data(); },
+#if USE(CF)
+ [](const RetainPtr<CFDataRef>& data) { return reinterpret_cast<const char*>(CFDataGetBytePtr(data.get())); },
+#endif
+#if USE(SOUP)
+ [](const GUniquePtr<SoupBuffer>& data) { return data->data; },
+#endif
+ [](const MappedFileData& data) { return reinterpret_cast<const char*>(data.data()); }
+ );
+ return WTF::visit(visitor, m_immutableData);
}
#if !USE(CF)
}
#endif
-#if !USE(NETWORK_CFDATA_ARRAY_CALLBACK)
-
-void SharedBuffer::copyBufferAndClear(char* destination, unsigned bytesToCopy) const
+size_t SharedBuffer::DataSegment::size() const
{
- for (char* segment : m_segments) {
- unsigned effectiveBytesToCopy = std::min(bytesToCopy, segmentSize);
- memcpy(destination, segment, effectiveBytesToCopy);
- destination += effectiveBytesToCopy;
- bytesToCopy -= effectiveBytesToCopy;
- freeSegment(segment);
- }
- m_segments.clear();
-}
-
+ auto visitor = WTF::makeVisitor(
+ [](const Vector<char>& data) { return data.size(); },
+#if USE(CF)
+ [](const RetainPtr<CFDataRef>& data) { return CFDataGetLength(data.get()); },
#endif
-
-const Vector<char>& SharedBuffer::buffer() const
-{
- unsigned bufferSize = m_buffer->data.size();
- if (m_size > bufferSize) {
- duplicateDataBufferIfNecessary();
- m_buffer->data.resize(m_size);
- copyBufferAndClear(m_buffer->data.data() + bufferSize, m_size - bufferSize);
- }
- return m_buffer->data;
-}
-
-unsigned SharedBuffer::getSomeData(const char*& someData, unsigned position) const
-{
- unsigned totalSize = size();
- if (position >= totalSize) {
- someData = 0;
- return 0;
- }
-
- if (hasPlatformData() || m_fileData) {
- ASSERT_WITH_SECURITY_IMPLICATION(position < size());
- someData = data() + position;
- return totalSize - position;
- }
-
- ASSERT_WITH_SECURITY_IMPLICATION(position < m_size);
- unsigned consecutiveSize = m_buffer->data.size();
- if (position < consecutiveSize) {
- someData = m_buffer->data.data() + position;
- return consecutiveSize - position;
- }
-
- position -= consecutiveSize;
-#if !USE(NETWORK_CFDATA_ARRAY_CALLBACK)
- unsigned segments = m_segments.size();
- unsigned maxSegmentedSize = segments * segmentSize;
- unsigned segment = segmentIndex(position);
- if (segment < segments) {
- unsigned bytesLeft = totalSize - consecutiveSize;
- unsigned segmentedSize = std::min(maxSegmentedSize, bytesLeft);
-
- unsigned positionInSegment = offsetInSegment(position);
- someData = m_segments[segment] + positionInSegment;
- return segment == segments - 1 ? segmentedSize - position : segmentSize - positionInSegment;
- }
- ASSERT_NOT_REACHED();
- return 0;
-#else
- return copySomeDataFromDataArray(someData, position);
+#if USE(SOUP)
+ [](const GUniquePtr<SoupBuffer>& data) { return static_cast<size_t>(data->length); },
#endif
+ [](const MappedFileData& data) { return data.size(); }
+ );
+ return WTF::visit(visitor, m_immutableData);
}
-void SharedBuffer::maybeTransferMappedFileData()
-{
- if (m_fileData) {
- auto fileData = WTFMove(m_fileData);
- append(static_cast<const char*>(fileData.data()), fileData.size());
- }
-}
-
-#if !USE(CF) && !USE(SOUP)
-
-inline void SharedBuffer::clearPlatformData()
-{
-}
-
-inline void SharedBuffer::maybeTransferPlatformData()
-{
-}
-
-inline bool SharedBuffer::hasPlatformData() const
-{
- return false;
-}
-
-inline const char* SharedBuffer::platformData() const
-{
- ASSERT_NOT_REACHED();
-
- return nullptr;
-}
-
-inline bool SharedBuffer::maybeAppendPlatformData(SharedBuffer&)
-{
- return false;
-}
-
-#endif
-
RefPtr<SharedBuffer> utf8Buffer(const String& string)
{
// Allocate a buffer big enough to hold all the characters.
#include <wtf/Forward.h>
#include <wtf/RefCounted.h>
#include <wtf/ThreadSafeRefCounted.h>
+#include <wtf/Variant.h>
#include <wtf/Vector.h>
#include <wtf/text/WTFString.h>
namespace WebCore {
-class SharedBuffer : public RefCounted<SharedBuffer> {
+class WEBCORE_EXPORT SharedBuffer : public RefCounted<SharedBuffer> {
public:
static Ref<SharedBuffer> create() { return adoptRef(*new SharedBuffer); }
- static Ref<SharedBuffer> create(const char* c, unsigned i) { return adoptRef(*new SharedBuffer(c, i)); }
- static Ref<SharedBuffer> create(const unsigned char* data, unsigned size) { return adoptRef(*new SharedBuffer(data, size)); }
+ static Ref<SharedBuffer> create(const char* data, size_t size) { return adoptRef(*new SharedBuffer(data, size)); }
+ static Ref<SharedBuffer> create(const unsigned char* data, size_t size) { return adoptRef(*new SharedBuffer(data, size)); }
+ static RefPtr<SharedBuffer> createWithContentsOfFile(const String& filePath);
- WEBCORE_EXPORT static RefPtr<SharedBuffer> createWithContentsOfFile(const String& filePath);
-
- WEBCORE_EXPORT static Ref<SharedBuffer> create(Vector<char>&&);
-
- WEBCORE_EXPORT ~SharedBuffer();
+ static Ref<SharedBuffer> create(Vector<char>&&);
#if USE(FOUNDATION)
- WEBCORE_EXPORT RetainPtr<NSData> createNSData();
- WEBCORE_EXPORT RetainPtr<NSArray> createNSDataArray() const;
- WEBCORE_EXPORT static Ref<SharedBuffer> wrapNSData(NSData *);
+ RetainPtr<NSData> createNSData();
+ RetainPtr<NSArray> createNSDataArray() const;
+ static Ref<SharedBuffer> create(NSData *);
#endif
#if USE(CF)
- WEBCORE_EXPORT RetainPtr<CFDataRef> createCFData();
- WEBCORE_EXPORT static Ref<SharedBuffer> wrapCFData(CFDataRef);
- WEBCORE_EXPORT void append(CFDataRef);
+ RetainPtr<CFDataRef> createCFData();
+ static Ref<SharedBuffer> create(CFDataRef);
+ void append(CFDataRef);
#endif
#if USE(SOUP)
static Ref<SharedBuffer> wrapSoupBuffer(SoupBuffer*);
#endif
- // Calling this function will force internal segmented buffers
- // to be merged into a flat buffer. Use getSomeData() whenever possible
- // for better performance.
- WEBCORE_EXPORT const char* data() const;
+ // Calling data() causes all the data segments to be copied into one segment if they are not already.
+ // Iterate the segments using begin() and end() instead.
+ // FIXME: Audit the call sites of this function and replace them with iteration if possible.
+ const char* data() const;
+
// Creates an ArrayBuffer and copies this SharedBuffer's contents to that
// ArrayBuffer without merging segmented buffers into a flat buffer.
- WEBCORE_EXPORT RefPtr<ArrayBuffer> createArrayBuffer() const;
+ RefPtr<ArrayBuffer> tryCreateArrayBuffer() const;
- WEBCORE_EXPORT unsigned size() const;
+ // FIXME: This should return a size_t.
+ unsigned size() const { return m_size; }
bool isEmpty() const { return !size(); }
- WEBCORE_EXPORT void append(SharedBuffer&);
- WEBCORE_EXPORT void append(const char*, unsigned);
- WEBCORE_EXPORT void append(Vector<char>&&);
-
- WEBCORE_EXPORT void clear();
-
- WEBCORE_EXPORT Ref<SharedBuffer> copy() const;
-
- // Return the number of consecutive bytes after "position". "data"
- // points to the first byte.
- // Return 0 when no more data left.
- // When extracting all data with getSomeData(), the caller should
- // repeat calling it until it returns 0.
- // Usage:
- // const char* segment;
- // unsigned pos = 0;
- // while (unsigned length = sharedBuffer->getSomeData(segment, pos)) {
- // // Use the data. for example: decoder->decode(segment, length);
- // pos += length;
- // }
- WEBCORE_EXPORT unsigned getSomeData(const char*& data, unsigned position = 0) const;
-
- bool tryReplaceContentsWithPlatformBuffer(SharedBuffer&);
- WEBCORE_EXPORT bool hasPlatformData() const;
-
- struct DataBuffer : public ThreadSafeRefCounted<DataBuffer> {
- Vector<char> data;
- };
-
- void hintMemoryNotNeededSoon();
-
-private:
- WEBCORE_EXPORT SharedBuffer();
- WEBCORE_EXPORT SharedBuffer(const char*, unsigned);
- WEBCORE_EXPORT SharedBuffer(const unsigned char*, unsigned);
- explicit SharedBuffer(MappedFileData&&);
-
- static RefPtr<SharedBuffer> createFromReadingFile(const String& filePath);
+ void append(const SharedBuffer&);
+ void append(const char*, size_t);
+ void append(Vector<char>&&);
- // Calling this function will force internal segmented buffers
- // to be merged into a flat buffer. Use getSomeData() whenever possible
- // for better performance.
- const Vector<char>& buffer() const;
+ void clear();
- void clearPlatformData();
- void maybeTransferPlatformData();
- bool maybeAppendPlatformData(SharedBuffer&);
+ Ref<SharedBuffer> copy() const;
- void maybeTransferMappedFileData();
+ // Data wrapped by a DataSegment should be immutable because it can be referenced by other objects.
+ // To modify or combine the data, allocate a new DataSegment.
+ class DataSegment : public ThreadSafeRefCounted<DataSegment> {
+ public:
+ const char* data() const;
+ size_t size() const;
- void copyBufferAndClear(char* destination, unsigned bytesToCopy) const;
-
- void appendToDataBuffer(const char *, unsigned) const;
- void duplicateDataBufferIfNecessary() const;
- void clearDataBuffer();
+ static Ref<DataSegment> create(Vector<char>&& data) { return adoptRef(*new DataSegment(WTFMove(data))); }
+#if USE(CF)
+ static Ref<DataSegment> create(RetainPtr<CFDataRef>&& data) { return adoptRef(*new DataSegment(WTFMove(data))); }
+#endif
+#if USE(SOUP)
+ static Ref<DataSegment> create(GUniquePtr<SoupBuffer>&& data) { return adoptRef(*new DataSegment(WTFMove(data))); }
+#endif
+ static Ref<DataSegment> create(MappedFileData&& data) { return adoptRef(*new DataSegment(WTFMove(data))); }
- unsigned m_size { 0 };
- mutable Ref<DataBuffer> m_buffer;
+ private:
+ DataSegment(Vector<char>&& data)
+ : m_immutableData(WTFMove(data)) { }
+#if USE(CF)
+ DataSegment(RetainPtr<CFDataRef>&& data)
+ : m_immutableData(WTFMove(data)) { }
+#endif
+#if USE(SOUP)
+ DataSegment(GUniquePtr<SoupBuffer>&& data)
+ : m_immutableData(WTFMove(data)) { }
+#endif
+ DataSegment(MappedFileData&& data)
+ : m_immutableData(WTFMove(data)) { }
-#if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
- mutable Vector<RetainPtr<CFDataRef>> m_dataArray;
- unsigned copySomeDataFromDataArray(const char*& someData, unsigned position) const;
- const char *singleDataArrayBuffer() const;
- bool maybeAppendDataArray(SharedBuffer&);
-#else
- mutable Vector<char*> m_segments;
+ Variant<Vector<char>,
+#if USE(CF)
+ RetainPtr<CFDataRef>,
+#endif
+#if USE(SOUP)
+ GUniquePtr<SoupBuffer>,
#endif
+ MappedFileData> m_immutableData;
+ friend class SharedBuffer;
+ };
- unsigned platformDataSize() const;
- const char* platformData() const;
+ using DataSegmentVector = Vector<Ref<DataSegment>, 1>;
+ DataSegmentVector::const_iterator begin() const { return m_segments.begin(); }
+ DataSegmentVector::const_iterator end() const { return m_segments.end(); }
+ void hintMemoryNotNeededSoon();
+
+private:
+ explicit SharedBuffer() = default;
+ explicit SharedBuffer(const char*, size_t);
+ explicit SharedBuffer(const unsigned char*, size_t);
+ explicit SharedBuffer(Vector<char>&&);
+ explicit SharedBuffer(MappedFileData&&);
#if USE(CF)
explicit SharedBuffer(CFDataRef);
- RetainPtr<CFDataRef> m_cfData;
- CFDataRef existingCFData();
#endif
-
#if USE(SOUP)
explicit SharedBuffer(SoupBuffer*);
- GUniquePtr<SoupBuffer> m_soupBuffer;
#endif
- MappedFileData m_fileData;
+ void combineIntoOneSegment() const;
+
+ static RefPtr<SharedBuffer> createFromReadingFile(const String& filePath);
+
+ size_t m_size { 0 };
+ mutable DataSegmentVector m_segments;
};
RefPtr<SharedBuffer> utf8Buffer(const String&);
#include "config.h"
#include "SharedBufferChunkReader.h"
+#if ENABLE(MHTML)
+
+// FIXME: This class is overkill. Remove this class and just iterate the segments of a SharedBuffer
+// using the cool new SharedBuffer::begin() and SharedBuffer::end() instead of using this class.
+
#include "SharedBuffer.h"
namespace WebCore {
// Read the next segment.
m_segmentIndex = 0;
m_bufferPosition += m_segmentLength;
- m_segmentLength = m_buffer->getSomeData(m_segment, m_bufferPosition);
+ // Let's pretend all the data is in one block.
+ // FIXME: This class should be removed in favor of just iterating the segments of the SharedBuffer.
+ m_segment = m_buffer->data() + m_bufferPosition;
+ m_segmentLength = m_buffer->size() - m_bufferPosition;
if (!m_segmentLength) {
m_reachedEndOfFile = true;
if (m_separatorIndex > 0)
size_t bufferPosition = m_bufferPosition + m_segmentLength;
const char* segment = 0;
- while (size_t segmentLength = m_buffer->getSomeData(segment, bufferPosition)) {
- if (requestedSize <= readBytesCount + segmentLength) {
- data.append(segment, requestedSize - readBytesCount);
- readBytesCount += (requestedSize - readBytesCount);
- break;
- }
+
+ // Let's pretend all the data is in one block.
+ // FIXME: This class should be removed in favor of just iterating the segments of the SharedBuffer.
+ if (bufferPosition != m_buffer->size()) {
+ segment = m_buffer->data() + bufferPosition;
+ size_t segmentLength = m_buffer->size() - bufferPosition;
+ if (segmentLength > requestedSize)
+ segmentLength = requestedSize;
data.append(segment, segmentLength);
readBytesCount += segmentLength;
bufferPosition += segmentLength;
}
}
+
+#endif
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef SharedBufferChunkReader_h
-#define SharedBufferChunkReader_h
+#pragma once
+
+#if ENABLE(MHTML)
#include <wtf/Vector.h>
#include <wtf/text/WTFString.h>
auto data = adoptCF(CFPropertyListCreateData(kCFAllocatorDefault, m_rootDictionary.get(), kCFPropertyListBinaryFormat_v1_0, 0, nullptr));
if (!data)
return nullptr;
- return SharedBuffer::wrapCFData(data.get());
+ return SharedBuffer::create(data.get());
}
} // namespace WebCore
namespace WebCore {
-SharedBuffer::SharedBuffer(CFDataRef cfData)
- : m_buffer(adoptRef(*new DataBuffer))
- , m_cfData(cfData)
+SharedBuffer::SharedBuffer(CFDataRef data)
{
+ append(data);
}
// Using Foundation allows for an even more efficient implementation of this function,
#if !USE(FOUNDATION)
RetainPtr<CFDataRef> SharedBuffer::createCFData()
{
- if (m_cfData)
- return m_cfData;
-
- // Internal data in SharedBuffer can be segmented. We need to get the contiguous buffer.
- const Vector<char>& contiguousBuffer = buffer();
- return adoptCF(CFDataCreate(0, reinterpret_cast<const UInt8*>(contiguousBuffer.data()), contiguousBuffer.size()));
+ if (m_segments.size() == 1) {
+ if (auto data = WTF::get_if<RetainPtr<CFDataRef>>(m_segments[0]->m_immutableData))
+ return *data;
+ }
+ return adoptCF(CFDataCreate(nullptr, reinterpret_cast<const UInt8*>(data()), size()));
}
#endif
-Ref<SharedBuffer> SharedBuffer::wrapCFData(CFDataRef data)
+Ref<SharedBuffer> SharedBuffer::create(CFDataRef data)
{
return adoptRef(*new SharedBuffer(data));
}
-bool SharedBuffer::hasPlatformData() const
-{
- return m_cfData;
-}
-
-const char* SharedBuffer::platformData() const
-{
- return reinterpret_cast<const char*>(CFDataGetBytePtr(m_cfData.get()));
-}
-
-unsigned SharedBuffer::platformDataSize() const
-{
- return CFDataGetLength(m_cfData.get());
-}
-
void SharedBuffer::hintMemoryNotNeededSoon()
{
- if (!hasPlatformData())
- return;
- OSAllocator::hintMemoryNotNeededSoon(const_cast<char*>(platformData()), platformDataSize());
-}
-
-void SharedBuffer::maybeTransferPlatformData()
-{
- if (!m_cfData)
- return;
-
- ASSERT(!m_size);
-
- // Hang on to the m_cfData pointer in a local pointer as append() will re-enter maybeTransferPlatformData()
- // and we need to make sure to early return when it does.
- RetainPtr<CFDataRef> cfData = adoptCF(m_cfData.leakRef());
-
- append(reinterpret_cast<const char*>(CFDataGetBytePtr(cfData.get())), CFDataGetLength(cfData.get()));
-}
-
-void SharedBuffer::clearPlatformData()
-{
- m_cfData = 0;
-}
-
-bool SharedBuffer::tryReplaceContentsWithPlatformBuffer(SharedBuffer& newContents)
-{
- if (!newContents.m_cfData)
- return false;
-
- clear();
- m_cfData = newContents.m_cfData;
- return true;
-}
-
-bool SharedBuffer::maybeAppendPlatformData(SharedBuffer& newContents)
-{
- if (size() || !newContents.m_cfData)
- return false;
- m_cfData = newContents.m_cfData;
- return true;
+ for (const auto& segment : m_segments) {
+ if (segment->hasOneRef()) {
+ if (auto data = WTF::get_if<RetainPtr<CFDataRef>>(segment->m_immutableData))
+ OSAllocator::hintMemoryNotNeededSoon(const_cast<UInt8*>(CFDataGetBytePtr(data->get())), CFDataGetLength(data->get()));
+ }
+ }
}
-#if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
void SharedBuffer::append(CFDataRef data)
{
ASSERT(data);
- m_dataArray.append(data);
m_size += CFDataGetLength(data);
+ m_segments.append(DataSegment::create(data));
}
-void SharedBuffer::copyBufferAndClear(char* destination, unsigned bytesToCopy) const
-{
- if (m_dataArray.isEmpty())
- return;
-
- CFIndex bytesLeft = bytesToCopy;
- for (auto& cfData : m_dataArray) {
- CFIndex dataLen = CFDataGetLength(cfData.get());
- ASSERT(bytesLeft >= dataLen);
- memcpy(destination, CFDataGetBytePtr(cfData.get()), dataLen);
- destination += dataLen;
- bytesLeft -= dataLen;
- }
- m_dataArray.clear();
-}
-
-unsigned SharedBuffer::copySomeDataFromDataArray(const char*& someData, unsigned position) const
-{
- unsigned totalOffset = 0;
- for (auto& cfData : m_dataArray) {
- unsigned dataLen = static_cast<unsigned>(CFDataGetLength(cfData.get()));
- ASSERT(totalOffset <= position);
- unsigned localOffset = position - totalOffset;
- if (localOffset < dataLen) {
- someData = reinterpret_cast<const char *>(CFDataGetBytePtr(cfData.get())) + localOffset;
- return dataLen - localOffset;
- }
- totalOffset += dataLen;
- }
- return 0;
-}
-
-const char *SharedBuffer::singleDataArrayBuffer() const
-{
- // If we had previously copied data into m_buffer in copyDataArrayAndClear() or some other
- // function, then we can't return a pointer to the CFDataRef buffer.
- if (m_buffer->data.size())
- return 0;
-
- if (m_dataArray.size() != 1)
- return 0;
-
- return reinterpret_cast<const char*>(CFDataGetBytePtr(m_dataArray.at(0).get()));
-}
-
-bool SharedBuffer::maybeAppendDataArray(SharedBuffer& data)
-{
- if (m_buffer->data.size() || m_cfData || !data.m_dataArray.size())
- return false;
-#if !ASSERT_DISABLED
- unsigned originalSize = size();
-#endif
- for (auto& cfData : data.m_dataArray)
- append(cfData.get());
- ASSERT(size() == originalSize + data.size());
- return true;
-}
-#endif
-
}
Ref<SharedBuffer> NetworkExtensionContentFilter::replacementData() const
{
ASSERT(didBlockData());
- return SharedBuffer::wrapNSData(m_replacementData.get());
+ return SharedBuffer::create(m_replacementData.get());
}
#if ENABLE(CONTENT_FILTERING)
Ref<SharedBuffer> ParentalControlsContentFilter::replacementData() const
{
ASSERT(didBlockData());
- return SharedBuffer::wrapNSData(m_replacementData.get());
+ return SharedBuffer::create(m_replacementData.get());
}
#if ENABLE(CONTENT_FILTERING)
@interface WebCoreSharedBufferData : NSData
{
- RefPtr<SharedBuffer::DataBuffer> sharedBufferDataBuffer;
+ RefPtr<const SharedBuffer::DataSegment> sharedBufferDataSegment;
}
-- (id)initWithSharedBufferDataBuffer:(SharedBuffer::DataBuffer*)dataBuffer;
+- (id)initWithSharedBufferDataSegment:(const SharedBuffer::DataSegment&)dataSegment;
@end
@implementation WebCoreSharedBufferData
[super dealloc];
}
-- (id)initWithSharedBufferDataBuffer:(SharedBuffer::DataBuffer*)dataBuffer
+- (id)initWithSharedBufferDataSegment:(const SharedBuffer::DataSegment&)dataSegment
{
self = [super init];
if (self)
- sharedBufferDataBuffer = dataBuffer;
+ sharedBufferDataSegment = &dataSegment;
return self;
}
- (NSUInteger)length
{
- return sharedBufferDataBuffer->data.size();
+ return sharedBufferDataSegment->size();
}
- (const void *)bytes
{
- return sharedBufferDataBuffer->data.data();
+ return sharedBufferDataSegment->data();
}
@end
namespace WebCore {
-Ref<SharedBuffer> SharedBuffer::wrapNSData(NSData *nsData)
+Ref<SharedBuffer> SharedBuffer::create(NSData *nsData)
{
return adoptRef(*new SharedBuffer((CFDataRef)nsData));
}
return adoptNS((NSData *)createCFData().leakRef());
}
-CFDataRef SharedBuffer::existingCFData()
-{
- if (m_cfData)
- return m_cfData.get();
-
-#if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
- if (m_dataArray.size() == 1)
- return m_dataArray.at(0).get();
-#endif
-
- return nullptr;
-}
-
RetainPtr<CFDataRef> SharedBuffer::createCFData()
{
- if (CFDataRef cfData = existingCFData())
- return cfData;
-
- data(); // Force data into m_buffer from segments or data array.
- return adoptCF((CFDataRef)adoptNS([[WebCoreSharedBufferData alloc] initWithSharedBufferDataBuffer:m_buffer.ptr()]).leakRef());
+ combineIntoOneSegment();
+ if (!m_segments.size())
+ return adoptCF(CFDataCreate(nullptr, nullptr, 0));
+ ASSERT(m_segments.size() == 1);
+ return adoptCF((CFDataRef)adoptNS([[WebCoreSharedBufferData alloc] initWithSharedBufferDataSegment:m_segments[0]]).leakRef());
}
RefPtr<SharedBuffer> SharedBuffer::createFromReadingFile(const String& filePath)
{
NSData *resourceData = [NSData dataWithContentsOfFile:filePath];
if (resourceData)
- return SharedBuffer::wrapNSData(resourceData);
+ return SharedBuffer::create(resourceData);
return nullptr;
}
RetainPtr<NSArray> SharedBuffer::createNSDataArray() const
{
- if (auto platformData = (NSData *)m_cfData.get())
- return @[ platformData ];
-
- if (m_fileData)
- return @[ [NSData dataWithBytes:m_fileData.data() length:m_fileData.size()] ];
-
- auto dataArray = adoptNS([[NSMutableArray alloc] init]);
- if (m_buffer->data.size())
- [dataArray addObject:adoptNS([[WebCoreSharedBufferData alloc] initWithSharedBufferDataBuffer:m_buffer.ptr()]).get()];
-
-#if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
- for (auto& data : m_dataArray)
- [dataArray addObject:(NSData *)data.get()];
-#else
- // Cocoa platforms all currently USE(NETWORK_CFDATA_ARRAY_CALLBACK), so implementing a code path for copying segments would be dead code.
- // If this ever changes, the following static_assert will detect it.
- static_assert(false, "FIXME: Copy the segments into an array of NSData objects.");
-#endif
-
+ auto dataArray = adoptNS([[NSMutableArray alloc] initWithCapacity:m_segments.size()]);
+ for (const auto& segment : m_segments)
+ [dataArray addObject:adoptNS([[WebCoreSharedBufferData alloc] initWithSharedBufferDataSegment:segment]).get()];
return WTFMove(dataArray);
}
responseOffset = static_cast<NSUInteger>(contentRange.firstBytePosition());
// Check for possible unsigned overflow.
- ASSERT([dataRequest currentOffset] >= [dataRequest requestedOffset]);
- ASSERT([dataRequest requestedLength] >= ([dataRequest currentOffset] - [dataRequest requestedOffset]));
-
- NSUInteger remainingLength = [dataRequest requestedLength] - static_cast<NSUInteger>([dataRequest currentOffset] - [dataRequest requestedOffset]);
- do {
- // Check to see if there is any data available in the buffer to fulfill the data request.
- if (data->size() <= [dataRequest currentOffset] - responseOffset)
- return;
-
- const char* someData;
- NSUInteger receivedLength = data->getSomeData(someData, static_cast<unsigned>([dataRequest currentOffset] - responseOffset));
-
- // Create an NSData with only as much of the received data as necessary to fulfill the request.
- NSUInteger length = MIN(receivedLength, remainingLength);
- RetainPtr<NSData> nsData = adoptNS([[NSData alloc] initWithBytes:someData length:length]);
-
- [dataRequest respondWithData:nsData.get()];
- remainingLength -= length;
- } while (remainingLength);
+ ASSERT(dataRequest.currentOffset >= dataRequest.requestedOffset);
+ ASSERT(dataRequest.requestedLength >= (dataRequest.currentOffset - dataRequest.requestedOffset));
+
+ NSUInteger remainingLength = dataRequest.requestedLength - static_cast<NSUInteger>(dataRequest.currentOffset - dataRequest.requestedOffset);
+
+ auto bytesToSkip = dataRequest.currentOffset - responseOffset;
+ RetainPtr<NSArray> array = data->createNSDataArray();
+ for (NSData *segment in array.get()) {
+ if (bytesToSkip) {
+ if (bytesToSkip > segment.length) {
+ bytesToSkip -= segment.length;
+ continue;
+ }
+ auto bytesToUse = segment.length - bytesToSkip;
+ [dataRequest respondWithData:[segment subdataWithRange:NSMakeRange(static_cast<NSUInteger>(bytesToSkip), static_cast<NSUInteger>(segment.length - bytesToSkip))]];
+ bytesToSkip = 0;
+ remainingLength -= bytesToUse;
+ continue;
+ }
+ if (segment.length <= remainingLength) {
+ [dataRequest respondWithData:segment];
+ remainingLength -= segment.length;
+ continue;
+ }
+ [dataRequest respondWithData:[segment subdataWithRange:NSMakeRange(0, remainingLength)]];
+ remainingLength = 0;
+ if (!remainingLength)
+ break;
+ }
- if ([dataRequest currentOffset] + [dataRequest requestedLength] >= [dataRequest requestedOffset]) {
+ if (dataRequest.currentOffset + dataRequest.requestedLength >= dataRequest.requestedOffset) {
[m_avRequest.get() finishLoading];
stopLoading();
}
RefPtr<SharedBuffer> FontPlatformData::openTypeTable(uint32_t table) const
{
if (RetainPtr<CFDataRef> data = adoptCF(CTFontCopyTable(font(), table, kCTFontTableOptionNoOptions)))
- return SharedBuffer::wrapCFData(data.get());
+ return SharedBuffer::create(data.get());
return nullptr;
}
void ResourceHandleStreamingClient::didReceiveBuffer(ResourceHandle*, Ref<SharedBuffer>&& buffer, int /* encodedLength */)
{
- // This pattern is suggested by SharedBuffer.h.
- const char* segment;
- unsigned position = 0;
- while (unsigned length = buffer->getSomeData(segment, position)) {
- handleDataReceived(segment, length);
- position += length;
- }
+ for (const auto& segment : buffer.get())
+ handleDataReceived(segment->data(), segment->size());
}
void ResourceHandleStreamingClient::didFinishLoading(ResourceHandle*)
NSData *namedImageData = [NSData dataWithContentsOfFile:imagePath];
if (namedImageData) {
auto image = BitmapImage::create();
- image->setData(SharedBuffer::wrapNSData(namedImageData), true);
+ image->setData(SharedBuffer::create(namedImageData), true);
return WTFMove(image);
}
namespace {
-unsigned copyFromSharedBuffer(char* buffer, unsigned bufferLength, const SharedBuffer& sharedBuffer, unsigned offset)
+static unsigned copyFromSharedBuffer(char* buffer, unsigned bufferLength, const SharedBuffer& sharedBuffer)
{
unsigned bytesExtracted = 0;
- const char* moreData;
- while (unsigned moreDataLength = sharedBuffer.getSomeData(moreData, offset)) {
- unsigned bytesToCopy = min(bufferLength - bytesExtracted, moreDataLength);
- memcpy(buffer + bytesExtracted, moreData, bytesToCopy);
- bytesExtracted += bytesToCopy;
- if (bytesExtracted == bufferLength)
+ for (const auto& segment : sharedBuffer) {
+ if (bytesExtracted + segment->size() <= bufferLength) {
+ memcpy(buffer + bytesExtracted, segment->data(), segment->size());
+ bytesExtracted += segment->size();
+ } else {
+ ASSERT(bufferLength - bytesExtracted < segment->size());
+ memcpy(buffer + bytesExtracted, segment->data(), bufferLength - bytesExtracted);
+ bytesExtracted = bufferLength;
break;
- offset += bytesToCopy;
+ }
}
return bytesExtracted;
}
{
static const unsigned lengthOfLongestSignature = 14; // To wit: "RIFF????WEBPVP"
char contents[lengthOfLongestSignature];
- unsigned length = copyFromSharedBuffer(contents, lengthOfLongestSignature, data, 0);
+ unsigned length = copyFromSharedBuffer(contents, lengthOfLongestSignature, data);
if (length < lengthOfLongestSignature)
return nullptr;
if (setjmp(JMPBUF(m_png)))
return decoder->setFailed();
- const char* segment;
- while (unsigned segmentLength = data.getSomeData(segment, m_readOffset)) {
- m_readOffset += segmentLength;
+ auto bytesToSkip = m_readOffset;
+ for (const auto& segment : data) {
+ if (bytesToSkip > segment->size()) {
+ bytesToSkip -= segment->size();
+ continue;
+ }
+ m_readOffset += segment->size();
m_currentBufferSize = m_readOffset;
- png_process_data(m_png, m_info, reinterpret_cast<png_bytep>(const_cast<char*>(segment)), segmentLength);
+ png_process_data(m_png, m_info, reinterpret_cast<png_bytep>(const_cast<char*>(segment->data() + bytesToSkip)), segment->size() - bytesToSkip);
+ bytesToSkip = 0;
// We explicitly specify the superclass encodedDataStatus() because we
// merely want to check if we've managed to set the size, not
// (recursively) trigger additional decoding if we haven't.
if (![pasteboardItem count])
return nullptr;
- return SharedBuffer::wrapNSData([pasteboardItem.get() objectAtIndex:0]);
+ return SharedBuffer::create([pasteboardItem.get() objectAtIndex:0]);
}
String PlatformPasteboard::readString(int index, const String& type)
if (!RTFDData)
return;
- newChangeCount = platformStrategies()->pasteboardStrategy()->setBufferForType(SharedBuffer::wrapNSData(RTFDData).ptr(), NSRTFDPboardType, pasteboardName);
+ newChangeCount = platformStrategies()->pasteboardStrategy()->setBufferForType(SharedBuffer::create(RTFDData).ptr(), NSRTFDPboardType, pasteboardName);
}
void Pasteboard::write(const PasteboardImage& pasteboardImage)
types.append(WebArchivePboardType);
m_changeCount = writeURLForTypes(types, m_pasteboardName, pasteboardImage.url);
- m_changeCount = platformStrategies()->pasteboardStrategy()->setBufferForType(SharedBuffer::wrapCFData(imageData).ptr(), NSTIFFPboardType, m_pasteboardName);
+ m_changeCount = platformStrategies()->pasteboardStrategy()->setBufferForType(SharedBuffer::create(imageData).ptr(), NSTIFFPboardType, m_pasteboardName);
if (pasteboardImage.dataInWebArchiveFormat)
m_changeCount = platformStrategies()->pasteboardStrategy()->setBufferForType(pasteboardImage.dataInWebArchiveFormat.get(), WebArchivePboardType, m_pasteboardName);
writeFileWrapperAsRTFDAttachment(fileWrapper(pasteboardImage), m_pasteboardName, m_changeCount);
NSData *data = [m_pasteboard.get() dataForType:pasteboardType];
if (!data)
return nullptr;
- return SharedBuffer::wrapNSData([[data copy] autorelease]);
+ return SharedBuffer::create([[data copy] autorelease]);
}
int PlatformPasteboard::numberOfFiles()
void BlobResourceHandle::notifyReceiveData(const char* data, int bytesRead)
{
if (client())
- client()->didReceiveBuffer(this, SharedBuffer::create(data, bytesRead), bytesRead);
+ client()->didReceiveBuffer(this, SharedBuffer::create(reinterpret_cast<const uint8_t*>(data), bytesRead), bytesRead);
}
void BlobResourceHandle::notifyFail(Error errorCode)
#include "config.h"
#include "MIMEHeader.h"
+#if ENABLE(MHTML)
+
#include "ParsedContentType.h"
#include "SharedBufferChunkReader.h"
#include <wtf/HashMap.h>
}
}
+
+#endif
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef MIMEHeader_h
-#define MIMEHeader_h
+#pragma once
+
+#if ENABLE(MHTML)
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
if (protectedThis->hasHandle() && m_handle->client()) {
LOG(Network, "CFNet - ResourceHandleCFURLConnectionDelegateWithOperationQueue::didReceiveData(handle=%p) (%s)", m_handle, m_handle->firstRequest().url().string().utf8().data());
- m_handle->client()->didReceiveBuffer(m_handle, SharedBuffer::wrapCFData(data), originalLength);
+ m_handle->client()->didReceiveBuffer(m_handle, SharedBuffer::create(data), originalLength);
}
CFRelease(data);
LOG(Network, "CFNet - SynchronousResourceHandleCFURLConnectionDelegate::didReceiveData(handle=%p, bytes=%ld) (%s)", m_handle, CFDataGetLength(data), m_handle->firstRequest().url().string().utf8().data());
if (ResourceHandleClient* client = m_handle->client())
- client->didReceiveBuffer(m_handle, SharedBuffer::wrapCFData(data), originalLength);
+ client->didReceiveBuffer(m_handle, SharedBuffer::create(data), originalLength);
}
void SynchronousResourceHandleCFURLConnectionDelegate::didFinishLoading()
// FIXME: https://bugs.webkit.org/show_bug.cgi?id=19793
// -1 means we do not provide any data about transfer size to inspector so it would use
// Content-Length headers or content size to show transfer size.
- m_handle->client()->didReceiveBuffer(m_handle, SharedBuffer::wrapNSData(data), -1);
+ m_handle->client()->didReceiveBuffer(m_handle, SharedBuffer::create(data), -1);
}
- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
// FIXME: https://bugs.webkit.org/show_bug.cgi?id=19793
// -1 means we do not provide any data about transfer size to inspector so it would use
// Content-Length headers or content size to show transfer size.
- m_handle->client()->didReceiveBuffer(m_handle, SharedBuffer::wrapNSData(data), -1);
+ m_handle->client()->didReceiveBuffer(m_handle, SharedBuffer::create(data), -1);
});
}
namespace WebCore {
SharedBuffer::SharedBuffer(SoupBuffer* soupBuffer)
- : m_buffer(*new DataBuffer)
- , m_soupBuffer(soupBuffer)
{
ASSERT(soupBuffer);
+ m_size = soupBuffer->length;
+ m_segments.append(DataSegment::create(GUniquePtr<SoupBuffer>(soupBuffer)));
}
Ref<SharedBuffer> SharedBuffer::wrapSoupBuffer(SoupBuffer* soupBuffer)
GUniquePtr<SoupBuffer> SharedBuffer::createSoupBuffer(unsigned offset, unsigned size)
{
- if (m_soupBuffer && !offset && !size) {
- GUniquePtr<SoupBuffer> buffer(soup_buffer_copy(m_soupBuffer.get()));
- return buffer;
- }
-
ref();
GUniquePtr<SoupBuffer> buffer(soup_buffer_new_with_owner(data() + offset, size ? size : this->size(), this, [](void* data) {
static_cast<SharedBuffer*>(data)->deref();
return buffer;
}
-void SharedBuffer::clearPlatformData()
-{
- m_soupBuffer.reset();
-}
-
-void SharedBuffer::maybeTransferPlatformData()
-{
- if (!m_soupBuffer)
- return;
-
- ASSERT(!m_size);
-
- // Hang on to the m_soupBuffer pointer in a local pointer as append() will re-enter maybeTransferPlatformData()
- // and we need to make sure to early return when it does.
- GUniquePtr<SoupBuffer> soupBuffer;
- soupBuffer.swap(m_soupBuffer);
-
- append(soupBuffer->data, soupBuffer->length);
-}
-
-bool SharedBuffer::hasPlatformData() const
-{
- return m_soupBuffer.get();
-}
-
-const char* SharedBuffer::platformData() const
-{
- return m_soupBuffer->data;
-}
-
-unsigned SharedBuffer::platformDataSize() const
-{
- return m_soupBuffer->length;
-}
-
-bool SharedBuffer::maybeAppendPlatformData(SharedBuffer&)
-{
- return false;
-}
-
-bool SharedBuffer::tryReplaceContentsWithPlatformBuffer(SharedBuffer& newContents)
-{
- if (!newContents.hasPlatformData())
- return false;
-
- clear();
- // FIXME: Use GRefPtr instead of GUniquePtr for the SoupBuffer.
- m_soupBuffer.swap(newContents.m_soupBuffer);
- return true;
-}
-
} // namespace WebCore
#endif
ASSERT(m_responseType == ResponseType::Arraybuffer);
ASSERT(doneWithoutErrors());
- auto result = m_binaryResponseBuilder ? m_binaryResponseBuilder->createArrayBuffer() : ArrayBuffer::create(nullptr, 0);
+ auto result = m_binaryResponseBuilder ? m_binaryResponseBuilder->tryCreateArrayBuffer() : ArrayBuffer::create(nullptr, 0);
m_binaryResponseBuilder = nullptr;
return result;
}
+2017-04-24 Alex Christensen <achristensen@webkit.org>
+
+ Reduce copies and allocations in SharedBuffer::append
+ https://bugs.webkit.org/show_bug.cgi?id=170956
+
+ Reviewed by Andreas Kling.
+
+ * WebView/WebArchive.mm:
+ (-[WebArchive initWithData:]):
+ * WebView/WebFrame.mm:
+ (-[WebFrame _loadData:MIMEType:textEncodingName:baseURL:unreachableURL:]):
+ * WebView/WebResource.mm:
+ (-[WebResource initWithCoder:]):
+ (-[WebResource _initWithData:URL:MIMEType:textEncodingName:frameName:response:copyData:]):
+
2017-04-24 Dan Bernstein <mitz@apple.com>
[Cocoa] Some ivars are needlessly @protected
#endif
_private = [[WebArchivePrivate alloc] init];
- auto coreArchive = LegacyWebArchive::create(SharedBuffer::wrapNSData(data));
+ auto coreArchive = LegacyWebArchive::create(SharedBuffer::create(data));
if (!coreArchive) {
[self release];
return nil;
ResourceRequest request(baseURL);
ResourceResponse response(responseURL, MIMEType, [data length], encodingName);
- SubstituteData substituteData(WebCore::SharedBuffer::wrapNSData(data), [unreachableURL absoluteURL], response, SubstituteData::SessionHistoryVisibility::Hidden);
+ SubstituteData substituteData(WebCore::SharedBuffer::create(data), [unreachableURL absoluteURL], response, SubstituteData::SessionHistoryVisibility::Hidden);
_private->coreFrame->loader().load(FrameLoadRequest(_private->coreFrame, request, ShouldOpenExternalURLsPolicy::ShouldNotAllow, substituteData));
}
return nil;
}
- auto coreResource = ArchiveResource::create(SharedBuffer::wrapNSData(data), url, mimeType, textEncoding, frameName, response);
+ auto coreResource = ArchiveResource::create(SharedBuffer::create(data), url, mimeType, textEncoding, frameName, response);
if (!coreResource) {
[self release];
return nil;
return nil;
}
- auto coreResource = ArchiveResource::create(SharedBuffer::wrapNSData(copyData ? [[data copy] autorelease] : data), URL, MIMEType, textEncodingName, frameName, response);
+ auto coreResource = ArchiveResource::create(SharedBuffer::create(copyData ? [[data copy] autorelease] : data), URL, MIMEType, textEncodingName, frameName, response);
if (!coreResource) {
[self release];
return nil;
+2017-04-24 Alex Christensen <achristensen@webkit.org>
+
+ Reduce copies and allocations in SharedBuffer::append
+ https://bugs.webkit.org/show_bug.cgi?id=170956
+
+ Reviewed by Andreas Kling.
+
+ * NetworkProcess/cocoa/NetworkSessionCocoa.mm:
+ (-[WKNetworkSessionDelegate URLSession:dataTask:didReceiveData:]):
+ * Platform/IPC/DataReference.cpp:
+ (IPC::SharedBufferDataReference::encode):
+ * Shared/ShareableResource.cpp:
+ (WebKit::ShareableResource::wrapInSharedBuffer):
+ * UIProcess/API/Cocoa/WKURLSchemeHandlerTask.mm:
+ (-[WKURLSchemeHandlerTaskImpl didReceiveData:]):
+ * WebProcess/InjectedBundle/API/mac/WKWebProcessPlugInBrowserContextController.mm:
+ (-[WKWebProcessPlugInBrowserContextController _setEditingDelegate:]):
+ * WebProcess/Plugins/PDF/PDFPlugin.mm:
+ (WebKit::PDFPlugin::addArchiveResource):
+ (WebKit::PDFPlugin::liveResourceData):
+ (WebKit::PDFPlugin::writeItemsToPasteboard):
+ * WebProcess/Plugins/PluginView.cpp:
+ (WebKit::PluginView::redeliverManualStream):
+ * WebProcess/WebCoreSupport/mac/WebDragClientMac.mm:
+ (WebKit::WebDragClient::declareAndWriteDragImage):
+ * WebProcess/WebPage/mac/WebPageMac.mm:
+ (WebKit::WebPage::cachedResponseDataForURL):
+
2017-04-24 Carlos Garcia Campos <cgarcia@igalia.com>
[GTK] Switch to use ENABLE_REMOTE_INSPECTOR instead of ENABLE_INSPECTOR_SERVER for the remote inspector
auto storedCredentials = _withCredentials ? WebCore::StoredCredentials::AllowStoredCredentials : WebCore::StoredCredentials::DoNotAllowStoredCredentials;
if (auto* networkDataTask = _session->dataTaskForIdentifier(dataTask.taskIdentifier, storedCredentials))
- networkDataTask->didReceiveData(WebCore::SharedBuffer::wrapNSData(data));
+ networkDataTask->didReceiveData(WebCore::SharedBuffer::create(data));
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
encoder.reserve(bufferSize + sizeof(uint64_t));
encoder << bufferSize;
- const char* partialData;
- unsigned position = 0;
- while (position < bufferSize) {
- unsigned bytesToWrite = m_buffer->getSomeData(partialData, position);
- encoder.encodeFixedLengthData(reinterpret_cast<const uint8_t*>(partialData), bytesToWrite, 1);
- position += bytesToWrite;
- }
+ for (const auto& segment : *m_buffer)
+ encoder.encodeFixedLengthData(reinterpret_cast<const uint8_t*>(segment->data()), segment->size(), 1);
}
} // namespace IPC
#if USE(CF)
RetainPtr<CFAllocatorRef> deallocator = adoptCF(createShareableResourceDeallocator(this));
RetainPtr<CFDataRef> cfData = adoptCF(CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data()), static_cast<CFIndex>(size()), deallocator.get()));
- return SharedBuffer::wrapCFData(cfData.get());
+ return SharedBuffer::create(cfData.get());
#elif USE(SOUP)
return SharedBuffer::wrapSoupBuffer(soup_buffer_new_with_owner(data(), size(), this, [](void* data) { static_cast<ShareableResource*>(data)->deref(); }));
#else
- (void)didReceiveData:(NSData *)data
{
- auto result = _urlSchemeHandlerTask->task().didReceiveData(WebCore::SharedBuffer::wrapNSData(data));
+ auto result = _urlSchemeHandlerTask->task().didReceiveData(WebCore::SharedBuffer::create(data));
raiseExceptionIfNecessary(result);
}
auto dataByType = [m_controller->_editingDelegate.get() _webProcessPlugInBrowserContextController:m_controller pasteboardDataForRange:wrapper(*InjectedBundleRangeHandle::getOrCreate(range).get())];
for (NSString *type in dataByType) {
pasteboardTypes.append(type);
- pasteboardData.append(SharedBuffer::wrapNSData(dataByType[type]));
+ pasteboardData.append(SharedBuffer::create(dataByType[type]));
};
}
RetainPtr<NSURLResponse> response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:m_sourceURL statusCode:200 HTTPVersion:(NSString*)kCFHTTPVersion1_1 headerFields:headers]);
ResourceResponse synthesizedResponse(response.get());
- RefPtr<ArchiveResource> resource = ArchiveResource::create(SharedBuffer::wrapCFData(m_data.get()), m_sourceURL, "application/pdf", String(), String(), synthesizedResponse);
+ RefPtr<ArchiveResource> resource = ArchiveResource::create(SharedBuffer::create(m_data.get()), m_sourceURL, "application/pdf", String(), String(), synthesizedResponse);
pluginView()->frame()->document()->loader()->addArchiveResource(resource.releaseNonNull());
}
if (!pdfData)
return nullptr;
- return SharedBuffer::wrapNSData(pdfData);
+ return SharedBuffer::create(pdfData);
}
bool PDFPlugin::pluginHandlesContentOffsetForAccessibilityHitTest() const
RetainPtr<NSString> plainTextString = adoptNS([[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
webProcess.parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::SetPasteboardStringForType(pasteboardName, type, plainTextString.get()), Messages::WebPasteboardProxy::SetPasteboardStringForType::Reply(newChangeCount), 0);
} else {
- RefPtr<SharedBuffer> buffer = SharedBuffer::wrapNSData(data);
+ RefPtr<SharedBuffer> buffer = SharedBuffer::create(data);
if (!buffer)
continue;
// Deliver the data.
if (m_manualStreamData) {
- const char* data;
- unsigned position = 0;
-
- while (unsigned length = m_manualStreamData->getSomeData(data, position)) {
- manualLoadDidReceiveData(data, length);
- position += length;
- }
-
+ for (const auto& segment : *m_manualStreamData)
+ manualLoadDidReceiveData(segment->data(), segment->size());
m_manualStreamData = nullptr;
}
SharedMemory::Handle archiveHandle;
size_t archiveSize = 0;
if (data) {
- RefPtr<SharedBuffer> archiveBuffer = SharedBuffer::wrapNSData((NSData *)data.get());
+ RefPtr<SharedBuffer> archiveBuffer = SharedBuffer::create((NSData *)data.get());
RefPtr<SharedMemory> archiveSharedMemoryBuffer = SharedMemory::allocate(archiveBuffer->size());
if (!archiveSharedMemoryBuffer)
return;
RefPtr<SharedBuffer> WebPage::cachedResponseDataForURL(const URL& url)
{
- return SharedBuffer::wrapNSData([cachedResponseForURL(this, url) data]);
+ return SharedBuffer::create([cachedResponseForURL(this, url) data]);
}
bool WebPage::platformCanHandleRequest(const WebCore::ResourceRequest& request)
+2017-04-24 Alex Christensen <achristensen@webkit.org>
+
+ Reduce copies and allocations in SharedBuffer::append
+ https://bugs.webkit.org/show_bug.cgi?id=170956
+
+ Reviewed by Andreas Kling.
+
+ * TestWebKitAPI/Tests/WebCore/cocoa/SharedBuffer.mm:
+ (TestWebKitAPI::TEST_F):
+
2017-04-24 Carlos Garcia Campos <cgarcia@igalia.com>
[GTK] Switch to use ENABLE_REMOTE_INSPECTOR instead of ENABLE_INSPECTOR_SERVER for the remote inspector
EXPECT_EQ('a', buffer->data()[strlen(SharedBufferTest::testData())]);
}
-TEST_F(SharedBufferTest, createArrayBuffer)
+TEST_F(SharedBufferTest, tryCreateArrayBuffer)
{
char testData0[] = "Hello";
char testData1[] = "World";
RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(testData0, strlen(testData0));
sharedBuffer->append(testData1, strlen(testData1));
sharedBuffer->append(testData2, strlen(testData2));
- RefPtr<ArrayBuffer> arrayBuffer = sharedBuffer->createArrayBuffer();
+ RefPtr<ArrayBuffer> arrayBuffer = sharedBuffer->tryCreateArrayBuffer();
char expectedConcatenation[] = "HelloWorldGoodbye";
ASSERT_EQ(strlen(expectedConcatenation), arrayBuffer->byteLength());
EXPECT_EQ(0, memcmp(expectedConcatenation, arrayBuffer->data(), strlen(expectedConcatenation)));
}
-TEST_F(SharedBufferTest, createArrayBufferLargeSegments)
+TEST_F(SharedBufferTest, tryCreateArrayBufferLargeSegments)
{
Vector<char> vector0(0x4000, 'a');
Vector<char> vector1(0x4000, 'b');
RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(WTFMove(vector0));
sharedBuffer->append(WTFMove(vector1));
sharedBuffer->append(WTFMove(vector2));
- RefPtr<ArrayBuffer> arrayBuffer = sharedBuffer->createArrayBuffer();
+ RefPtr<ArrayBuffer> arrayBuffer = sharedBuffer->tryCreateArrayBuffer();
ASSERT_EQ(0x4000U + 0x4000U + 0x4000U, arrayBuffer->byteLength());
int position = 0;
for (int i = 0; i < 0x4000; ++i) {
buffer->append((CFDataRef)worldData);
expectDataArraysEqual(@[ helloData, worldData ], buffer->createNSDataArray().get());
- expectDataArraysEqual(@[ helloData ], SharedBuffer::wrapNSData(helloData)->createNSDataArray().get());
- expectDataArraysEqual(@[ worldData ], SharedBuffer::wrapCFData((CFDataRef)worldData)->createNSDataArray().get());
+ expectDataArraysEqual(@[ helloData ], SharedBuffer::create(helloData)->createNSDataArray().get());
+ expectDataArraysEqual(@[ worldData ], SharedBuffer::create((CFDataRef)worldData)->createNSDataArray().get());
expectDataArraysEqual(@[ [NSData dataWithContentsOfFile:tempFilePath()] ], SharedBuffer::createWithContentsOfFile(tempFilePath())->createNSDataArray().get());
}