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