1 : // Copyright 2012 Google Inc. All Rights Reserved.
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 : // Contains Serialization implementation details. See 'serialization.h'
16 : // for more information. This file is not meant to be included directly,
17 : // but is brought in by serialization.h.
18 :
19 : #ifndef SYZYGY_CORE_SERIALIZATION_IMPL_H_
20 : #define SYZYGY_CORE_SERIALIZATION_IMPL_H_
21 :
22 : #include <iterator>
23 :
24 : // Forward declare base::Time, defined in "base/time/time.h".
25 : namespace base {
26 : class Time;
27 : } // namespace base
28 :
29 : // Forward declare the OMAP struct. This is defined in DbgHelp.h.
30 : struct _OMAP;
31 : typedef struct _OMAP OMAP;
32 :
33 : namespace core {
34 :
35 : namespace internal {
36 :
37 : // This is for testing type equality.
38 : template<typename T1, typename T2> struct TypesAreEqual {
39 : enum { Value = 0 };
40 : };
41 : template<typename T> struct TypesAreEqual<T, T> {
42 : enum { Value = 1 };
43 : };
44 :
45 : // This tests that a given type is a signed or unsigned 1-byte type.
46 : template<typename T> struct IsByteLike {
47 : enum {
48 : Value =
49 : (TypesAreEqual<T, int8_t>::Value || TypesAreEqual<T, uint8_t>::Value) &&
50 : (sizeof(T) == 1)
51 : };
52 : };
53 :
54 : // This compares two iterators. It only does so if the iterator type is
55 : // not an output iterator.
56 : template<typename IteratorTag> struct IteratorsAreEqualFunctor {
57 : template<typename Iterator> bool operator()(Iterator it1, Iterator it2) {
58 : return it1 == it2;
59 : }
60 : };
61 : template<> struct IteratorsAreEqualFunctor<std::output_iterator_tag> {
62 i : template<typename Iterator> bool operator()(Iterator it1, Iterator it2) {
63 i : return false;
64 i : }
65 : };
66 :
67 : // Serialization for STL containers. This expects the container to implement
68 : // 'size', and iterators.
69 : template<class Container, class OutArchive> bool SaveContainer(
70 E : const Container& container, OutArchive* out_archive) {
71 E : DCHECK(out_archive != NULL);
72 :
73 E : if (!out_archive->Save(container.size()))
74 i : return false;
75 :
76 E : typename Container::const_iterator it = container.begin();
77 E : for (; it != container.end(); ++it) {
78 E : if (!out_archive->Save(*it))
79 i : return false;
80 E : }
81 :
82 E : return true;
83 E : }
84 :
85 : // We use this type traits struct to get the value_type associated with a
86 : // given container. We require this to get around the pair<const, non-const>
87 : // value_type declaration of std::map.
88 : template<class Container> struct ContainerValueType {
89 : typedef typename Container::value_type ValueType;
90 : };
91 : template<typename Key, typename Data, typename Compare, typename Alloc>
92 : struct ContainerValueType<std::map<Key, Data, Compare, Alloc> > {
93 : typedef std::pair<Key, Data> ValueType;
94 : };
95 :
96 : // Reserves space in a container for the given number of entries, if possible.
97 : template<typename Container>
98 : struct ReserveContainer {
99 E : void operator()(size_t entries, Container* container) {
100 : // Do nothing for most containers.
101 E : }
102 : };
103 : // std::vector and std::basic_string both support 'reserve'.
104 : template<typename T>
105 : struct ReserveContainer<std::vector<T>> {
106 E : void operator()(size_t entries, std::vector<T>* vector) {
107 E : DCHECK(vector != NULL);
108 E : vector->reserve(entries);
109 E : }
110 : };
111 : template<typename Char, typename Traits, typename Alloc>
112 : struct ReserveContainer<std::basic_string<Char, Traits, Alloc>> {
113 : void operator()(size_t entries,
114 E : std::basic_string<Char, Traits, Alloc>* string) {
115 E : DCHECK(string != NULL);
116 E : string->reserve(entries);
117 E : }
118 : };
119 :
120 : // Loads serialized values into a container via an output iterator.
121 : template<typename Container, typename OutputIterator, class InArchive>
122 : bool LoadContainer(Container* container,
123 : OutputIterator output_iterator,
124 E : InArchive* in_archive) {
125 E : DCHECK(container != NULL);
126 E : DCHECK(in_archive != NULL);
127 :
128 : // Get the value type.
129 : typedef ContainerValueType<Container>::ValueType ValueType;
130 :
131 E : typename Container::size_type size = 0;
132 E : if (!in_archive->Load(&size))
133 i : return false;
134 :
135 : // Reserve room for the entries, if the container supports it. This makes
136 : // this slightly more efficient.
137 E : ReserveContainer<Container>()(size, container);
138 :
139 E : typename Container::size_type i = 0;
140 E : for (; i < size; ++i) {
141 E : ValueType value;
142 E : if (!in_archive->Load(&value))
143 i : return false;
144 E : *output_iterator = value;
145 E : ++output_iterator;
146 E : }
147 :
148 E : DCHECK_EQ(size, container->size());
149 :
150 E : return true;
151 E : }
152 :
153 : } // namespace internal
154 :
155 : template<typename OutputIterator> bool ByteOutStream<OutputIterator>::Write(
156 E : size_t length, const Byte* bytes) {
157 E : for (size_t i = 0; i < length; ++i, ++bytes) {
158 E : if (have_end_ && IteratorsAreEqual()(iter_, end_))
159 i : return false;
160 : // The underlying output type has to be able to cope with
161 : // assignment from a Byte!
162 E : *iter_ = *bytes;
163 E : ++iter_;
164 E : }
165 E : return true;
166 E : }
167 :
168 : template<typename InputIterator> bool ByteInStream<InputIterator>::ReadImpl(
169 E : size_t length, Byte* bytes, size_t* bytes_read) {
170 E : DCHECK(bytes != NULL);
171 E : DCHECK(bytes_read != NULL);
172 :
173 E : Byte* bytes_start = bytes;
174 E : for (size_t i = 0; i < length; ++i, ++bytes) {
175 E : if (iter_ == end_)
176 E : break;
177 E : *bytes = static_cast<Byte>(*iter_);
178 E : ++iter_;
179 E : }
180 :
181 E : *bytes_read = static_cast<size_t>(bytes - bytes_start);
182 E : return true;
183 E : }
184 :
185 : // Default implementations of core::Save and core::Load.
186 :
187 : // This delegates to Data::Save.
188 : template<class Data, class OutArchive> bool Save(
189 E : const Data& data, OutArchive* out_archive) {
190 E : DCHECK(out_archive != NULL);
191 E : return data.Save(out_archive);
192 E : }
193 :
194 : // This delegates to Data::Load.
195 : template<class Data, class InArchive> bool Load(
196 E : Data* data, InArchive* in_archive) {
197 E : DCHECK(data != NULL);
198 E : DCHECK(in_archive != NULL);
199 E : return data->Load(in_archive);
200 E : }
201 :
202 : // Implementation of STL Save specializations.
203 :
204 : template<typename Char, typename Traits, typename Alloc, class OutArchive>
205 : bool Save(const std::basic_string<Char, Traits, Alloc>& string,
206 E : OutArchive* out_archive) {
207 E : DCHECK(out_archive != NULL);
208 E : return internal::SaveContainer(string, out_archive);
209 E : }
210 :
211 : template<typename Key, typename Data, typename Compare, typename Alloc,
212 : class OutArchive>
213 : bool Save(const std::map<Key, Data, Compare, Alloc>& map,
214 E : OutArchive* out_archive) {
215 E : DCHECK(out_archive != NULL);
216 E : return internal::SaveContainer(map, out_archive);
217 E : }
218 :
219 : template<typename Type1, typename Type2, class OutArchive>
220 : bool Save(const std::pair<Type1, Type2>& pair,
221 E : OutArchive* out_archive) {
222 E : DCHECK(out_archive != NULL);
223 E : return out_archive->Save(pair.first) && out_archive->Save(pair.second);
224 E : }
225 :
226 : template<typename Key, typename Compare, typename Alloc, class OutArchive>
227 : bool Save(const std::set<Key, Compare, Alloc>& set,
228 E : OutArchive* out_archive) {
229 E : DCHECK(out_archive != NULL);
230 E : return internal::SaveContainer(set, out_archive);
231 E : }
232 :
233 : template<typename Type, typename Alloc, class OutArchive>
234 : bool Save(const std::vector<Type, Alloc>& vector,
235 E : OutArchive* out_archive) {
236 E : DCHECK(out_archive != NULL);
237 E : return internal::SaveContainer(vector, out_archive);
238 E : }
239 :
240 : // Implementation of STL Load specializations.
241 :
242 : template<typename Char, typename Traits, typename Alloc, class InArchive>
243 : bool Load(std::basic_string<Char, Traits, Alloc>* string,
244 E : InArchive* in_archive) {
245 E : DCHECK(string != NULL);
246 E : DCHECK(in_archive != NULL);
247 E : string->clear();
248 E : return internal::LoadContainer(string,
249 : std::back_inserter(*string),
250 : in_archive);
251 E : }
252 :
253 : template<typename Key, typename Data, typename Compare, typename Alloc,
254 : class InArchive>
255 : bool Load(std::map<Key, Data, Compare, Alloc>* map,
256 E : InArchive* in_archive) {
257 E : DCHECK(map != NULL);
258 E : DCHECK(in_archive != NULL);
259 E : map->clear();
260 E : return internal::LoadContainer(map,
261 : std::inserter(*map, map->begin()),
262 : in_archive);
263 E : }
264 :
265 : template<typename Type1, typename Type2, class InArchive>
266 : bool Load(std::pair<Type1, Type2>* pair,
267 E : InArchive* in_archive) {
268 E : DCHECK(pair != NULL);
269 E : DCHECK(in_archive != NULL);
270 E : return in_archive->Load(&(pair->first)) && in_archive->Load(&(pair->second));
271 E : }
272 :
273 : template<typename Key, typename Compare, typename Alloc, class InArchive>
274 : bool Load(std::set<Key, Compare, Alloc>* set,
275 E : InArchive* in_archive) {
276 E : DCHECK(set != NULL);
277 E : DCHECK(in_archive != NULL);
278 E : set->clear();
279 E : return internal::LoadContainer(set,
280 : std::inserter(*set, set->begin()),
281 : in_archive);
282 E : }
283 :
284 : template<typename Type, typename Alloc, class InArchive>
285 : bool Load(std::vector<Type, Alloc>* vector,
286 E : InArchive* in_archive) {
287 E : DCHECK(vector != NULL);
288 E : DCHECK(in_archive != NULL);
289 E : return internal::LoadContainer(vector,
290 : std::back_inserter(*vector),
291 : in_archive);
292 E : }
293 :
294 : // Implementation of serialization for C-style arrays.
295 :
296 : template<typename Type, size_t Length, class OutArchive>
297 E : bool Save(const Type (&data)[Length], OutArchive* out_archive) {
298 E : DCHECK(out_archive != NULL);
299 E : for (size_t i = 0; i < Length; ++i) {
300 E : if (!out_archive->Save(data[i]))
301 i : return false;
302 E : }
303 E : return true;
304 E : }
305 :
306 : template<typename Type, size_t Length, class InArchive>
307 E : bool Load(Type (*data)[Length], InArchive* in_archive) {
308 E : DCHECK(data != NULL);
309 E : DCHECK(in_archive != NULL);
310 E : for (size_t i = 0; i < Length; ++i) {
311 E : if (!in_archive->Load(&((*data)[i])))
312 i : return false;
313 E : }
314 E : return true;
315 E : }
316 :
317 : // Declaration of serialization for base::Time.
318 : bool Save(const base::Time& time, OutArchive* out_archive);
319 : bool Load(base::Time* time, InArchive* in_archive);
320 :
321 : // Declaration of OMAP struct serialization.
322 : bool Save(const OMAP& omap, OutArchive* out_archive);
323 : bool Load(OMAP* omap, InArchive* in_archive);
324 :
325 : } // namespace core
326 :
327 : #endif // SYZYGY_CORE_SERIALIZATION_IMPL_H_
|