ee8563034485ef2474ff9a46398eeb0ccff0374c
[WebKit-https.git] / Source / WebKit2 / Platform / IPC / ArgumentEncoder.cpp
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 #include "config.h"
27 #include "ArgumentEncoder.h"
28
29 #include "DataReference.h"
30 #include <algorithm>
31 #include <stdio.h>
32
33 #if OS(DARWIN)
34 #include <sys/mman.h>
35 #endif
36
37 namespace IPC {
38
39 static inline void* allocBuffer(size_t size)
40 {
41 #if OS(DARWIN)
42     return mmap(0, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
43 #else
44     return fastMalloc(size);
45 #endif
46 }
47
48 static inline void freeBuffer(void* addr, size_t size)
49 {
50 #if OS(DARWIN)
51     munmap(addr, size);
52 #else
53     UNUSED_PARAM(size);
54     fastFree(addr);
55 #endif
56 }
57
58 ArgumentEncoder::ArgumentEncoder()
59     : m_buffer(m_inlineBuffer)
60     , m_bufferPointer(m_inlineBuffer)
61     , m_bufferSize(0)
62     , m_bufferCapacity(sizeof(m_inlineBuffer))
63 {
64 }
65
66 ArgumentEncoder::~ArgumentEncoder()
67 {
68     if (m_buffer != m_inlineBuffer)
69         freeBuffer(m_buffer, m_bufferCapacity);
70
71 #if !USE(UNIX_DOMAIN_SOCKETS)
72     // FIXME: We need to dispose of the attachments in cases of failure.
73 #else
74     for (size_t i = 0; i < m_attachments.size(); ++i)
75         m_attachments[i].dispose();
76 #endif
77 }
78
79 static inline size_t roundUpToAlignment(size_t value, unsigned alignment)
80 {
81     return ((value + alignment - 1) / alignment) * alignment;
82 }
83
84 uint8_t* ArgumentEncoder::grow(unsigned alignment, size_t size)
85 {
86     size_t alignedSize = roundUpToAlignment(m_bufferSize, alignment);
87     
88     if (alignedSize + size > m_bufferCapacity) {
89         size_t newCapacity = roundUpToAlignment(m_bufferCapacity * 2, 4096);
90         while (newCapacity < alignedSize + size)
91             newCapacity *= 2;
92
93         uint8_t* newBuffer = static_cast<uint8_t*>(allocBuffer(newCapacity));
94         if (!newBuffer)
95             CRASH();
96
97         memcpy(newBuffer, m_buffer, m_bufferSize);
98
99         if (m_buffer != m_inlineBuffer)
100             freeBuffer(m_buffer, m_bufferCapacity);
101
102         m_buffer = newBuffer;
103         m_bufferCapacity = newCapacity;
104     }
105
106     m_bufferSize = alignedSize + size;
107     m_bufferPointer = m_buffer + alignedSize + size;
108     
109     return m_buffer + alignedSize;
110 }
111
112 void ArgumentEncoder::encodeFixedLengthData(const uint8_t* data, size_t size, unsigned alignment)
113 {
114     ASSERT(!(reinterpret_cast<uintptr_t>(data) % alignment));
115
116     uint8_t* buffer = grow(alignment, size);
117     memcpy(buffer, data, size);
118 }
119
120 void ArgumentEncoder::encodeVariableLengthByteArray(const DataReference& dataReference)
121 {
122     encode(static_cast<uint64_t>(dataReference.size()));
123     encodeFixedLengthData(dataReference.data(), dataReference.size(), 1);
124 }
125
126 template<typename Type>
127 static void copyValueToBuffer(Type value, uint8_t* bufferPosition)
128 {
129     memcpy(bufferPosition, &value, sizeof(Type));
130 }
131
132 void ArgumentEncoder::encode(bool n)
133 {
134     uint8_t* buffer = grow(sizeof(n), sizeof(n));
135     copyValueToBuffer(n, buffer);
136 }
137
138 void ArgumentEncoder::encode(uint8_t n)
139 {
140     uint8_t* buffer = grow(sizeof(n), sizeof(n));
141     copyValueToBuffer(n, buffer);
142 }
143
144 void ArgumentEncoder::encode(uint16_t n)
145 {
146     uint8_t* buffer = grow(sizeof(n), sizeof(n));
147     copyValueToBuffer(n, buffer);
148 }
149
150 void ArgumentEncoder::encode(uint32_t n)
151 {
152     uint8_t* buffer = grow(sizeof(n), sizeof(n));
153     copyValueToBuffer(n, buffer);
154 }
155
156 void ArgumentEncoder::encode(uint64_t n)
157 {
158     uint8_t* buffer = grow(sizeof(n), sizeof(n));
159     copyValueToBuffer(n, buffer);
160 }
161
162 void ArgumentEncoder::encode(int32_t n)
163 {
164     uint8_t* buffer = grow(sizeof(n), sizeof(n));
165     copyValueToBuffer(n, buffer);
166 }
167
168 void ArgumentEncoder::encode(int64_t n)
169 {
170     uint8_t* buffer = grow(sizeof(n), sizeof(n));
171     copyValueToBuffer(n, buffer);
172 }
173
174 void ArgumentEncoder::encode(float n)
175 {
176     uint8_t* buffer = grow(sizeof(n), sizeof(n));
177     copyValueToBuffer(n, buffer);
178 }
179
180 void ArgumentEncoder::encode(double n)
181 {
182     uint8_t* buffer = grow(sizeof(n), sizeof(n));
183     copyValueToBuffer(n, buffer);
184 }
185
186 void ArgumentEncoder::addAttachment(const Attachment& attachment)
187 {
188     m_attachments.append(attachment);
189 }
190
191 Vector<Attachment> ArgumentEncoder::releaseAttachments()
192 {
193     Vector<Attachment> newList;
194     newList.swap(m_attachments);
195     return newList;
196 }
197
198 } // namespace IPC