diff options
Diffstat (limited to 'Source/WTF/wtf/persistence')
-rw-r--r-- | Source/WTF/wtf/persistence/Coder.h | 47 | ||||
-rw-r--r-- | Source/WTF/wtf/persistence/Coders.cpp | 156 | ||||
-rw-r--r-- | Source/WTF/wtf/persistence/Coders.h | 302 | ||||
-rw-r--r-- | Source/WTF/wtf/persistence/Decoder.cpp | 133 | ||||
-rw-r--r-- | Source/WTF/wtf/persistence/Decoder.h | 100 | ||||
-rw-r--r-- | Source/WTF/wtf/persistence/Encoder.cpp | 126 | ||||
-rw-r--r-- | Source/WTF/wtf/persistence/Encoder.h | 114 |
7 files changed, 978 insertions, 0 deletions
diff --git a/Source/WTF/wtf/persistence/Coder.h b/Source/WTF/wtf/persistence/Coder.h new file mode 100644 index 000000000..f7d98c4ed --- /dev/null +++ b/Source/WTF/wtf/persistence/Coder.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2010, 2014 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. AND ITS CONTRIBUTORS ``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 ITS 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. + */ + +#pragma once + +namespace WTF { +namespace Persistence { + +class Decoder; +class Encoder; + +template<typename T> struct Coder { + static void encode(Encoder& encoder, const T& t) + { + t.encode(encoder); + } + + static bool decode(Decoder& decoder, T& t) + { + return T::decode(decoder, t); + } +}; + +} +} diff --git a/Source/WTF/wtf/persistence/Coders.cpp b/Source/WTF/wtf/persistence/Coders.cpp new file mode 100644 index 000000000..7cd42f488 --- /dev/null +++ b/Source/WTF/wtf/persistence/Coders.cpp @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2011, 2014-2015 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. AND ITS CONTRIBUTORS ``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 ITS 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 "Coders.h" + +#include <wtf/text/CString.h> +#include <wtf/text/WTFString.h> + +namespace WTF { +namespace Persistence { + +void Coder<AtomicString>::encode(Encoder& encoder, const AtomicString& atomicString) +{ + encoder << atomicString.string(); +} + +bool Coder<AtomicString>::decode(Decoder& decoder, AtomicString& atomicString) +{ + String string; + if (!decoder.decode(string)) + return false; + + atomicString = string; + return true; +} + +void Coder<CString>::encode(Encoder& encoder, const CString& string) +{ + // Special case the null string. + if (string.isNull()) { + encoder << std::numeric_limits<uint32_t>::max(); + return; + } + + uint32_t length = string.length(); + encoder << length; + encoder.encodeFixedLengthData(reinterpret_cast<const uint8_t*>(string.data()), length); +} + +bool Coder<CString>::decode(Decoder& decoder, CString& result) +{ + uint32_t length; + if (!decoder.decode(length)) + return false; + + if (length == std::numeric_limits<uint32_t>::max()) { + // This is the null string. + result = CString(); + return true; + } + + // Before allocating the string, make sure that the decoder buffer is big enough. + if (!decoder.bufferIsLargeEnoughToContain<char>(length)) + return false; + + char* buffer; + CString string = CString::newUninitialized(length, buffer); + if (!decoder.decodeFixedLengthData(reinterpret_cast<uint8_t*>(buffer), length)) + return false; + + result = string; + return true; +} + + +void Coder<String>::encode(Encoder& encoder, const String& string) +{ + // Special case the null string. + if (string.isNull()) { + encoder << std::numeric_limits<uint32_t>::max(); + return; + } + + uint32_t length = string.length(); + bool is8Bit = string.is8Bit(); + + encoder << length << is8Bit; + + if (is8Bit) + encoder.encodeFixedLengthData(reinterpret_cast<const uint8_t*>(string.characters8()), length * sizeof(LChar)); + else + encoder.encodeFixedLengthData(reinterpret_cast<const uint8_t*>(string.characters16()), length * sizeof(UChar)); +} + +template <typename CharacterType> +static inline bool decodeStringText(Decoder& decoder, uint32_t length, String& result) +{ + // Before allocating the string, make sure that the decoder buffer is big enough. + if (!decoder.bufferIsLargeEnoughToContain<CharacterType>(length)) + return false; + + CharacterType* buffer; + String string = String::createUninitialized(length, buffer); + if (!decoder.decodeFixedLengthData(reinterpret_cast<uint8_t*>(buffer), length * sizeof(CharacterType))) + return false; + + result = string; + return true; +} + +bool Coder<String>::decode(Decoder& decoder, String& result) +{ + uint32_t length; + if (!decoder.decode(length)) + return false; + + if (length == std::numeric_limits<uint32_t>::max()) { + // This is the null string. + result = String(); + return true; + } + + bool is8Bit; + if (!decoder.decode(is8Bit)) + return false; + + if (is8Bit) + return decodeStringText<LChar>(decoder, length, result); + return decodeStringText<UChar>(decoder, length, result); +} + +void Coder<SHA1::Digest>::encode(Encoder& encoder, const SHA1::Digest& digest) +{ + encoder.encodeFixedLengthData(digest.data(), sizeof(digest)); +} + +bool Coder<SHA1::Digest>::decode(Decoder& decoder, SHA1::Digest& digest) +{ + return decoder.decodeFixedLengthData(digest.data(), sizeof(digest)); +} + +} +} diff --git a/Source/WTF/wtf/persistence/Coders.h b/Source/WTF/wtf/persistence/Coders.h new file mode 100644 index 000000000..3cde70a7f --- /dev/null +++ b/Source/WTF/wtf/persistence/Coders.h @@ -0,0 +1,302 @@ +/* + * Copyright (C) 2010, 2014-2015 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. AND ITS CONTRIBUTORS ``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 ITS 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. + */ + +#pragma once + +#include <utility> +#include <wtf/Forward.h> +#include <wtf/HashMap.h> +#include <wtf/HashSet.h> +#include <wtf/SHA1.h> +#include <wtf/Vector.h> +#include <wtf/persistence/Decoder.h> +#include <wtf/persistence/Encoder.h> + +namespace WTF { +namespace Persistence { + +template<typename T, typename U> struct Coder<std::pair<T, U>> { + static void encode(Encoder& encoder, const std::pair<T, U>& pair) + { + encoder << pair.first << pair.second; + } + + static bool decode(Decoder& decoder, std::pair<T, U>& pair) + { + T first; + if (!decoder.decode(first)) + return false; + + U second; + if (!decoder.decode(second)) + return false; + + pair.first = first; + pair.second = second; + return true; + } +}; + +template<typename Rep, typename Period> struct Coder<std::chrono::duration<Rep, Period>> { + static void encode(Encoder& encoder, const std::chrono::duration<Rep, Period>& duration) + { + static_assert(std::is_integral<Rep>::value && std::is_signed<Rep>::value && sizeof(Rep) <= sizeof(int64_t), "Serialization of this Rep type is not supported yet. Only signed integer type which can be fit in an int64_t is currently supported."); + encoder << static_cast<int64_t>(duration.count()); + } + + static bool decode(Decoder& decoder, std::chrono::duration<Rep, Period>& result) + { + int64_t count; + if (!decoder.decode(count)) + return false; + result = std::chrono::duration<Rep, Period>(static_cast<Rep>(count)); + return true; + } +}; + +template<typename T> struct Coder<std::optional<T>> { + static void encode(Encoder& encoder, const std::optional<T>& optional) + { + if (!optional) { + encoder << false; + return; + } + + encoder << true; + encoder << optional.value(); + } + + static bool decode(Decoder& decoder, std::optional<T>& optional) + { + bool isEngaged; + if (!decoder.decode(isEngaged)) + return false; + + if (!isEngaged) { + optional = std::nullopt; + return true; + } + + T value; + if (!decoder.decode(value)) + return false; + + optional = WTFMove(value); + return true; + } +}; + +template<typename KeyType, typename ValueType> struct Coder<WTF::KeyValuePair<KeyType, ValueType>> { + static void encode(Encoder& encoder, const WTF::KeyValuePair<KeyType, ValueType>& pair) + { + encoder << pair.key << pair.value; + } + + static bool decode(Decoder& decoder, WTF::KeyValuePair<KeyType, ValueType>& pair) + { + KeyType key; + if (!decoder.decode(key)) + return false; + + ValueType value; + if (!decoder.decode(value)) + return false; + + pair.key = key; + pair.value = value; + return true; + } +}; + +template<bool fixedSizeElements, typename T, size_t inlineCapacity> struct VectorCoder; + +template<typename T, size_t inlineCapacity> struct VectorCoder<false, T, inlineCapacity> { + static void encode(Encoder& encoder, const Vector<T, inlineCapacity>& vector) + { + encoder << static_cast<uint64_t>(vector.size()); + for (size_t i = 0; i < vector.size(); ++i) + encoder << vector[i]; + } + + static bool decode(Decoder& decoder, Vector<T, inlineCapacity>& vector) + { + uint64_t size; + if (!decoder.decode(size)) + return false; + + Vector<T, inlineCapacity> tmp; + for (size_t i = 0; i < size; ++i) { + T element; + if (!decoder.decode(element)) + return false; + + tmp.append(WTFMove(element)); + } + + tmp.shrinkToFit(); + vector.swap(tmp); + return true; + } +}; + +template<typename T, size_t inlineCapacity> struct VectorCoder<true, T, inlineCapacity> { + static void encode(Encoder& encoder, const Vector<T, inlineCapacity>& vector) + { + encoder << static_cast<uint64_t>(vector.size()); + encoder.encodeFixedLengthData(reinterpret_cast<const uint8_t*>(vector.data()), vector.size() * sizeof(T), alignof(T)); + } + + static bool decode(Decoder& decoder, Vector<T, inlineCapacity>& vector) + { + uint64_t size; + if (!decoder.decode(size)) + return false; + + // Since we know the total size of the elements, we can allocate the vector in + // one fell swoop. Before allocating we must however make sure that the decoder buffer + // is big enough. + if (!decoder.bufferIsLargeEnoughToContain<T>(size)) + return false; + + Vector<T, inlineCapacity> temp; + temp.resize(size); + + decoder.decodeFixedLengthData(reinterpret_cast<uint8_t*>(temp.data()), size * sizeof(T)); + + vector.swap(temp); + return true; + } +}; + +template<typename T, size_t inlineCapacity> struct Coder<Vector<T, inlineCapacity>> : VectorCoder<std::is_arithmetic<T>::value, T, inlineCapacity> { }; + +template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg> struct Coder<HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>> { + typedef HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> HashMapType; + + static void encode(Encoder& encoder, const HashMapType& hashMap) + { + encoder << static_cast<uint64_t>(hashMap.size()); + for (typename HashMapType::const_iterator it = hashMap.begin(), end = hashMap.end(); it != end; ++it) + encoder << *it; + } + + static bool decode(Decoder& decoder, HashMapType& hashMap) + { + uint64_t hashMapSize; + if (!decoder.decode(hashMapSize)) + return false; + + HashMapType tempHashMap; + for (uint64_t i = 0; i < hashMapSize; ++i) { + KeyArg key; + MappedArg value; + if (!decoder.decode(key)) + return false; + if (!decoder.decode(value)) + return false; + + if (!tempHashMap.add(key, value).isNewEntry) { + // The hash map already has the specified key, bail. + return false; + } + } + + hashMap.swap(tempHashMap); + return true; + } +}; + +template<typename KeyArg, typename HashArg, typename KeyTraitsArg> struct Coder<HashSet<KeyArg, HashArg, KeyTraitsArg>> { + typedef HashSet<KeyArg, HashArg, KeyTraitsArg> HashSetType; + + static void encode(Encoder& encoder, const HashSetType& hashSet) + { + encoder << static_cast<uint64_t>(hashSet.size()); + for (typename HashSetType::const_iterator it = hashSet.begin(), end = hashSet.end(); it != end; ++it) + encoder << *it; + } + + static bool decode(Decoder& decoder, HashSetType& hashSet) + { + uint64_t hashSetSize; + if (!decoder.decode(hashSetSize)) + return false; + + HashSetType tempHashSet; + for (uint64_t i = 0; i < hashSetSize; ++i) { + KeyArg key; + if (!decoder.decode(key)) + return false; + + if (!tempHashSet.add(key).isNewEntry) { + // The hash map already has the specified key, bail. + return false; + } + } + + hashSet.swap(tempHashSet); + return true; + } +}; + +template<> struct Coder<std::chrono::system_clock::time_point> { + static void encode(Encoder& encoder, const std::chrono::system_clock::time_point& timePoint) + { + encoder << static_cast<int64_t>(timePoint.time_since_epoch().count()); + } + + static bool decode(Decoder& decoder, std::chrono::system_clock::time_point& result) + { + int64_t time; + if (!decoder.decode(time)) + return false; + + result = std::chrono::system_clock::time_point(std::chrono::system_clock::duration(static_cast<std::chrono::system_clock::rep>(time))); + return true; + } +}; + +template<> struct Coder<AtomicString> { + WTF_EXPORT_PRIVATE static void encode(Encoder&, const AtomicString&); + WTF_EXPORT_PRIVATE static bool decode(Decoder&, AtomicString&); +}; + +template<> struct Coder<CString> { + WTF_EXPORT_PRIVATE static void encode(Encoder&, const CString&); + WTF_EXPORT_PRIVATE static bool decode(Decoder&, CString&); +}; + +template<> struct Coder<String> { + WTF_EXPORT_PRIVATE static void encode(Encoder&, const String&); + WTF_EXPORT_PRIVATE static bool decode(Decoder&, String&); +}; + +template<> struct Coder<SHA1::Digest> { + WTF_EXPORT_PRIVATE static void encode(Encoder&, const SHA1::Digest&); + WTF_EXPORT_PRIVATE static bool decode(Decoder&, SHA1::Digest&); +}; + +} +} diff --git a/Source/WTF/wtf/persistence/Decoder.cpp b/Source/WTF/wtf/persistence/Decoder.cpp new file mode 100644 index 000000000..354ff0606 --- /dev/null +++ b/Source/WTF/wtf/persistence/Decoder.cpp @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2010, 2011, 2014 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. AND ITS CONTRIBUTORS ``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 ITS 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 "Decoder.h" + +#include <wtf/persistence/Encoder.h> + +namespace WTF { +namespace Persistence { + +Decoder::Decoder(const uint8_t* buffer, size_t bufferSize) + : m_buffer(buffer) + , m_bufferPosition(buffer) + , m_bufferEnd(buffer + bufferSize) +{ +} + +Decoder::~Decoder() +{ +} + +bool Decoder::bufferIsLargeEnoughToContain(size_t size) const +{ + return size <= static_cast<size_t>(m_bufferEnd - m_bufferPosition); +} + +bool Decoder::decodeFixedLengthData(uint8_t* data, size_t size) +{ + if (!bufferIsLargeEnoughToContain(size)) + return false; + + memcpy(data, m_bufferPosition, size); + m_bufferPosition += size; + + Encoder::updateChecksumForData(m_sha1, data, size); + return true; +} + +template<typename Type> +bool Decoder::decodeNumber(Type& value) +{ + if (!bufferIsLargeEnoughToContain(sizeof(value))) + return false; + + memcpy(&value, m_bufferPosition, sizeof(value)); + m_bufferPosition += sizeof(Type); + + Encoder::updateChecksumForNumber(m_sha1, value); + return true; +} + +bool Decoder::decode(bool& result) +{ + return decodeNumber(result); +} + +bool Decoder::decode(uint8_t& result) +{ + return decodeNumber(result); +} + +bool Decoder::decode(uint16_t& result) +{ + return decodeNumber(result); +} + +bool Decoder::decode(uint32_t& result) +{ + return decodeNumber(result); +} + +bool Decoder::decode(uint64_t& result) +{ + return decodeNumber(result); +} + +bool Decoder::decode(int32_t& result) +{ + return decodeNumber(result); +} + +bool Decoder::decode(int64_t& result) +{ + return decodeNumber(result); +} + +bool Decoder::decode(float& result) +{ + return decodeNumber(result); +} + +bool Decoder::decode(double& result) +{ + return decodeNumber(result); +} + +bool Decoder::verifyChecksum() +{ + SHA1::Digest computedHash; + m_sha1.computeHash(computedHash); + + SHA1::Digest savedHash; + if (!decodeFixedLengthData(savedHash.data(), sizeof(savedHash))) + return false; + + return computedHash == savedHash; +} + +} +} diff --git a/Source/WTF/wtf/persistence/Decoder.h b/Source/WTF/wtf/persistence/Decoder.h new file mode 100644 index 000000000..414ec88fc --- /dev/null +++ b/Source/WTF/wtf/persistence/Decoder.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2014 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. AND ITS CONTRIBUTORS ``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 ITS 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. + */ + +#pragma once + +#include <wtf/SHA1.h> +#include <wtf/persistence/Coder.h> + +namespace WTF { +namespace Persistence { + +class Decoder { + WTF_MAKE_FAST_ALLOCATED; +public: + WTF_EXPORT_PRIVATE Decoder(const uint8_t* buffer, size_t bufferSize); + WTF_EXPORT_PRIVATE ~Decoder(); + + size_t length() const { return m_bufferEnd - m_buffer; } + size_t currentOffset() const { return m_bufferPosition - m_buffer; } + + WTF_EXPORT_PRIVATE bool verifyChecksum(); + + WTF_EXPORT_PRIVATE bool decodeFixedLengthData(uint8_t*, size_t); + + WTF_EXPORT_PRIVATE bool decode(bool&); + WTF_EXPORT_PRIVATE bool decode(uint8_t&); + WTF_EXPORT_PRIVATE bool decode(uint16_t&); + WTF_EXPORT_PRIVATE bool decode(uint32_t&); + WTF_EXPORT_PRIVATE bool decode(uint64_t&); + WTF_EXPORT_PRIVATE bool decode(int32_t&); + WTF_EXPORT_PRIVATE bool decode(int64_t&); + WTF_EXPORT_PRIVATE bool decode(float&); + WTF_EXPORT_PRIVATE bool decode(double&); + + template<typename T> bool decodeEnum(T& result) + { + static_assert(sizeof(T) <= 8, "Enum type T must not be larger than 64 bits!"); + + uint64_t value; + if (!decode(value)) + return false; + + result = static_cast<T>(value); + return true; + } + + template<typename T> bool decode(T& t) + { + return Coder<T>::decode(*this, t); + } + + template<typename T> + bool bufferIsLargeEnoughToContain(size_t numElements) const + { + static_assert(std::is_arithmetic<T>::value, "Type T must have a fixed, known encoded size!"); + + if (numElements > std::numeric_limits<size_t>::max() / sizeof(T)) + return false; + + return bufferIsLargeEnoughToContain(numElements * sizeof(T)); + } + + static const bool isIPCDecoder = false; + +private: + WTF_EXPORT_PRIVATE bool bufferIsLargeEnoughToContain(size_t) const; + template<typename Type> bool decodeNumber(Type&); + + const uint8_t* m_buffer; + const uint8_t* m_bufferPosition; + const uint8_t* m_bufferEnd; + + SHA1 m_sha1; +}; + +} +} + diff --git a/Source/WTF/wtf/persistence/Encoder.cpp b/Source/WTF/wtf/persistence/Encoder.cpp new file mode 100644 index 000000000..0f11e3481 --- /dev/null +++ b/Source/WTF/wtf/persistence/Encoder.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2010, 2014 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. AND ITS CONTRIBUTORS ``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 ITS 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 "Encoder.h" + +#include "SHA1.h" + +namespace WTF { +namespace Persistence { + +Encoder::Encoder() +{ +} + +Encoder::~Encoder() +{ +} + +uint8_t* Encoder::grow(size_t size) +{ + size_t newPosition = m_buffer.size(); + m_buffer.grow(m_buffer.size() + size); + return m_buffer.data() + newPosition; +} + +void Encoder::updateChecksumForData(SHA1& sha1, const uint8_t* data, size_t size) +{ + auto typeSalt = Salt<uint8_t*>::value; + sha1.addBytes(reinterpret_cast<uint8_t*>(&typeSalt), sizeof(typeSalt)); + sha1.addBytes(data, size); +} + +void Encoder::encodeFixedLengthData(const uint8_t* data, size_t size) +{ + updateChecksumForData(m_sha1, data, size); + + uint8_t* buffer = grow(size); + memcpy(buffer, data, size); +} + +template<typename Type> +void Encoder::encodeNumber(Type value) +{ + Encoder::updateChecksumForNumber(m_sha1, value); + + uint8_t* buffer = grow(sizeof(Type)); + memcpy(buffer, &value, sizeof(Type)); +} + +void Encoder::encode(bool value) +{ + encodeNumber(value); +} + +void Encoder::encode(uint8_t value) +{ + encodeNumber(value); +} + +void Encoder::encode(uint16_t value) +{ + encodeNumber(value); +} + +void Encoder::encode(uint32_t value) +{ + encodeNumber(value); +} + +void Encoder::encode(uint64_t value) +{ + encodeNumber(value); +} + +void Encoder::encode(int32_t value) +{ + encodeNumber(value); +} + +void Encoder::encode(int64_t value) +{ + encodeNumber(value); +} + +void Encoder::encode(float value) +{ + encodeNumber(value); +} + +void Encoder::encode(double value) +{ + encodeNumber(value); +} + +void Encoder::encodeChecksum() +{ + SHA1::Digest hash; + m_sha1.computeHash(hash); + encodeFixedLengthData(hash.data(), hash.size()); +} + +} +} diff --git a/Source/WTF/wtf/persistence/Encoder.h b/Source/WTF/wtf/persistence/Encoder.h new file mode 100644 index 000000000..61c965530 --- /dev/null +++ b/Source/WTF/wtf/persistence/Encoder.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``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 ITS 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. + */ + +#pragma once + +#include <wtf/SHA1.h> +#include <wtf/Vector.h> +#include <wtf/persistence/Coder.h> + +namespace WTF { +namespace Persistence { + +class Encoder; +class DataReference; + +class Encoder { + WTF_MAKE_FAST_ALLOCATED; +public: + WTF_EXPORT_PRIVATE Encoder(); + WTF_EXPORT_PRIVATE ~Encoder(); + + WTF_EXPORT_PRIVATE void encodeChecksum(); + WTF_EXPORT_PRIVATE void encodeFixedLengthData(const uint8_t*, size_t); + + template<typename T> void encodeEnum(T t) + { + COMPILE_ASSERT(sizeof(T) <= sizeof(uint64_t), enum_type_must_not_be_larger_than_64_bits); + + encode(static_cast<uint64_t>(t)); + } + + template<typename T> void encode(const T& t) + { + Coder<T>::encode(*this, t); + } + + template<typename T> Encoder& operator<<(const T& t) + { + encode(t); + return *this; + } + + const uint8_t* buffer() const { return m_buffer.data(); } + size_t bufferSize() const { return m_buffer.size(); } + + WTF_EXPORT_PRIVATE static void updateChecksumForData(SHA1&, const uint8_t*, size_t); + template <typename Type> static void updateChecksumForNumber(SHA1&, Type); + + static const bool isIPCEncoder = false; + +private: + WTF_EXPORT_PRIVATE void encode(bool); + WTF_EXPORT_PRIVATE void encode(uint8_t); + WTF_EXPORT_PRIVATE void encode(uint16_t); + WTF_EXPORT_PRIVATE void encode(uint32_t); + WTF_EXPORT_PRIVATE void encode(uint64_t); + WTF_EXPORT_PRIVATE void encode(int32_t); + WTF_EXPORT_PRIVATE void encode(int64_t); + WTF_EXPORT_PRIVATE void encode(float); + WTF_EXPORT_PRIVATE void encode(double); + + template<typename Type> void encodeNumber(Type); + + uint8_t* grow(size_t); + + template <typename Type> struct Salt; + + Vector<uint8_t, 4096> m_buffer; + SHA1 m_sha1; +}; + +template <> struct Encoder::Salt<bool> { static const unsigned value = 3; }; +template <> struct Encoder::Salt<uint8_t> { static const unsigned value = 5; }; +template <> struct Encoder::Salt<uint16_t> { static const unsigned value = 7; }; +template <> struct Encoder::Salt<uint32_t> { static const unsigned value = 11; }; +template <> struct Encoder::Salt<uint64_t> { static const unsigned value = 13; }; +template <> struct Encoder::Salt<int32_t> { static const unsigned value = 17; }; +template <> struct Encoder::Salt<int64_t> { static const unsigned value = 19; }; +template <> struct Encoder::Salt<float> { static const unsigned value = 23; }; +template <> struct Encoder::Salt<double> { static const unsigned value = 29; }; +template <> struct Encoder::Salt<uint8_t*> { static const unsigned value = 101; }; + +template <typename Type> +void Encoder::updateChecksumForNumber(SHA1& sha1, Type value) +{ + auto typeSalt = Salt<Type>::value; + sha1.addBytes(reinterpret_cast<uint8_t*>(&typeSalt), sizeof(typeSalt)); + sha1.addBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value)); +} + +} +} |