1 /*
2  *  Copyright (C) 2005-2018 Team Kodi
3  *  This file is part of Kodi - https://kodi.tv
4  *
5  *  SPDX-License-Identifier: GPL-2.0-or-later
6  *  See LICENSES/README.md for more information.
7  */
8 
9 #pragma once
10 
11 #include "XBDateTime.h"
12 
13 #include <memory>
14 #include <string>
15 #include <vector>
16 
17 #define CARCHIVE_BUFFER_MAX 4096
18 
19 namespace XFILE
20 {
21   class CFile;
22 }
23 class CVariant;
24 class IArchivable;
25 
26 class CArchive
27 {
28 public:
29   CArchive(XFILE::CFile* pFile, int mode);
30   ~CArchive();
31 
32   /* CArchive support storing and loading of all C basic integer types
33    * C basic types was chosen instead of fixed size ints (int16_t - int64_t) to support all integer typedefs
34    * For example size_t can be typedef of unsigned int, long or long long depending on platform
35    * while int32_t and int64_t are usually unsigned short, int or long long, but not long
36    * and even if int and long can have same binary representation they are different types for compiler
37    * According to section 5.2.4.2.1 of C99 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
38    * minimal size of short int is 16 bits
39    * minimal size of int is 16 bits (usually 32 or 64 bits, larger or equal to short int)
40    * minimal size of long int is 32 bits (larger or equal to int)
41    * minimal size of long long int is 64 bits (larger or equal to long int) */
42   // storing
43   CArchive& operator<<(float f);
44   CArchive& operator<<(double d);
45   CArchive& operator<<(short int s);
46   CArchive& operator<<(unsigned short int us);
47   CArchive& operator<<(int i);
48   CArchive& operator<<(unsigned int ui);
49   CArchive& operator<<(long int l);
50   CArchive& operator<<(unsigned long int ul);
51   CArchive& operator<<(long long int ll);
52   CArchive& operator<<(unsigned long long int ull);
53   CArchive& operator<<(bool b);
54   CArchive& operator<<(char c);
55   CArchive& operator<<(const std::string &str);
56   CArchive& operator<<(const std::wstring& wstr);
57   CArchive& operator<<(const KODI::TIME::SystemTime& time);
58   CArchive& operator<<(IArchivable& obj);
59   CArchive& operator<<(const CVariant& variant);
60   CArchive& operator<<(const std::vector<std::string>& strArray);
61   CArchive& operator<<(const std::vector<int>& iArray);
62 
63   // loading
64   inline CArchive& operator>>(float& f)
65   {
66     return streamin(&f, sizeof(f));
67   }
68 
69   inline CArchive& operator>>(double& d)
70   {
71     return streamin(&d, sizeof(d));
72   }
73 
74   inline CArchive& operator>>(short int& s)
75   {
76     return streamin(&s, sizeof(s));
77   }
78 
79   inline CArchive& operator>>(unsigned short int& us)
80   {
81     return streamin(&us, sizeof(us));
82   }
83 
84   inline CArchive& operator>>(int& i)
85   {
86     return streamin(&i, sizeof(i));
87   }
88 
89   inline CArchive& operator>>(unsigned int& ui)
90   {
91     return streamin(&ui, sizeof(ui));
92   }
93 
94   inline CArchive& operator>>(long int& l)
95   {
96     return streamin(&l, sizeof(l));
97   }
98 
99   inline CArchive& operator>>(unsigned long int& ul)
100   {
101     return streamin(&ul, sizeof(ul));
102   }
103 
104   inline CArchive& operator>>(long long int& ll)
105   {
106     return streamin(&ll, sizeof(ll));
107   }
108 
109   inline CArchive& operator>>(unsigned long long int& ull)
110   {
111     return streamin(&ull, sizeof(ull));
112   }
113 
114   inline CArchive& operator>>(bool& b)
115   {
116     return streamin(&b, sizeof(b));
117   }
118 
119   inline CArchive& operator>>(char& c)
120   {
121     return streamin(&c, sizeof(c));
122   }
123 
124   CArchive& operator>>(std::string &str);
125   CArchive& operator>>(std::wstring& wstr);
126   CArchive& operator>>(KODI::TIME::SystemTime& time);
127   CArchive& operator>>(IArchivable& obj);
128   CArchive& operator>>(CVariant& variant);
129   CArchive& operator>>(std::vector<std::string>& strArray);
130   CArchive& operator>>(std::vector<int>& iArray);
131 
132   bool IsLoading() const;
133   bool IsStoring() const;
134 
135   void Close();
136 
137   enum Mode {load = 0, store};
138 
139 protected:
streamout(const void * dataPtr,size_t size)140   inline CArchive &streamout(const void *dataPtr, size_t size)
141   {
142     auto ptr = static_cast<const uint8_t *>(dataPtr);
143     /* Note, the buffer is flushed as soon as it is full (m_BufferRemain == size) rather
144      * than waiting until we attempt to put more data into an already full buffer */
145     if (m_BufferRemain > size)
146     {
147       memcpy(m_BufferPos, ptr, size);
148       m_BufferPos += size;
149       m_BufferRemain -= size;
150       return *this;
151     }
152 
153     return streamout_bufferwrap(ptr, size);
154   }
155 
streamin(void * dataPtr,size_t size)156   inline CArchive &streamin(void *dataPtr, size_t size)
157   {
158     auto ptr = static_cast<uint8_t *>(dataPtr);
159     /* Note, refilling the buffer is deferred until we know we need to read more from it */
160     if (m_BufferRemain >= size)
161     {
162       memcpy(ptr, m_BufferPos, size);
163       m_BufferPos += size;
164       m_BufferRemain -= size;
165       return *this;
166     }
167 
168     return streamin_bufferwrap(ptr, size);
169   }
170 
171   XFILE::CFile* m_pFile; //non-owning
172   int m_iMode;
173   std::unique_ptr<uint8_t[]> m_pBuffer;
174   uint8_t *m_BufferPos;
175   size_t m_BufferRemain;
176 
177 private:
178   void FlushBuffer();
179   CArchive &streamout_bufferwrap(const uint8_t *ptr, size_t size);
180   void FillBuffer();
181   CArchive &streamin_bufferwrap(uint8_t *ptr, size_t size);
182 };
183