1/*
2 * Copyright (C) 2010 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#include <wtf/EnumTraits.h>
29#include <wtf/SHA1.h>
30#include <wtf/Vector.h>
31#include <wtf/persistence/PersistentCoder.h>
32
33namespace WTF {
34namespace Persistence {
35
36class Encoder;
37class DataReference;
38
39class Encoder {
40 WTF_MAKE_FAST_ALLOCATED;
41public:
42 WTF_EXPORT_PRIVATE Encoder();
43 WTF_EXPORT_PRIVATE ~Encoder();
44
45 WTF_EXPORT_PRIVATE void encodeChecksum();
46 WTF_EXPORT_PRIVATE void encodeFixedLengthData(const uint8_t*, size_t);
47
48 template<typename E> auto encode(E value) -> std::enable_if_t<std::is_enum<E>::value>
49 {
50 static_assert(sizeof(E) <= sizeof(uint64_t), "Enum type must not be larger than 64 bits.");
51
52 ASSERT(isValidEnum<E>(static_cast<uint64_t>(value)));
53 encode(static_cast<uint64_t>(value));
54 }
55
56 template<typename T> void encodeEnum(T t)
57 {
58 COMPILE_ASSERT(sizeof(T) <= sizeof(uint64_t), enum_type_must_not_be_larger_than_64_bits);
59
60 encode(static_cast<uint64_t>(t));
61 }
62
63 template<typename T> auto encode(const T& t) -> std::enable_if_t<!std::is_enum<T>::value>
64 {
65 Coder<T>::encode(*this, t);
66 }
67
68 template<typename T> Encoder& operator<<(const T& t)
69 {
70 encode(t);
71 return *this;
72 }
73
74 const uint8_t* buffer() const { return m_buffer.data(); }
75 size_t bufferSize() const { return m_buffer.size(); }
76
77 WTF_EXPORT_PRIVATE static void updateChecksumForData(SHA1&, const uint8_t*, size_t);
78 template <typename Type> static void updateChecksumForNumber(SHA1&, Type);
79
80 static const bool isIPCEncoder = false;
81
82private:
83 WTF_EXPORT_PRIVATE void encode(bool);
84 WTF_EXPORT_PRIVATE void encode(uint8_t);
85 WTF_EXPORT_PRIVATE void encode(uint16_t);
86 WTF_EXPORT_PRIVATE void encode(uint32_t);
87 WTF_EXPORT_PRIVATE void encode(uint64_t);
88 WTF_EXPORT_PRIVATE void encode(int32_t);
89 WTF_EXPORT_PRIVATE void encode(int64_t);
90 WTF_EXPORT_PRIVATE void encode(float);
91 WTF_EXPORT_PRIVATE void encode(double);
92
93 template<typename Type> void encodeNumber(Type);
94
95 uint8_t* grow(size_t);
96
97 template <typename Type> struct Salt;
98
99 Vector<uint8_t, 4096> m_buffer;
100 SHA1 m_sha1;
101};
102
103template <> struct Encoder::Salt<bool> { static const unsigned value = 3; };
104template <> struct Encoder::Salt<uint8_t> { static const unsigned value = 5; };
105template <> struct Encoder::Salt<uint16_t> { static const unsigned value = 7; };
106template <> struct Encoder::Salt<uint32_t> { static const unsigned value = 11; };
107template <> struct Encoder::Salt<uint64_t> { static const unsigned value = 13; };
108template <> struct Encoder::Salt<int32_t> { static const unsigned value = 17; };
109template <> struct Encoder::Salt<int64_t> { static const unsigned value = 19; };
110template <> struct Encoder::Salt<float> { static const unsigned value = 23; };
111template <> struct Encoder::Salt<double> { static const unsigned value = 29; };
112template <> struct Encoder::Salt<uint8_t*> { static const unsigned value = 101; };
113
114template <typename Type>
115void Encoder::updateChecksumForNumber(SHA1& sha1, Type value)
116{
117 auto typeSalt = Salt<Type>::value;
118 sha1.addBytes(reinterpret_cast<uint8_t*>(&typeSalt), sizeof(typeSalt));
119 sha1.addBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
120}
121
122}
123}
124