OLD | NEW |
| (Empty) |
1 // Copyright 2005-2009 Google Inc. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 // ======================================================================== | |
15 // | |
16 // Provides the base class framework for those objects to be serialized | |
17 // | |
18 // HACK: | |
19 // | |
20 // During the serialization/deserialization of vector<T> members, we | |
21 // coerce the type from vector<T> to vector<byte> since we are unable to | |
22 // get the real type vector<T> at later time. This is feasible because | |
23 // vector<T> in the vector library we are linking now keeps track of | |
24 // only front() and end() pointers and use them to calculate size(). | |
25 // We need to check whether this approach is still OK if we upgrade the | |
26 // standard libraries. | |
27 | |
28 #include "omaha/base/serializable_object.h" | |
29 #include "omaha/base/debug.h" | |
30 #include "omaha/base/logging.h" | |
31 | |
32 namespace omaha { | |
33 | |
34 // Serialize | |
35 bool SerializableObject::Serialize(std::vector<byte>* data) const { | |
36 ASSERT(data, (_T(""))); | |
37 | |
38 // Estimate how much memory we need | |
39 int size = data->size(); | |
40 for (size_t i = 0; i < members_.size(); ++i) | |
41 size += (members_[i].size > 0) ? members_[i].size : sizeof(int); | |
42 | |
43 // Reserve the estimated size fo vector memory | |
44 data->reserve(size); | |
45 | |
46 // Copy over the data | |
47 for (size_t i = 0; i < members_.size(); ++i) { | |
48 switch (members_[i].type) { | |
49 case SERIALIZABLE_VALUE_TYPE: { | |
50 int pos = data->size(); | |
51 data->resize(data->size() + members_[i].size); | |
52 memcpy(&(*data)[pos], members_[i].ptr, members_[i].size); | |
53 break; | |
54 } | |
55 | |
56 case SERIALIZABLE_CSTRING: { | |
57 CString* s = reinterpret_cast<CString*>(members_[i].ptr); | |
58 SerializeValueList(data, | |
59 reinterpret_cast<const byte*>(s->GetString()), | |
60 sizeof(TCHAR), | |
61 s->GetLength()); | |
62 break; | |
63 } | |
64 | |
65 case SERIALIZABLE_NESTED_OBJECT: { | |
66 SerializableObject* nested_obj = | |
67 reinterpret_cast<SerializableObject*>(members_[i].ptr); | |
68 if (!nested_obj->Serialize(data)) | |
69 return false; | |
70 break; | |
71 } | |
72 | |
73 case SERIALIZABLE_VECTOR | SERIALIZABLE_VALUE_TYPE: { | |
74 // Hack: coerce vector<T> to vector<byte> | |
75 std::vector<byte>* v = | |
76 reinterpret_cast<std::vector<byte>*>(members_[i].ptr); | |
77 if (v->size() != 0) { | |
78 SerializeValueList(data, | |
79 &v->front(), | |
80 members_[i].size, | |
81 v->size() / members_[i].size); | |
82 } else { | |
83 SerializeValueList(data, | |
84 NULL, | |
85 members_[i].size, | |
86 v->size() / members_[i].size); | |
87 } | |
88 break; | |
89 } | |
90 | |
91 case SERIALIZABLE_VECTOR | SERIALIZABLE_CSTRING: { | |
92 std::vector<CString>* v = | |
93 reinterpret_cast<std::vector<CString>*>(members_[i].ptr); | |
94 SerializeSizeAndCount(data, 1, v->size()); | |
95 if (!v->empty()) { | |
96 for (std::vector<CString>::const_iterator it = v->begin(); | |
97 it != v->end(); | |
98 ++it) { | |
99 SerializeValueList(data, | |
100 reinterpret_cast<const byte*>(it->GetString()), | |
101 sizeof(TCHAR), | |
102 it->GetLength()); | |
103 } | |
104 } | |
105 break; | |
106 } | |
107 | |
108 case SERIALIZABLE_VECTOR | SERIALIZABLE_NESTED_OBJECT: { | |
109 if (!SerializeVectorNestedObject(data, members_[i].ptr)) | |
110 return false; | |
111 break; | |
112 } | |
113 | |
114 default: | |
115 ASSERT(false, (_T(""))); | |
116 return false; | |
117 } | |
118 } | |
119 | |
120 return true; | |
121 } | |
122 | |
123 // Serialize the size and count values | |
124 void SerializableObject::SerializeSizeAndCount(std::vector<byte>* data, | |
125 int size, | |
126 int count) const { | |
127 ASSERT(data, (_T(""))); | |
128 ASSERT(size >= 0, (_T(""))); | |
129 | |
130 // Get current size | |
131 int pos = data->size(); | |
132 | |
133 // Adjust the size of the data buffer | |
134 data->resize(data->size() + 2 * sizeof(int)); | |
135 | |
136 // Get pointer to the position of data buffer we start to write | |
137 byte* ptr = &((*data)[pos]); | |
138 | |
139 // Push size | |
140 memcpy(ptr, &size, sizeof(int)); | |
141 ptr += sizeof(int); | |
142 | |
143 // Push count | |
144 memcpy(ptr, &count, sizeof(int)); | |
145 ptr += sizeof(int); | |
146 } | |
147 | |
148 // Serialize a list of value-typed elements | |
149 // | |
150 // Args: | |
151 // ser_data: pointer to the vector for the serialized data | |
152 // raw_data: pointer to the raw data to be serialized | |
153 // size: the size of the element in the list | |
154 // count: the number of the elements in the list | |
155 void SerializableObject::SerializeValueList(std::vector<byte>* ser_data, | |
156 const byte* raw_data, | |
157 int size, | |
158 int count) const { | |
159 ASSERT(ser_data, (_T(""))); | |
160 ASSERT(size > 0, (_T(""))); | |
161 | |
162 // Serialize the size and count values | |
163 SerializeSizeAndCount(ser_data, size, count); | |
164 | |
165 // Push data | |
166 if (count > 0) { | |
167 // Get current size | |
168 int pos = ser_data->size(); | |
169 | |
170 // Adjust the size of the data buffer | |
171 ser_data->resize(ser_data->size() + count * size); | |
172 | |
173 // Get pointer to the position of data buffer we start to write | |
174 byte* ptr = &((*ser_data)[pos]); | |
175 | |
176 // Copy data | |
177 memcpy(ptr, raw_data, count * size); | |
178 } | |
179 } | |
180 | |
181 // Deserialize | |
182 bool SerializableObject::Deserialize(byte* data, int size, uint32 version) { | |
183 ASSERT(data, (_T(""))); | |
184 ASSERT(size > 0, (_T(""))); | |
185 | |
186 byte* tail = data + size; | |
187 byte** data_ptr = &data; | |
188 if (!DeserializeHelper(data_ptr, size, version)) | |
189 return false; | |
190 | |
191 if (*data_ptr != tail) { | |
192 UTIL_LOG(LE, (_T("[SerializableObject::Deserialize]") | |
193 _T("[failed to deserialize all data]"))); | |
194 return false; | |
195 } | |
196 | |
197 return true; | |
198 } | |
199 | |
200 // Deserialize helper | |
201 bool SerializableObject::DeserializeHelper(byte** data, | |
202 int size, | |
203 uint32 version) { | |
204 ASSERT(data, (_T(""))); | |
205 ASSERT(size > 0, (_T(""))); | |
206 | |
207 byte* tail = *data + size; | |
208 | |
209 for (size_t i = 0; i < members_.size(); ++i) { | |
210 // Ignore those members which are persisted in newer versions | |
211 if (version != kLatestSerializableVersion && | |
212 members_[i].version > version) { | |
213 continue; | |
214 } | |
215 | |
216 switch (members_[i].type) { | |
217 case SERIALIZABLE_VALUE_TYPE: | |
218 if (*data + members_[i].size > tail) { | |
219 UTIL_LOG(L6, (_T("[SerializableObject::DeserializeHelper]") | |
220 _T("[overflow when deserializing value type]"))); | |
221 return false; | |
222 } | |
223 memcpy(members_[i].ptr, *data, members_[i].size); | |
224 *data += members_[i].size; | |
225 break; | |
226 | |
227 case SERIALIZABLE_CSTRING: { | |
228 std::vector<byte> deser_data; | |
229 if (!DeserializeValueList(&deser_data, | |
230 members_[i].size, | |
231 data, | |
232 tail - *data)) | |
233 return false; | |
234 CString* s = reinterpret_cast<CString*>(members_[i].ptr); | |
235 if (deser_data.size() != 0) { | |
236 s->SetString(reinterpret_cast<const TCHAR*>(&deser_data.front()), | |
237 deser_data.size() / members_[i].size); | |
238 } else { | |
239 s->SetString(_T("")); | |
240 } | |
241 break; | |
242 } | |
243 | |
244 case SERIALIZABLE_NESTED_OBJECT: { | |
245 SerializableObject* nested_obj = | |
246 reinterpret_cast<SerializableObject*>(members_[i].ptr); | |
247 if (!nested_obj->DeserializeHelper(data, size, version)) | |
248 return false; | |
249 break; | |
250 } | |
251 | |
252 case SERIALIZABLE_VECTOR | SERIALIZABLE_VALUE_TYPE: { | |
253 // Hack: coerce vector<T> to vector<byte> | |
254 std::vector<byte>* v = | |
255 reinterpret_cast<std::vector<byte>*>(members_[i].ptr); | |
256 if (!DeserializeValueList(v, members_[i].size, data, tail - *data)) | |
257 return false; | |
258 break; | |
259 } | |
260 | |
261 case SERIALIZABLE_VECTOR | SERIALIZABLE_CSTRING: { | |
262 std::vector<CString>* v = | |
263 reinterpret_cast<std::vector<CString>*>(members_[i].ptr); | |
264 int count = 0; | |
265 if (!DeserializeSizeAndCount(&count, 1, data, tail - *data)) | |
266 return false; | |
267 for (int j = 0; j < count; ++j) { | |
268 std::vector<byte> deser_data; | |
269 if (!DeserializeValueList(&deser_data, | |
270 members_[i].size, | |
271 data, | |
272 tail - *data)) | |
273 return false; | |
274 | |
275 CString s; | |
276 if (deser_data.size() != 0) { | |
277 s = CString(reinterpret_cast<const TCHAR*>(&deser_data.front()), | |
278 deser_data.size() / members_[i].size); | |
279 } | |
280 v->push_back(s); | |
281 } | |
282 break; | |
283 } | |
284 | |
285 case SERIALIZABLE_VECTOR | SERIALIZABLE_NESTED_OBJECT: { | |
286 if (!DeserializeVectorNestedObject(data, | |
287 tail - *data, | |
288 members_[i].ptr, | |
289 version)) | |
290 return false; | |
291 break; | |
292 } | |
293 | |
294 default: | |
295 ASSERT(false, (_T(""))); | |
296 break; | |
297 } | |
298 } | |
299 | |
300 return true; | |
301 } | |
302 | |
303 // Serialize the size and count values | |
304 bool SerializableObject::DeserializeSizeAndCount(int* count, | |
305 int size, | |
306 byte** ser_data, | |
307 int ser_size) const { | |
308 ASSERT(ser_data, (_T(""))); | |
309 ASSERT(count, (_T(""))); | |
310 | |
311 byte* ser_tail = *ser_data + ser_size; | |
312 | |
313 // Check to make sure that the serialization data should at least contain | |
314 // 'size' and 'count' | |
315 if (*ser_data + 2 * sizeof(int) > ser_tail) { | |
316 UTIL_LOG(L6, (_T("[SerializableObject::DeserializeSizeAndCount]") | |
317 _T("[overflow when deserializing size and count]"))); | |
318 return false; | |
319 } | |
320 | |
321 // Get size | |
322 // If the passing size is 0, skip the size check | |
323 int size2 = *(reinterpret_cast<const int*>(*ser_data)); | |
324 *ser_data += sizeof(int); | |
325 if (size && size != size2) | |
326 return false; | |
327 | |
328 // Get count | |
329 *count = *(reinterpret_cast<const int*>(*ser_data)); | |
330 *ser_data += sizeof(int); | |
331 | |
332 return true; | |
333 } | |
334 | |
335 // Deserialize a list of value-typed elements | |
336 // | |
337 // Args: | |
338 // ser_data: pointer to the vector for the serialized data | |
339 // size: the size of the element in the list | |
340 // raw_data: pointer to the raw data to be serialized | |
341 // ser_size: size of the serization data | |
342 bool SerializableObject::DeserializeValueList(std::vector<byte>* raw_data, | |
343 int size, | |
344 byte** ser_data, | |
345 int ser_size) { | |
346 ASSERT(raw_data, (_T(""))); | |
347 ASSERT(ser_data, (_T(""))); | |
348 | |
349 byte* ser_tail = *ser_data + ser_size; | |
350 | |
351 // Deserialize the size and count values | |
352 int count = 0; | |
353 bool ret = DeserializeSizeAndCount(&count, size, ser_data, ser_size); | |
354 if (!ret) | |
355 return false; | |
356 | |
357 // Check to make sure that the serialization data is in the right size | |
358 if (*ser_data + count * size > ser_tail) { | |
359 UTIL_LOG(L6, (_T("[SerializableObject::DeserializeValueList]") | |
360 _T("[overflow when deserializing value list]"))); | |
361 return false; | |
362 } | |
363 | |
364 // Get data | |
365 raw_data->resize(size * count); | |
366 if (count > 0) { | |
367 memcpy(&raw_data->front(), *ser_data, count * size); | |
368 *ser_data += count * size; | |
369 } | |
370 | |
371 return true; | |
372 } | |
373 | |
374 } // namespace omaha | |
375 | |
OLD | NEW |