]> git.cworth.org Git - vogl/blob - src/voglcore/vogl_data_stream_serializer.h
Initial vogl checkin
[vogl] / src / voglcore / vogl_data_stream_serializer.h
1 /**************************************************************************
2  *
3  * Copyright 2013-2014 RAD Game Tools and Valve Software
4  * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  *
25  **************************************************************************/
26
27 // File: data_stream_serializer.h
28 #pragma once
29
30 #include "vogl_core.h"
31 #include "vogl_data_stream.h"
32
33 namespace vogl
34 {
35     // Defaults to little endian mode.
36     class data_stream_serializer
37     {
38     public:
39         data_stream_serializer()
40             : m_pStream(NULL), m_little_endian(true)
41         {
42         }
43         data_stream_serializer(data_stream *pStream)
44             : m_pStream(pStream), m_little_endian(true)
45         {
46         }
47         data_stream_serializer(data_stream &stream)
48             : m_pStream(&stream), m_little_endian(true)
49         {
50         }
51         data_stream_serializer(const data_stream_serializer &other)
52             : m_pStream(other.m_pStream), m_little_endian(other.m_little_endian)
53         {
54         }
55
56         data_stream_serializer &operator=(const data_stream_serializer &rhs)
57         {
58             m_pStream = rhs.m_pStream;
59             m_little_endian = rhs.m_little_endian;
60             return *this;
61         }
62
63         data_stream *get_stream() const
64         {
65             return m_pStream;
66         }
67         void set_stream(data_stream *pStream)
68         {
69             m_pStream = pStream;
70         }
71
72         const dynamic_string &get_name() const
73         {
74             return m_pStream ? m_pStream->get_name() : g_empty_dynamic_string;
75         }
76
77         // true if stream has latched an error
78         bool get_error()
79         {
80             return m_pStream ? m_pStream->get_error() : false;
81         }
82
83         bool get_little_endian() const
84         {
85             return m_little_endian;
86         }
87         void set_little_endian(bool little_endian)
88         {
89             m_little_endian = little_endian;
90         }
91
92         bool write(const void *pBuf, uint len)
93         {
94             return m_pStream->write(pBuf, len) == len;
95         }
96
97         bool read(void *pBuf, uint len)
98         {
99             return m_pStream->read(pBuf, len) == len;
100         }
101
102         // size = size of each element, count = number of elements, returns actual count of elements written
103         uint write(const void *pBuf, uint size, uint count)
104         {
105             uint actual_size = size * count;
106             if (!actual_size)
107                 return 0;
108             uint n = m_pStream->write(pBuf, actual_size);
109             if (n == actual_size)
110                 return count;
111             return n / size;
112         }
113
114         // size = size of each element, count = number of elements, returns actual count of elements read
115         uint read(void *pBuf, uint size, uint count)
116         {
117             uint actual_size = size * count;
118             if (!actual_size)
119                 return 0;
120             uint n = m_pStream->read(pBuf, actual_size);
121             if (n == actual_size)
122                 return count;
123             return n / size;
124         }
125
126         bool write_chars(const char *pBuf, uint len)
127         {
128             return write(pBuf, len);
129         }
130
131         bool read_chars(char *pBuf, uint len)
132         {
133             return read(pBuf, len);
134         }
135
136         bool skip(uint len)
137         {
138             return m_pStream->skip(len) == len;
139         }
140
141         template <typename T>
142         bool write_object(const T &obj)
143         {
144             if (m_little_endian == c_vogl_little_endian_platform)
145                 return write(&obj, sizeof(obj));
146             else
147             {
148                 uint8 buf[sizeof(T)];
149                 uint buf_size = sizeof(T);
150                 void *pBuf = buf;
151                 utils::write_obj(obj, pBuf, buf_size, m_little_endian);
152
153                 return write(buf, sizeof(T));
154             }
155         }
156
157         template <typename T>
158         bool read_object(T &obj)
159         {
160             if (m_little_endian == c_vogl_little_endian_platform)
161                 return read(&obj, sizeof(obj));
162             else
163             {
164                 uint8 buf[sizeof(T)];
165                 if (!read(buf, sizeof(T)))
166                     return false;
167
168                 uint buf_size = sizeof(T);
169                 const void *pBuf = buf;
170                 utils::read_obj(obj, pBuf, buf_size, m_little_endian);
171
172                 return true;
173             }
174         }
175
176         template <typename T>
177         bool write_value(T value)
178         {
179             return write_object(value);
180         }
181
182         template <typename T>
183         T read_value(const T &on_error_value = T())
184         {
185             T result;
186             if (!read_object(result))
187                 result = on_error_value;
188             return result;
189         }
190
191         int8 read_int8(int8 def = 0)
192         {
193             int8 result;
194             if (!read_object(result))
195                 result = def;
196             return result;
197         }
198
199         uint8 read_uint8(uint8 def = 0)
200         {
201             uint8 result;
202             if (!read_object(result))
203                 result = def;
204             return result;
205         }
206
207         int16 read_int16(int16 def = 0)
208         {
209             int16 result;
210             if (!read_object(result))
211                 result = def;
212             return result;
213         }
214
215         uint16 read_uint16(uint16 def = 0)
216         {
217             uint16 result;
218             if (!read_object(result))
219                 result = def;
220             return result;
221         }
222
223         int32 read_int32(int32 def = 0)
224         {
225             int32 result;
226             if (!read_object(result))
227                 result = def;
228             return result;
229         }
230
231         uint32 read_uint32(uint32 def = 0)
232         {
233             uint32 result;
234             if (!read_object(result))
235                 result = def;
236             return result;
237         }
238
239         float read_float(float def = 0)
240         {
241             float result;
242             if (!read_object(result))
243                 result = def;
244             return result;
245         }
246
247         double read_double(double def = 0)
248         {
249             double result;
250             if (!read_object(result))
251                 result = def;
252             return result;
253         }
254
255         int64_t read_int64(int64_t def = 0)
256         {
257             int64_t result;
258             if (!read_object(result))
259                 result = def;
260             return result;
261         }
262
263         uint64_t read_uint64(uint64_t def = 0)
264         {
265             uint64_t result;
266             if (!read_object(result))
267                 result = def;
268             return result;
269         }
270
271         template <typename T>
272         bool write_enum(T e)
273         {
274             int val = static_cast<int>(e);
275             return write_object(val);
276         }
277
278         template <typename T>
279         T read_enum()
280         {
281             return static_cast<T>(read_value<int>());
282         }
283
284         // Writes uint using a simple variable length code (VLC).
285         bool write_uint_vlc(uint val)
286         {
287             do
288             {
289                 uint8 c = static_cast<uint8>(val) & 0x7F;
290                 if (val <= 0x7F)
291                     c |= 0x80;
292
293                 if (!write_value(c))
294                     return false;
295
296                 val >>= 7;
297             } while (val);
298
299             return true;
300         }
301
302         // Reads uint using a simple variable length code (VLC).
303         bool read_uint_vlc(uint &val)
304         {
305             val = 0;
306             uint shift = 0;
307
308             for (;;)
309             {
310                 if (shift >= 32)
311                     return false;
312
313                 uint8 c;
314                 if (!read_object(c))
315                     return false;
316
317                 val |= ((c & 0x7F) << shift);
318                 shift += 7;
319
320                 if (c & 0x80)
321                     break;
322             }
323
324             return true;
325         }
326
327         bool write_c_str(const char *p)
328         {
329             uint len = static_cast<uint>(strlen(p));
330             if (!write_uint_vlc(len))
331                 return false;
332
333             return write_chars(p, len);
334         }
335
336         bool read_c_str(char *pBuf, uint buf_size)
337         {
338             uint len;
339             if (!read_uint_vlc(len))
340                 return false;
341             if ((len + 1) > buf_size)
342                 return false;
343
344             pBuf[len] = '\0';
345
346             return read_chars(pBuf, len);
347         }
348
349         bool write_string(const dynamic_string &str)
350         {
351             if (!write_uint_vlc(str.get_len()))
352                 return false;
353
354             return write_chars(str.get_ptr(), str.get_len());
355         }
356
357         bool read_string(dynamic_string &str)
358         {
359             uint len;
360             if (!read_uint_vlc(len))
361                 return false;
362
363             if (!str.set_len(len))
364                 return false;
365
366             if (len)
367             {
368                 if (!read_chars(str.get_ptr_raw(), len))
369                     return false;
370
371                 if (memchr(str.get_ptr(), 0, len) != NULL)
372                 {
373                     str.truncate(0);
374                     return false;
375                 }
376             }
377
378             return true;
379         }
380
381         template <typename T>
382         bool write_vector(const T &vec)
383         {
384             if (!write_uint_vlc(vec.size()))
385                 return false;
386
387             for (uint i = 0; i < vec.size(); i++)
388             {
389                 *this << vec[i];
390                 if (get_error())
391                     return false;
392             }
393
394             return true;
395         };
396
397         template <typename T>
398         bool read_vector(T &vec, uint num_expected = UINT_MAX)
399         {
400             uint size;
401             if (!read_uint_vlc(size))
402                 return false;
403
404             if ((size * sizeof(T::value_type)) >= 2U * 1024U * 1024U * 1024U)
405                 return false;
406
407             if ((num_expected != UINT_MAX) && (size != num_expected))
408                 return false;
409
410             vec.resize(size);
411             for (uint i = 0; i < vec.size(); i++)
412             {
413                 *this >> vec[i];
414
415                 if (get_error())
416                     return false;
417             }
418
419             return true;
420         }
421
422         bool read_entire_file(vogl::vector<uint8> &buf)
423         {
424             return m_pStream->read_array(buf);
425         }
426
427         bool write_entire_file(const vogl::vector<uint8> &buf)
428         {
429             return m_pStream->write_array(buf);
430         }
431
432         // Got this idea from the Molly Rocket forums.
433         // fmt may contain the characters "1", "2", or "4".
434         bool writef(char *fmt, ...)
435         {
436             va_list v;
437             va_start(v, fmt);
438
439             while (*fmt)
440             {
441                 switch (*fmt++)
442                 {
443                     case '1':
444                     {
445                         const uint8 x = static_cast<uint8>(va_arg(v, uint));
446                         if (!write_value(x))
447                             return false;
448                     }
449                     case '2':
450                     {
451                         const uint16 x = static_cast<uint16>(va_arg(v, uint));
452                         if (!write_value(x))
453                             return false;
454                     }
455                     case '4':
456                     {
457                         const uint32 x = static_cast<uint32>(va_arg(v, uint));
458                         if (!write_value(x))
459                             return false;
460                     }
461                     case ' ':
462                     case ',':
463                     {
464                         break;
465                     }
466                     default:
467                     {
468                         VOGL_ASSERT_ALWAYS;
469                         return false;
470                     }
471                 }
472             }
473
474             va_end(v);
475             return true;
476         }
477
478         // Got this idea from the Molly Rocket forums.
479         // fmt may contain the characters "1", "2", or "4".
480         bool readf(char *fmt, ...)
481         {
482             va_list v;
483             va_start(v, fmt);
484
485             while (*fmt)
486             {
487                 switch (*fmt++)
488                 {
489                     case '1':
490                     {
491                         uint8 *x = va_arg(v, uint8 *);
492                         VOGL_ASSERT(x);
493                         if (!read_object(*x))
494                             return false;
495                     }
496                     case '2':
497                     {
498                         uint16 *x = va_arg(v, uint16 *);
499                         VOGL_ASSERT(x);
500                         if (!read_object(*x))
501                             return false;
502                     }
503                     case '4':
504                     {
505                         uint32 *x = va_arg(v, uint32 *);
506                         VOGL_ASSERT(x);
507                         if (!read_object(*x))
508                             return false;
509                     }
510                     case ' ':
511                     case ',':
512                     {
513                         break;
514                     }
515                     default:
516                     {
517                         VOGL_ASSERT_ALWAYS;
518                         return false;
519                     }
520                 }
521             }
522
523             va_end(v);
524             return true;
525         }
526
527     private:
528         data_stream *m_pStream;
529
530         bool m_little_endian;
531     };
532
533     // Write operators
534     inline data_stream_serializer &operator<<(data_stream_serializer &serializer, bool val)
535     {
536         serializer.write_value(val);
537         return serializer;
538     }
539     inline data_stream_serializer &operator<<(data_stream_serializer &serializer, int8 val)
540     {
541         serializer.write_value(val);
542         return serializer;
543     }
544     inline data_stream_serializer &operator<<(data_stream_serializer &serializer, uint8 val)
545     {
546         serializer.write_value(val);
547         return serializer;
548     }
549     inline data_stream_serializer &operator<<(data_stream_serializer &serializer, int16 val)
550     {
551         serializer.write_value(val);
552         return serializer;
553     }
554     inline data_stream_serializer &operator<<(data_stream_serializer &serializer, uint16 val)
555     {
556         serializer.write_value(val);
557         return serializer;
558     }
559     inline data_stream_serializer &operator<<(data_stream_serializer &serializer, int32 val)
560     {
561         serializer.write_value(val);
562         return serializer;
563     }
564     inline data_stream_serializer &operator<<(data_stream_serializer &serializer, uint32 val)
565     {
566         serializer.write_uint_vlc(val);
567         return serializer;
568     }
569     inline data_stream_serializer &operator<<(data_stream_serializer &serializer, int64_t val)
570     {
571         serializer.write_value(val);
572         return serializer;
573     }
574     inline data_stream_serializer &operator<<(data_stream_serializer &serializer, uint64_t val)
575     {
576         serializer.write_value(val);
577         return serializer;
578     }
579     inline data_stream_serializer &operator<<(data_stream_serializer &serializer, float val)
580     {
581         serializer.write_value(val);
582         return serializer;
583     }
584     inline data_stream_serializer &operator<<(data_stream_serializer &serializer, double val)
585     {
586         serializer.write_value(val);
587         return serializer;
588     }
589     inline data_stream_serializer &operator<<(data_stream_serializer &serializer, const char *p)
590     {
591         serializer.write_c_str(p);
592         return serializer;
593     }
594
595     inline data_stream_serializer &operator<<(data_stream_serializer &serializer, const dynamic_string &str)
596     {
597         serializer.write_string(str);
598         return serializer;
599     }
600
601     template <typename T>
602     inline data_stream_serializer &operator<<(data_stream_serializer &serializer, const vogl::vector<T> &vec)
603     {
604         serializer.write_vector(vec);
605         return serializer;
606     }
607
608     template <typename T>
609     inline data_stream_serializer &operator<<(data_stream_serializer &serializer, const T *p)
610     {
611         serializer.write_object(*p);
612         return serializer;
613     }
614
615     // Read operators
616     inline data_stream_serializer &operator>>(data_stream_serializer &serializer, bool &val)
617     {
618         serializer.read_object(val);
619         return serializer;
620     }
621     inline data_stream_serializer &operator>>(data_stream_serializer &serializer, int8 &val)
622     {
623         serializer.read_object(val);
624         return serializer;
625     }
626     inline data_stream_serializer &operator>>(data_stream_serializer &serializer, uint8 &val)
627     {
628         serializer.read_object(val);
629         return serializer;
630     }
631     inline data_stream_serializer &operator>>(data_stream_serializer &serializer, int16 &val)
632     {
633         serializer.read_object(val);
634         return serializer;
635     }
636     inline data_stream_serializer &operator>>(data_stream_serializer &serializer, uint16 &val)
637     {
638         serializer.read_object(val);
639         return serializer;
640     }
641     inline data_stream_serializer &operator>>(data_stream_serializer &serializer, int32 &val)
642     {
643         serializer.read_object(val);
644         return serializer;
645     }
646     inline data_stream_serializer &operator>>(data_stream_serializer &serializer, uint32 &val)
647     {
648         serializer.read_uint_vlc(val);
649         return serializer;
650     }
651     inline data_stream_serializer &operator>>(data_stream_serializer &serializer, int64_t &val)
652     {
653         serializer.read_object(val);
654         return serializer;
655     }
656     inline data_stream_serializer &operator>>(data_stream_serializer &serializer, uint64_t &val)
657     {
658         serializer.read_object(val);
659         return serializer;
660     }
661 #ifdef NEVER // __amd64__
662     inline data_stream_serializer &operator>>(data_stream_serializer &serializer, long &val)
663     {
664         serializer.read_object(val);
665         return serializer;
666     }
667     inline data_stream_serializer &operator>>(data_stream_serializer &serializer, unsigned long &val)
668     {
669         serializer.read_object(val);
670         return serializer;
671     }
672 #endif
673     inline data_stream_serializer &operator>>(data_stream_serializer &serializer, float &val)
674     {
675         serializer.read_object(val);
676         return serializer;
677     }
678     inline data_stream_serializer &operator>>(data_stream_serializer &serializer, double &val)
679     {
680         serializer.read_object(val);
681         return serializer;
682     }
683
684     inline data_stream_serializer &operator>>(data_stream_serializer &serializer, dynamic_string &str)
685     {
686         serializer.read_string(str);
687         return serializer;
688     }
689
690     template <typename T>
691     inline data_stream_serializer &operator>>(data_stream_serializer &serializer, vogl::vector<T> &vec)
692     {
693         serializer.read_vector(vec);
694         return serializer;
695     }
696
697     template <typename T>
698     inline data_stream_serializer &operator>>(data_stream_serializer &serializer, T *p)
699     {
700         serializer.read_object(*p);
701         return serializer;
702     }
703
704 } // namespace vogl