summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/cf
diff options
context:
space:
mode:
authorFeng Qian <fqian@google.com>2009-06-17 12:12:20 -0700
committerFeng Qian <fqian@google.com>2009-06-17 12:12:20 -0700
commit5f1ab04193ad0130ca8204aadaceae083aca9881 (patch)
tree5a92cd389e2cfe7fb67197ce14b38469462379f8 /WebCore/platform/cf
parent194315e5a908cc8ed67d597010544803eef1ac59 (diff)
downloadexternal_webkit-5f1ab04193ad0130ca8204aadaceae083aca9881.zip
external_webkit-5f1ab04193ad0130ca8204aadaceae083aca9881.tar.gz
external_webkit-5f1ab04193ad0130ca8204aadaceae083aca9881.tar.bz2
Get WebKit r44544.
Diffstat (limited to 'WebCore/platform/cf')
-rw-r--r--WebCore/platform/cf/BinaryPropertyList.cpp831
-rw-r--r--WebCore/platform/cf/BinaryPropertyList.h108
-rw-r--r--WebCore/platform/cf/SharedBufferCF.cpp5
3 files changed, 944 insertions, 0 deletions
diff --git a/WebCore/platform/cf/BinaryPropertyList.cpp b/WebCore/platform/cf/BinaryPropertyList.cpp
new file mode 100644
index 0000000..c0fda3d
--- /dev/null
+++ b/WebCore/platform/cf/BinaryPropertyList.cpp
@@ -0,0 +1,831 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "BinaryPropertyList.h"
+
+#include "StringHash.h"
+#include <wtf/HashSet.h>
+#include <limits>
+
+using namespace std;
+
+namespace WebCore {
+
+static const size_t headerSize = 8;
+static const size_t trailerSize = 32;
+
+static const UInt8 booleanTrueMarkerByte = 0x09;
+static const UInt8 oneByteIntegerMarkerByte = 0x10;
+static const UInt8 twoByteIntegerMarkerByte = 0x11;
+static const UInt8 fourByteIntegerMarkerByte = 0x12;
+static const UInt8 eightByteIntegerMarkerByte = 0x13;
+static const UInt8 asciiStringMarkerByte = 0x50;
+static const UInt8 asciiStringWithSeparateLengthMarkerByte = 0x5F;
+static const UInt8 unicodeStringMarkerByte = 0x60;
+static const UInt8 unicodeStringWithSeparateLengthMarkerByte = 0x6F;
+static const UInt8 arrayMarkerByte = 0xA0;
+static const UInt8 arrayWithSeparateLengthMarkerByte = 0xAF;
+static const UInt8 dictionaryMarkerByte = 0xD0;
+static const UInt8 dictionaryWithSeparateLengthMarkerByte = 0xDF;
+static const size_t maxLengthInMarkerByte = 0xE;
+
+class IntegerArray {
+public:
+ IntegerArray() : m_integers(0), m_size(0) { }
+ IntegerArray(const int* integers, size_t size) : m_integers(integers), m_size(size) { ASSERT(integers); ASSERT(size); }
+
+ void markDeleted() { m_integers = 0; m_size = deletedValueSize(); }
+ bool isDeletedValue() const { return m_size == deletedValueSize(); }
+
+ const int* integers() const { ASSERT(!isDeletedValue()); return m_integers; }
+ size_t size() const { ASSERT(!isDeletedValue()); return m_size; }
+
+private:
+ static size_t deletedValueSize() { return numeric_limits<size_t>::max(); }
+
+ friend bool operator==(const IntegerArray&, const IntegerArray&);
+
+ const int* m_integers;
+ size_t m_size;
+};
+
+inline bool operator==(const IntegerArray& a, const IntegerArray& b)
+{
+ return a.m_integers == b.m_integers && a.m_size == b.m_size;
+}
+
+struct IntegerArrayHashTraits : WTF::GenericHashTraits<IntegerArray> {
+ static const bool needsDestruction = false;
+ static void constructDeletedValue(IntegerArray& slot) { slot.markDeleted(); }
+ static bool isDeletedValue(const IntegerArray& array) { return array.isDeletedValue(); }
+};
+
+struct IntegerArrayHash {
+ static unsigned hash(const IntegerArray&);
+ static bool equal(const IntegerArray&, const IntegerArray&);
+ static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+unsigned IntegerArrayHash::hash(const IntegerArray& array)
+{
+ return StringImpl::computeHash(reinterpret_cast<const UChar*>(array.integers()), array.size() / (sizeof(int) / sizeof(UChar)));
+}
+
+bool IntegerArrayHash::equal(const IntegerArray& a, const IntegerArray& b)
+{
+ if (a.isDeletedValue() || b.isDeletedValue())
+ return a.isDeletedValue() == b.isDeletedValue();
+ if (a.size() != b.size())
+ return false;
+ for (size_t i = 0; i < a.size(); ++i) {
+ if (a.integers()[i] != b.integers()[i])
+ return false;
+ }
+ return true;
+}
+
+typedef size_t ObjectReference;
+
+class BinaryPropertyListPlan : private BinaryPropertyListObjectStream {
+public:
+ BinaryPropertyListPlan(BinaryPropertyListWriter&);
+
+ ObjectReference booleanTrueObjectReference() const;
+ ObjectReference integerObjectReference(int) const;
+ ObjectReference stringObjectReference(const String&) const;
+ ObjectReference integerArrayObjectReference(const int*, size_t) const;
+
+ ObjectReference objectCount() const { return m_currentObjectReference; }
+
+ ObjectReference byteCount() const { return m_byteCount; }
+ ObjectReference objectReferenceCount() const { return m_objectReferenceCount; }
+
+private:
+ virtual void writeBooleanTrue();
+ virtual void writeInteger(int);
+ virtual void writeString(const String&);
+ virtual void writeIntegerArray(const int*, size_t);
+ virtual void writeUniqueString(const String&);
+ virtual void writeUniqueString(const char*);
+ virtual size_t writeArrayStart();
+ virtual void writeArrayEnd(size_t);
+ virtual size_t writeDictionaryStart();
+ virtual void writeDictionaryEnd(size_t);
+
+ void writeArrayObject(size_t);
+ void writeDictionaryObject(size_t);
+ void writeStringObject(const String&);
+ void writeStringObject(const char*);
+
+ static ObjectReference invalidObjectReference() { return numeric_limits<ObjectReference>::max(); }
+
+ typedef HashMap<IntegerArray, ObjectReference, IntegerArrayHash, IntegerArrayHashTraits> IntegerArrayMap;
+
+ ObjectReference m_booleanTrueObjectReference;
+ ObjectReference m_integerZeroObjectReference;
+ HashMap<int, ObjectReference> m_integers;
+ HashMap<String, ObjectReference> m_strings;
+ IntegerArrayMap m_integerArrays;
+
+ ObjectReference m_currentObjectReference;
+
+ size_t m_currentAggregateSize;
+
+ size_t m_byteCount;
+ size_t m_objectReferenceCount;
+};
+
+BinaryPropertyListPlan::BinaryPropertyListPlan(BinaryPropertyListWriter& client)
+ : m_booleanTrueObjectReference(invalidObjectReference())
+ , m_integerZeroObjectReference(invalidObjectReference())
+ , m_currentObjectReference(0)
+ , m_currentAggregateSize(0)
+ , m_byteCount(0)
+ , m_objectReferenceCount(0)
+{
+ client.writeObjects(*this);
+ ASSERT(m_currentAggregateSize == 1);
+}
+
+void BinaryPropertyListPlan::writeBooleanTrue()
+{
+ ++m_currentAggregateSize;
+ if (m_booleanTrueObjectReference != invalidObjectReference())
+ return;
+ m_booleanTrueObjectReference = m_currentObjectReference++;
+ ++m_byteCount;
+}
+
+static inline int integerByteCount(size_t integer)
+{
+ if (integer <= 0xFF)
+ return 2;
+ if (integer <= 0xFFFF)
+ return 3;
+#ifdef __LP64__
+ if (integer <= 0xFFFFFFFFULL)
+ return 5;
+ return 9;
+#else
+ return 5;
+#endif
+}
+
+void BinaryPropertyListPlan::writeInteger(int integer)
+{
+ ASSERT(integer >= 0);
+ ++m_currentAggregateSize;
+ if (!integer) {
+ if (m_integerZeroObjectReference != invalidObjectReference())
+ return;
+ m_integerZeroObjectReference = m_currentObjectReference;
+ } else {
+ if (!m_integers.add(integer, m_currentObjectReference).second)
+ return;
+ }
+ ++m_currentObjectReference;
+ m_byteCount += integerByteCount(integer);
+}
+
+void BinaryPropertyListPlan::writeString(const String& string)
+{
+ ++m_currentAggregateSize;
+ if (!m_strings.add(string, m_currentObjectReference).second)
+ return;
+ ++m_currentObjectReference;
+ writeStringObject(string);
+}
+
+void BinaryPropertyListPlan::writeIntegerArray(const int* integers, size_t size)
+{
+ size_t savedAggregateSize = ++m_currentAggregateSize;
+ ASSERT(size);
+ pair<IntegerArrayMap::iterator, bool> addResult = m_integerArrays.add(IntegerArray(integers, size), 0);
+ if (!addResult.second)
+ return;
+ for (size_t i = 0; i < size; ++i)
+ writeInteger(integers[i]);
+ addResult.first->second = m_currentObjectReference++;
+ writeArrayObject(size);
+ m_currentAggregateSize = savedAggregateSize;
+}
+
+void BinaryPropertyListPlan::writeUniqueString(const String& string)
+{
+ ++m_currentAggregateSize;
+ ++m_currentObjectReference;
+ writeStringObject(string);
+}
+
+void BinaryPropertyListPlan::writeUniqueString(const char* string)
+{
+ ++m_currentAggregateSize;
+ ++m_currentObjectReference;
+ writeStringObject(string);
+}
+
+size_t BinaryPropertyListPlan::writeArrayStart()
+{
+ size_t savedAggregateSize = m_currentAggregateSize;
+ m_currentAggregateSize = 0;
+ return savedAggregateSize;
+}
+
+void BinaryPropertyListPlan::writeArrayEnd(size_t savedAggregateSize)
+{
+ ++m_currentObjectReference;
+ writeArrayObject(m_currentAggregateSize);
+ m_currentAggregateSize = savedAggregateSize + 1;
+}
+
+size_t BinaryPropertyListPlan::writeDictionaryStart()
+{
+ size_t savedAggregateSize = m_currentAggregateSize;
+ m_currentAggregateSize = 0;
+ return savedAggregateSize;
+}
+
+void BinaryPropertyListPlan::writeDictionaryEnd(size_t savedAggregateSize)
+{
+ ++m_currentObjectReference;
+ writeDictionaryObject(m_currentAggregateSize);
+ m_currentAggregateSize = savedAggregateSize + 1;
+}
+
+static size_t markerPlusLengthByteCount(size_t length)
+{
+ if (length <= maxLengthInMarkerByte)
+ return 1;
+ return 1 + integerByteCount(length);
+}
+
+void BinaryPropertyListPlan::writeStringObject(const String& string)
+{
+ const UChar* characters = string.characters();
+ unsigned length = string.length();
+ m_byteCount += markerPlusLengthByteCount(length) + length;
+ if (!charactersAreAllASCII(characters, length))
+ m_byteCount += length;
+}
+
+void BinaryPropertyListPlan::writeStringObject(const char* string)
+{
+ unsigned length = strlen(string);
+ m_byteCount += markerPlusLengthByteCount(length) + length;
+}
+
+void BinaryPropertyListPlan::writeArrayObject(size_t size)
+{
+ ASSERT(size);
+ m_byteCount += markerPlusLengthByteCount(size);
+ m_objectReferenceCount += size;
+}
+
+void BinaryPropertyListPlan::writeDictionaryObject(size_t size)
+{
+ ASSERT(size);
+ ASSERT(!(size & 1));
+ m_byteCount += markerPlusLengthByteCount(size / 2);
+ m_objectReferenceCount += size;
+}
+
+ObjectReference BinaryPropertyListPlan::booleanTrueObjectReference() const
+{
+ ASSERT(m_booleanTrueObjectReference != invalidObjectReference());
+ return m_booleanTrueObjectReference;
+}
+
+ObjectReference BinaryPropertyListPlan::integerObjectReference(int integer) const
+{
+ ASSERT(integer >= 0);
+ if (!integer) {
+ ASSERT(m_integerZeroObjectReference != invalidObjectReference());
+ return m_integerZeroObjectReference;
+ }
+ ASSERT(m_integers.contains(integer));
+ return m_integers.get(integer);
+}
+
+ObjectReference BinaryPropertyListPlan::stringObjectReference(const String& string) const
+{
+ ASSERT(m_strings.contains(string));
+ return m_strings.get(string);
+}
+
+ObjectReference BinaryPropertyListPlan::integerArrayObjectReference(const int* integers, size_t size) const
+{
+ ASSERT(m_integerArrays.contains(IntegerArray(integers, size)));
+ return m_integerArrays.get(IntegerArray(integers, size));
+}
+
+class BinaryPropertyListSerializer : private BinaryPropertyListObjectStream {
+public:
+ BinaryPropertyListSerializer(BinaryPropertyListWriter&);
+
+private:
+ virtual void writeBooleanTrue();
+ virtual void writeInteger(int);
+ virtual void writeString(const String&);
+ virtual void writeIntegerArray(const int*, size_t);
+ virtual void writeUniqueString(const String&);
+ virtual void writeUniqueString(const char*);
+ virtual size_t writeArrayStart();
+ virtual void writeArrayEnd(size_t);
+ virtual size_t writeDictionaryStart();
+ virtual void writeDictionaryEnd(size_t);
+
+ ObjectReference writeIntegerWithoutAddingAggregateObjectReference(int);
+
+ void appendIntegerObject(int);
+ void appendStringObject(const String&);
+ void appendStringObject(const char*);
+ void appendIntegerArrayObject(const int*, size_t);
+
+ void appendByte(unsigned char);
+ void appendByte(unsigned);
+ void appendByte(unsigned long);
+ void appendByte(int);
+
+ void appendInteger(size_t);
+
+ void appendObjectReference(ObjectReference);
+
+ void addAggregateObjectReference(ObjectReference);
+
+ void startObject();
+
+ const BinaryPropertyListPlan m_plan;
+ const int m_objectReferenceSize;
+ const size_t m_offsetTableStart;
+ const int m_offsetSize;
+ const size_t m_bufferSize;
+ UInt8* const m_buffer;
+
+ UInt8* m_currentByte;
+ ObjectReference m_currentObjectReference;
+ UInt8* m_currentAggregateBufferByte;
+};
+
+inline void BinaryPropertyListSerializer::appendByte(unsigned char byte)
+{
+ *m_currentByte++ = byte;
+ ASSERT(m_currentByte <= m_currentAggregateBufferByte);
+}
+
+inline void BinaryPropertyListSerializer::appendByte(unsigned byte)
+{
+ *m_currentByte++ = byte;
+ ASSERT(m_currentByte <= m_currentAggregateBufferByte);
+}
+
+inline void BinaryPropertyListSerializer::appendByte(unsigned long byte)
+{
+ *m_currentByte++ = byte;
+ ASSERT(m_currentByte <= m_currentAggregateBufferByte);
+}
+
+inline void BinaryPropertyListSerializer::appendByte(int byte)
+{
+ *m_currentByte++ = byte;
+ ASSERT(m_currentByte <= m_currentAggregateBufferByte);
+}
+
+static int bytesNeeded(size_t count)
+{
+ ASSERT(count);
+ int bytesNeeded = 1;
+ for (size_t mask = numeric_limits<size_t>::max() << 8; count & mask; mask <<= 8)
+ ++bytesNeeded;
+ return bytesNeeded;
+}
+
+static inline void storeLength(UInt8* destination, size_t length)
+{
+#ifdef __LP64__
+ destination[0] = length >> 56;
+ destination[1] = length >> 48;
+ destination[2] = length >> 40;
+ destination[3] = length >> 32;
+#else
+ destination[0] = 0;
+ destination[1] = 0;
+ destination[2] = 0;
+ destination[3] = 0;
+#endif
+ destination[4] = length >> 24;
+ destination[5] = length >> 16;
+ destination[6] = length >> 8;
+ destination[7] = length;
+}
+
+// Like memmove, but reverses the bytes.
+static void moveAndReverseBytes(UInt8* destination, const UInt8* source, size_t length)
+{
+ ASSERT(length);
+ memmove(destination, source, length);
+ UInt8* start = destination;
+ UInt8* end = destination + length;
+ while (end - start > 1)
+ std::swap(*start++, *--end);
+}
+
+// The serializer uses a single buffer for the property list.
+// The buffer contains:
+//
+// 8-byte header
+// object data
+// offset table
+// 32-byte trailer
+//
+// While serializing object, the offset table entry for each object is written just before
+// the object data for that object is written. Aggregates, arrays and dictionaries, are a
+// special case. The objects that go into an aggregate are written before the aggregate is.
+// As each object is written, the object reference is put in the aggregate buffer. Then,
+// when the aggregate is written, the aggregate buffer is copied into place in the object
+// data. Finally, the header and trailer are written.
+//
+// The aggregate buffer shares space with the object data, like this:
+//
+// 8-byte header
+// object data
+// >>> aggregate buffer <<<
+// offset table
+// 32-byte trailer
+//
+// To make it easy to build it incrementally, the buffer starts at the end of the object
+// data space, and grows backwards. We're guaranteed the aggregate buffer will never collide
+// with the object data pointer because we know that the object data is correctly sized
+// based on our plan, and all the data in the aggregate buffer will be used to create the
+// actual aggregate objects; in the worst case the aggregate buffer will already be in
+// exactly the right place, but backwards.
+
+BinaryPropertyListSerializer::BinaryPropertyListSerializer(BinaryPropertyListWriter& client)
+ : m_plan(client)
+ , m_objectReferenceSize(bytesNeeded(m_plan.objectCount()))
+ , m_offsetTableStart(headerSize + m_plan.byteCount() + m_plan.objectReferenceCount() * m_objectReferenceSize)
+ , m_offsetSize(bytesNeeded(m_offsetTableStart))
+ , m_bufferSize(m_offsetTableStart + m_plan.objectCount() * m_offsetSize + trailerSize)
+ , m_buffer(client.buffer(m_bufferSize))
+ , m_currentObjectReference(0)
+{
+ ASSERT(m_objectReferenceSize > 0);
+ ASSERT(m_offsetSize > 0);
+
+#ifdef __LP64__
+ ASSERT(m_objectReferenceSize <= 8);
+ ASSERT(m_offsetSize <= 8);
+#else
+ ASSERT(m_objectReferenceSize <= 4);
+ ASSERT(m_offsetSize <= 4);
+#endif
+
+ if (!m_buffer)
+ return;
+
+ // Write objects and offset table.
+ m_currentByte = m_buffer + headerSize;
+ m_currentAggregateBufferByte = m_buffer + m_offsetTableStart;
+ client.writeObjects(*this);
+ ASSERT(m_currentObjectReference == m_plan.objectCount());
+ ASSERT(m_currentAggregateBufferByte == m_buffer + m_offsetTableStart);
+ ASSERT(m_currentByte == m_buffer + m_offsetTableStart);
+
+ // Write header.
+ memcpy(m_buffer, "bplist00", headerSize);
+
+ // Write trailer.
+ UInt8* trailer = m_buffer + m_bufferSize - trailerSize;
+ memset(trailer, 0, 6);
+ trailer[6] = m_offsetSize;
+ trailer[7] = m_objectReferenceSize;
+ storeLength(trailer + 8, m_plan.objectCount());
+ storeLength(trailer + 16, m_plan.objectCount() - 1);
+ storeLength(trailer + 24, m_offsetTableStart);
+}
+
+void BinaryPropertyListSerializer::writeBooleanTrue()
+{
+ ObjectReference reference = m_plan.booleanTrueObjectReference();
+ if (m_currentObjectReference != reference)
+ ASSERT(reference < m_currentObjectReference);
+ else {
+ startObject();
+ appendByte(booleanTrueMarkerByte);
+ }
+ addAggregateObjectReference(reference);
+}
+
+inline ObjectReference BinaryPropertyListSerializer::writeIntegerWithoutAddingAggregateObjectReference(int integer)
+{
+ ObjectReference reference = m_plan.integerObjectReference(integer);
+ if (m_currentObjectReference != reference)
+ ASSERT(reference < m_currentObjectReference);
+ else
+ appendIntegerObject(integer);
+ return reference;
+}
+
+void BinaryPropertyListSerializer::writeInteger(int integer)
+{
+ addAggregateObjectReference(writeIntegerWithoutAddingAggregateObjectReference(integer));
+}
+
+void BinaryPropertyListSerializer::writeString(const String& string)
+{
+ ObjectReference reference = m_plan.stringObjectReference(string);
+ if (m_currentObjectReference != reference)
+ ASSERT(reference < m_currentObjectReference);
+ else
+ appendStringObject(string);
+ addAggregateObjectReference(reference);
+}
+
+void BinaryPropertyListSerializer::writeIntegerArray(const int* integers, size_t size)
+{
+ ObjectReference reference = m_plan.integerArrayObjectReference(integers, size);
+ for (size_t i = 0; i < size; ++i)
+ writeIntegerWithoutAddingAggregateObjectReference(integers[i]);
+ if (m_currentObjectReference != reference)
+ ASSERT(reference < m_currentObjectReference);
+ else
+ appendIntegerArrayObject(integers, size);
+ addAggregateObjectReference(reference);
+}
+
+void BinaryPropertyListSerializer::writeUniqueString(const char* string)
+{
+ addAggregateObjectReference(m_currentObjectReference);
+ appendStringObject(string);
+}
+
+void BinaryPropertyListSerializer::writeUniqueString(const String& string)
+{
+ addAggregateObjectReference(m_currentObjectReference);
+ appendStringObject(string);
+}
+
+size_t BinaryPropertyListSerializer::writeArrayStart()
+{
+ return m_currentAggregateBufferByte - m_buffer;
+}
+
+void BinaryPropertyListSerializer::writeArrayEnd(size_t savedAggregateBufferOffset)
+{
+ ObjectReference reference = m_currentObjectReference;
+ startObject();
+ size_t aggregateBufferByteCount = savedAggregateBufferOffset - (m_currentAggregateBufferByte - m_buffer);
+ ASSERT(aggregateBufferByteCount);
+ ASSERT(!(aggregateBufferByteCount % m_objectReferenceSize));
+ size_t size = aggregateBufferByteCount / m_objectReferenceSize;
+ if (size <= maxLengthInMarkerByte)
+ appendByte(arrayMarkerByte | size);
+ else {
+ appendByte(arrayWithSeparateLengthMarkerByte);
+ appendInteger(size);
+ }
+ m_currentAggregateBufferByte = m_buffer + savedAggregateBufferOffset;
+ ASSERT(m_currentByte <= m_currentAggregateBufferByte);
+ moveAndReverseBytes(m_currentByte, m_currentAggregateBufferByte - aggregateBufferByteCount, aggregateBufferByteCount);
+ m_currentByte += aggregateBufferByteCount;
+ ASSERT(m_currentByte <= m_currentAggregateBufferByte);
+ if (m_currentObjectReference < m_plan.objectCount())
+ addAggregateObjectReference(reference);
+ else
+ ASSERT(m_currentObjectReference == m_plan.objectCount());
+}
+
+size_t BinaryPropertyListSerializer::writeDictionaryStart()
+{
+ return m_currentAggregateBufferByte - m_buffer;
+}
+
+void BinaryPropertyListSerializer::writeDictionaryEnd(size_t savedAggregateBufferOffset)
+{
+ ObjectReference reference = m_currentObjectReference;
+ startObject();
+ size_t aggregateBufferByteCount = savedAggregateBufferOffset - (m_currentAggregateBufferByte - m_buffer);
+ ASSERT(aggregateBufferByteCount);
+ ASSERT(!(aggregateBufferByteCount % (m_objectReferenceSize * 2)));
+ size_t size = aggregateBufferByteCount / (m_objectReferenceSize * 2);
+ if (size <= maxLengthInMarkerByte)
+ appendByte(dictionaryMarkerByte | size);
+ else {
+ appendByte(dictionaryWithSeparateLengthMarkerByte);
+ appendInteger(size);
+ }
+ m_currentAggregateBufferByte = m_buffer + savedAggregateBufferOffset;
+ ASSERT(m_currentByte <= m_currentAggregateBufferByte);
+ moveAndReverseBytes(m_currentByte, m_currentAggregateBufferByte - aggregateBufferByteCount, aggregateBufferByteCount);
+ m_currentByte += aggregateBufferByteCount;
+ ASSERT(m_currentByte <= m_currentAggregateBufferByte);
+ if (m_currentObjectReference != m_plan.objectCount())
+ addAggregateObjectReference(reference);
+ else
+ ASSERT(m_currentObjectReference == m_plan.objectCount());
+}
+
+void BinaryPropertyListSerializer::appendIntegerObject(int integer)
+{
+ startObject();
+ ASSERT(integer >= 0);
+ appendInteger(integer);
+}
+
+void BinaryPropertyListSerializer::appendInteger(size_t integer)
+{
+ if (integer <= 0xFF) {
+ appendByte(oneByteIntegerMarkerByte);
+ appendByte(integer);
+ return;
+ }
+ if (integer <= 0xFFFF) {
+ appendByte(twoByteIntegerMarkerByte);
+ appendByte(integer >> 8);
+ appendByte(integer);
+ return;
+ }
+#ifdef __LP64__
+ if (integer <= 0xFFFFFFFFULL) {
+#endif
+ appendByte(fourByteIntegerMarkerByte);
+ appendByte(integer >> 24);
+ appendByte(integer >> 16);
+ appendByte(integer >> 8);
+ appendByte(integer);
+#ifdef __LP64__
+ return;
+ }
+ appendByte(eightByteIntegerMarkerByte);
+ appendByte(integer >> 56);
+ appendByte(integer >> 48);
+ appendByte(integer >> 40);
+ appendByte(integer >> 32);
+ appendByte(integer >> 24);
+ appendByte(integer >> 16);
+ appendByte(integer >> 8);
+ appendByte(integer);
+#endif
+}
+
+void BinaryPropertyListSerializer::appendStringObject(const String& string)
+{
+ startObject();
+ const UChar* characters = string.characters();
+ unsigned length = string.length();
+ if (charactersAreAllASCII(characters, length)) {
+ if (length <= maxLengthInMarkerByte)
+ appendByte(asciiStringMarkerByte | length);
+ else {
+ appendByte(asciiStringWithSeparateLengthMarkerByte);
+ appendInteger(length);
+ }
+ for (unsigned i = 0; i < length; ++i)
+ appendByte(characters[i]);
+ } else {
+ if (length <= maxLengthInMarkerByte)
+ appendByte(unicodeStringMarkerByte | length);
+ else {
+ appendByte(unicodeStringWithSeparateLengthMarkerByte);
+ appendInteger(length);
+ }
+ for (unsigned i = 0; i < length; ++i) {
+ appendByte(characters[i] >> 8);
+ appendByte(characters[i]);
+ }
+ }
+}
+
+void BinaryPropertyListSerializer::appendStringObject(const char* string)
+{
+ startObject();
+ unsigned length = strlen(string);
+ if (length <= maxLengthInMarkerByte)
+ appendByte(asciiStringMarkerByte | length);
+ else {
+ appendByte(asciiStringWithSeparateLengthMarkerByte);
+ appendInteger(length);
+ }
+ for (unsigned i = 0; i < length; ++i)
+ appendByte(string[i]);
+}
+
+void BinaryPropertyListSerializer::appendIntegerArrayObject(const int* integers, size_t size)
+{
+ startObject();
+ if (size <= maxLengthInMarkerByte)
+ appendByte(arrayMarkerByte | size);
+ else {
+ appendByte(arrayWithSeparateLengthMarkerByte);
+ appendInteger(size);
+ }
+ for (unsigned i = 0; i < size; ++i)
+ appendObjectReference(m_plan.integerObjectReference(integers[i]));
+}
+
+void BinaryPropertyListSerializer::appendObjectReference(ObjectReference reference)
+{
+ switch (m_objectReferenceSize) {
+#ifdef __LP64__
+ case 8:
+ appendByte(reference >> 56);
+ case 7:
+ appendByte(reference >> 48);
+ case 6:
+ appendByte(reference >> 40);
+ case 5:
+ appendByte(reference >> 32);
+#endif
+ case 4:
+ appendByte(reference >> 24);
+ case 3:
+ appendByte(reference >> 16);
+ case 2:
+ appendByte(reference >> 8);
+ case 1:
+ appendByte(reference);
+ }
+}
+
+void BinaryPropertyListSerializer::startObject()
+{
+ ObjectReference reference = m_currentObjectReference++;
+
+ size_t offset = m_currentByte - m_buffer;
+
+ UInt8* offsetTableEntry = m_buffer + m_offsetTableStart + reference * m_offsetSize + m_offsetSize;
+ switch (m_offsetSize) {
+#ifdef __LP64__
+ case 8:
+ offsetTableEntry[-8] = offset >> 56;
+ case 7:
+ offsetTableEntry[-7] = offset >> 48;
+ case 6:
+ offsetTableEntry[-6] = offset >> 40;
+ case 5:
+ offsetTableEntry[-5] = offset >> 32;
+#endif
+ case 4:
+ offsetTableEntry[-4] = offset >> 24;
+ case 3:
+ offsetTableEntry[-3] = offset >> 16;
+ case 2:
+ offsetTableEntry[-2] = offset >> 8;
+ case 1:
+ offsetTableEntry[-1] = offset;
+ }
+}
+
+void BinaryPropertyListSerializer::addAggregateObjectReference(ObjectReference reference)
+{
+ switch (m_objectReferenceSize) {
+#ifdef __LP64__
+ case 8:
+ *--m_currentAggregateBufferByte = reference >> 56;
+ case 7:
+ *--m_currentAggregateBufferByte = reference >> 48;
+ case 6:
+ *--m_currentAggregateBufferByte = reference >> 40;
+ case 5:
+ *--m_currentAggregateBufferByte = reference >> 32;
+#endif
+ case 4:
+ *--m_currentAggregateBufferByte = reference >> 24;
+ case 3:
+ *--m_currentAggregateBufferByte = reference >> 16;
+ case 2:
+ *--m_currentAggregateBufferByte = reference >> 8;
+ case 1:
+ *--m_currentAggregateBufferByte = reference;
+ }
+ ASSERT(m_currentByte <= m_currentAggregateBufferByte);
+}
+
+void BinaryPropertyListWriter::writePropertyList()
+{
+ BinaryPropertyListSerializer(*this);
+}
+
+}
diff --git a/WebCore/platform/cf/BinaryPropertyList.h b/WebCore/platform/cf/BinaryPropertyList.h
new file mode 100644
index 0000000..598aaa7
--- /dev/null
+++ b/WebCore/platform/cf/BinaryPropertyList.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BinaryPropertyList_h
+#define BinaryPropertyList_h
+
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class String;
+
+// Writes a limited subset of binary property lists.
+// Covers only what's needed for writing browser history as of this writing.
+class BinaryPropertyListObjectStream {
+public:
+ // Call writeBooleanTrue to write the boolean true value.
+ // A single shared object will be used in the serialized list.
+ virtual void writeBooleanTrue() = 0;
+
+ // Call writeInteger to write an integer value.
+ // A single shared object will be used for each integer in the serialized list.
+ virtual void writeInteger(int) = 0;
+
+ // Call writeString to write a string value.
+ // A single shared object will be used for each string in the serialized list.
+ virtual void writeString(const String&) = 0;
+
+ // Call writeUniqueString instead of writeString when it's unlikely the
+ // string will be written twice in the same property list; this saves hash
+ // table overhead for such strings. A separate object will be used for each
+ // of these strings in the serialized list.
+ virtual void writeUniqueString(const String&) = 0;
+ virtual void writeUniqueString(const char*) = 0;
+
+ // Call writeIntegerArray instead of writeArrayStart/writeArrayEnd for
+ // arrays entirely composed of integers. A single shared object will be used
+ // for each identical array in the serialized list. Warning: The integer
+ // pointer must remain valid until the writeBinaryPropertyList function
+ // returns, because these lists are put into a hash table without copying
+ // them -- that's OK if the client already has a Vector<int>.
+ virtual void writeIntegerArray(const int*, size_t) = 0;
+
+ // After calling writeArrayStart, write array elements.
+ // Then call writeArrayEnd, passing in the result from writeArrayStart.
+ // A separate object will be used for each of these arrays in the serialized list.
+ virtual size_t writeArrayStart() = 0;
+ virtual void writeArrayEnd(size_t resultFromWriteArrayStart) = 0;
+
+ // After calling writeDictionaryStart, write all keys, then all values.
+ // Then call writeDictionaryEnd, passing in the result from writeDictionaryStart.
+ // A separate object will be used for each dictionary in the serialized list.
+ virtual size_t writeDictionaryStart() = 0;
+ virtual void writeDictionaryEnd(size_t resultFromWriteDictionaryStart) = 0;
+
+protected:
+ virtual ~BinaryPropertyListObjectStream() { }
+};
+
+class BinaryPropertyListWriter {
+public:
+ // Calls writeObjects once to prepare for writing and determine how big a
+ // buffer is required. Then calls buffer to get the appropriately-sized
+ // buffer, then calls writeObjects a second time and writes the property list.
+ void writePropertyList();
+
+protected:
+ virtual ~BinaryPropertyListWriter() { }
+
+private:
+ // Called by writePropertyList.
+ // Must call the object stream functions for the objects to be written
+ // into the property list.
+ virtual void writeObjects(BinaryPropertyListObjectStream&) = 0;
+
+ // Called by writePropertyList.
+ // Returns the buffer that the writer should write into.
+ virtual UInt8* buffer(size_t) = 0;
+
+ friend class BinaryPropertyListPlan;
+ friend class BinaryPropertyListSerializer;
+};
+
+}
+
+#endif
diff --git a/WebCore/platform/cf/SharedBufferCF.cpp b/WebCore/platform/cf/SharedBufferCF.cpp
index 7213c7e..26fc07f 100644
--- a/WebCore/platform/cf/SharedBufferCF.cpp
+++ b/WebCore/platform/cf/SharedBufferCF.cpp
@@ -51,6 +51,11 @@ CFDataRef SharedBuffer::createCFData()
}
#endif
+PassRefPtr<SharedBuffer> SharedBuffer::wrapCFData(CFDataRef data)
+{
+ return adoptRef(new SharedBuffer(data));
+}
+
bool SharedBuffer::hasPlatformData() const
{
return m_cfData;