Merge pull request #4676 from jmarshallnz/dont_set_scraper_on_tvshow_on_nfo
[vuplus_xbmc] / xbmc / utils / Archive.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include <cstring>
22 #include "Archive.h"
23 #include "filesystem/File.h"
24 #include "Variant.h"
25 #include "utils/log.h"
26
27 #ifdef __GNUC__
28 #pragma GCC diagnostic ignored "-Wlong-long"
29 #endif
30
31 using namespace XFILE;
32
33 #define BUFFER_MAX 4096
34
35 CArchive::CArchive(CFile* pFile, int mode)
36 {
37   m_pFile = pFile;
38   m_iMode = mode;
39
40   m_pBuffer = new uint8_t[BUFFER_MAX];
41   memset(m_pBuffer, 0, BUFFER_MAX);
42
43   m_BufferPos = 0;
44 }
45
46 CArchive::~CArchive()
47 {
48   FlushBuffer();
49   delete[] m_pBuffer;
50   m_BufferPos = 0;
51 }
52
53 void CArchive::Close()
54 {
55   FlushBuffer();
56 }
57
58 bool CArchive::IsLoading()
59 {
60   return (m_iMode == load);
61 }
62
63 bool CArchive::IsStoring()
64 {
65   return (m_iMode == store);
66 }
67
68 CArchive& CArchive::operator<<(float f)
69 {
70   return streamout(&f, sizeof(f));
71 }
72
73 CArchive& CArchive::operator<<(double d)
74 {
75   return streamout(&d, sizeof(d));
76 }
77
78 CArchive& CArchive::operator<<(short int s)
79 {
80   return streamout(&s, sizeof(s));
81 }
82
83 CArchive& CArchive::operator<<(unsigned short int us)
84 {
85   return streamout(&us, sizeof(us));
86 }
87
88 CArchive& CArchive::operator<<(int i)
89 {
90   return streamout(&i, sizeof(i));
91 }
92
93 CArchive& CArchive::operator<<(unsigned int ui)
94 {
95   return streamout(&ui, sizeof(ui));
96 }
97
98 CArchive& CArchive::operator<<(long int l)
99 {
100   return streamout(&l, sizeof(l));
101 }
102
103 CArchive& CArchive::operator<<(unsigned long int ul)
104 {
105   return streamout(&ul, sizeof(ul));
106 }
107
108 CArchive& CArchive::operator<<(long long int ll)
109 {
110   return streamout(&ll, sizeof(ll));
111 }
112
113 CArchive& CArchive::operator<<(unsigned long long int ull)
114 {
115   return streamout(&ull, sizeof(ull));
116 }
117
118 CArchive& CArchive::operator<<(bool b)
119 {
120   return streamout(&b, sizeof(b));
121 }
122
123 CArchive& CArchive::operator<<(char c)
124 {
125   return streamout(&c, sizeof(c));
126 }
127
128 CArchive& CArchive::operator<<(const std::string& str)
129 {
130   *this << str.size();
131
132   return streamout(str.data(), str.size() * sizeof(char));
133 }
134
135 CArchive& CArchive::operator<<(const std::wstring& wstr)
136 {
137   *this << wstr.size();
138
139   return streamout(wstr.data(), wstr.size() * sizeof(wchar_t));
140 }
141
142 CArchive& CArchive::operator<<(const SYSTEMTIME& time)
143 {
144   return streamout(&time, sizeof(SYSTEMTIME));
145 }
146
147 CArchive& CArchive::operator<<(IArchivable& obj)
148 {
149   obj.Archive(*this);
150
151   return *this;
152 }
153
154 CArchive& CArchive::operator<<(const CVariant& variant)
155 {
156   *this << (int)variant.type();
157   switch (variant.type())
158   {
159   case CVariant::VariantTypeInteger:
160     *this << variant.asInteger();
161     break;
162   case CVariant::VariantTypeUnsignedInteger:
163     *this << variant.asUnsignedInteger();
164     break;
165   case CVariant::VariantTypeBoolean:
166     *this << variant.asBoolean();
167     break;
168   case CVariant::VariantTypeString:
169     *this << variant.asString();
170     break;
171   case CVariant::VariantTypeWideString:
172     *this << variant.asWideString();
173     break;
174   case CVariant::VariantTypeDouble:
175     *this << variant.asDouble();
176     break;
177   case CVariant::VariantTypeArray:
178     *this << variant.size();
179     for (unsigned int index = 0; index < variant.size(); index++)
180       *this << variant[index];
181     break;
182   case CVariant::VariantTypeObject:
183     *this << variant.size();
184     for (CVariant::const_iterator_map itr = variant.begin_map(); itr != variant.end_map(); itr++)
185     {
186       *this << itr->first;
187       *this << itr->second;
188     }
189     break;
190   case CVariant::VariantTypeNull:
191   case CVariant::VariantTypeConstNull:
192   default:
193     break;
194   }
195
196   return *this;
197 }
198
199 CArchive& CArchive::operator<<(const std::vector<std::string>& strArray)
200 {
201   *this << strArray.size();
202   for (size_t index = 0; index < strArray.size(); index++)
203     *this << strArray.at(index);
204
205   return *this;
206 }
207
208 CArchive& CArchive::operator<<(const std::vector<int>& iArray)
209 {
210   *this << iArray.size();
211   for (size_t index = 0; index < iArray.size(); index++)
212     *this << iArray.at(index);
213
214   return *this;
215 }
216
217 inline CArchive& CArchive::streamout(const void* dataPtr, size_t size)
218 {
219   const uint8_t* ptr = (const uint8_t*)dataPtr;
220
221   if (size + m_BufferPos >= BUFFER_MAX)
222   {
223     FlushBuffer();
224     while (size >= BUFFER_MAX)
225     {
226       memcpy(m_pBuffer, ptr, BUFFER_MAX);
227       m_BufferPos = BUFFER_MAX;
228       ptr += BUFFER_MAX;
229       size -= BUFFER_MAX;
230       FlushBuffer();
231     }
232   }
233
234   memcpy(m_pBuffer + m_BufferPos, ptr, size);
235   m_BufferPos += size;
236
237   return *this;
238 }
239
240 CArchive& CArchive::operator>>(float& f)
241 {
242   return streamin(&f, sizeof(f));
243 }
244
245 CArchive& CArchive::operator>>(double& d)
246 {
247   return streamin(&d, sizeof(d));
248 }
249
250 CArchive& CArchive::operator>>(short int& s)
251 {
252   return streamin(&s, sizeof(s));
253 }
254
255 CArchive& CArchive::operator>>(unsigned short int& us)
256 {
257   return streamin(&us, sizeof(us));
258 }
259
260 CArchive& CArchive::operator>>(int& i)
261 {
262   return streamin(&i, sizeof(i));
263 }
264
265 CArchive& CArchive::operator>>(unsigned int& ui)
266 {
267   return streamin(&ui, sizeof(ui));
268 }
269
270 CArchive& CArchive::operator>>(long int& l)
271 {
272   return streamin(&l, sizeof(l));
273 }
274
275 CArchive& CArchive::operator>>(unsigned long int& ul)
276 {
277   return streamin(&ul, sizeof(ul));
278 }
279
280 CArchive& CArchive::operator>>(long long int& ll)
281 {
282   return streamin(&ll, sizeof(ll));
283 }
284
285 CArchive& CArchive::operator>>(unsigned long long int& ull)
286 {
287   return streamin(&ull, sizeof(ull));
288 }
289
290 CArchive& CArchive::operator>>(bool& b)
291 {
292   return streamin(&b, sizeof(b));
293 }
294
295 CArchive& CArchive::operator>>(char& c)
296 {
297   return streamin(&c, sizeof(c));
298 }
299
300 CArchive& CArchive::operator>>(std::string& str)
301 {
302   size_t iLength = 0;
303   *this >> iLength;
304
305   char *s = new char[iLength];
306   streamin(s, iLength * sizeof(char));
307   str.assign(s, iLength);
308   delete[] s;
309
310   return *this;
311 }
312
313 CArchive& CArchive::operator>>(std::wstring& wstr)
314 {
315   size_t iLength = 0;
316   *this >> iLength;
317
318   wchar_t * const p = new wchar_t[iLength];
319   streamin(p, iLength * sizeof(wchar_t));
320   wstr.assign(p, iLength);
321   delete[] p;
322
323   return *this;
324 }
325
326 CArchive& CArchive::operator>>(SYSTEMTIME& time)
327 {
328   return streamin(&time, sizeof(SYSTEMTIME));
329 }
330
331 CArchive& CArchive::operator>>(IArchivable& obj)
332 {
333   obj.Archive(*this);
334
335   return *this;
336 }
337
338 CArchive& CArchive::operator>>(CVariant& variant)
339 {
340   int type;
341   *this >> type;
342   variant = CVariant((CVariant::VariantType)type);
343
344   switch (variant.type())
345   {
346   case CVariant::VariantTypeInteger:
347   {
348     int64_t value;
349     *this >> value;
350     variant = value;
351     break;
352   }
353   case CVariant::VariantTypeUnsignedInteger:
354   {
355     uint64_t value;
356     *this >> value;
357     variant = value;
358     break;
359   }
360   case CVariant::VariantTypeBoolean:
361   {
362     bool value;
363     *this >> value;
364     variant = value;
365     break;
366   }
367   case CVariant::VariantTypeString:
368   {
369     std::string value;
370     *this >> value;
371     variant = value;
372     break;
373   }
374   case CVariant::VariantTypeWideString:
375   {
376     std::wstring value;
377     *this >> value;
378     variant = value;
379     break;
380   }
381   case CVariant::VariantTypeDouble:
382   {
383     double value;
384     *this >> value;
385     variant = value;
386     break;
387   }
388   case CVariant::VariantTypeArray:
389   {
390     unsigned int size;
391     *this >> size;
392     for (; size > 0; size--)
393     {
394       CVariant value;
395       *this >> value;
396       variant.append(value);
397     }
398     break;
399   }
400   case CVariant::VariantTypeObject:
401   {
402     unsigned int size;
403     *this >> size;
404     for (; size > 0; size--)
405     {
406       std::string name;
407       CVariant value;
408       *this >> name;
409       *this >> value;
410       variant[name] = value;
411     }
412     break;
413   }
414   case CVariant::VariantTypeNull:
415   case CVariant::VariantTypeConstNull:
416   default:
417     break;
418   }
419
420   return *this;
421 }
422
423 CArchive& CArchive::operator>>(std::vector<std::string>& strArray)
424 {
425   size_t size;
426   *this >> size;
427   strArray.clear();
428   for (size_t index = 0; index < size; index++)
429   {
430     std::string str;
431     *this >> str;
432     strArray.push_back(str);
433   }
434
435   return *this;
436 }
437
438 CArchive& CArchive::operator>>(std::vector<int>& iArray)
439 {
440   size_t size;
441   *this >> size;
442   iArray.clear();
443   for (size_t index = 0; index < size; index++)
444   {
445     int i;
446     *this >> i;
447     iArray.push_back(i);
448   }
449
450   return *this;
451 }
452
453 inline CArchive& CArchive::streamin(void* dataPtr, const size_t size)
454 {
455   size_t read = m_pFile->Read(dataPtr, size);
456   if (read < size)
457   {
458     CLog::Log(LOGERROR, "%s: can't stream out: requested %lu bytes, was read %lu bytes", __FUNCTION__, (unsigned long)size, (unsigned long)read);
459     memset(dataPtr, 0, size);
460   }
461
462   return *this;
463 }
464
465 void CArchive::FlushBuffer()
466 {
467   if (m_BufferPos > 0)
468   {
469     m_pFile->Write(m_pBuffer, m_BufferPos);
470     m_BufferPos = 0;
471   }
472 }