1/////////////////////////////////////////////////////////////////////////////
2// Name:        src/common/datstrm.cpp
3// Purpose:     Data stream classes
4// Author:      Guilhem Lavaux
5// Modified by: Mickael Gilabert
6// Created:     28/06/98
7// RCS-ID:      $Id: datstrm.cpp 53028 2008-04-05 17:28:32Z VZ $
8// Copyright:   (c) Guilhem Lavaux
9// Licence:     wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
16  #pragma hdrstop
17#endif
18
19#if wxUSE_STREAMS
20
21#include "wx/datstrm.h"
22
23#ifndef WX_PRECOMP
24    #include "wx/math.h"
25#endif //WX_PRECOMP
26
27// ---------------------------------------------------------------------------
28// wxDataInputStream
29// ---------------------------------------------------------------------------
30
31#if wxUSE_UNICODE
32wxDataInputStream::wxDataInputStream(wxInputStream& s, const wxMBConv& conv)
33  : m_input(&s), m_be_order(false), m_conv(conv.Clone())
34#else
35wxDataInputStream::wxDataInputStream(wxInputStream& s)
36  : m_input(&s), m_be_order(false)
37#endif
38{
39}
40
41wxDataInputStream::~wxDataInputStream()
42{
43#if wxUSE_UNICODE
44    delete m_conv;
45#endif // wxUSE_UNICODE
46}
47
48#if wxHAS_INT64
49wxUint64 wxDataInputStream::Read64()
50{
51  wxUint64 tmp;
52  Read64(&tmp, 1);
53  return tmp;
54}
55#endif // wxHAS_INT64
56
57wxUint32 wxDataInputStream::Read32()
58{
59  wxUint32 i32;
60
61  m_input->Read(&i32, 4);
62
63  if (m_be_order)
64    return wxUINT32_SWAP_ON_LE(i32);
65  else
66    return wxUINT32_SWAP_ON_BE(i32);
67}
68
69wxUint16 wxDataInputStream::Read16()
70{
71  wxUint16 i16;
72
73  m_input->Read(&i16, 2);
74
75  if (m_be_order)
76    return wxUINT16_SWAP_ON_LE(i16);
77  else
78    return wxUINT16_SWAP_ON_BE(i16);
79}
80
81wxUint8 wxDataInputStream::Read8()
82{
83  wxUint8 buf;
84
85  m_input->Read(&buf, 1);
86  return (wxUint8)buf;
87}
88
89double wxDataInputStream::ReadDouble()
90{
91#if wxUSE_APPLE_IEEE
92  char buf[10];
93
94  m_input->Read(buf, 10);
95  return ConvertFromIeeeExtended((const wxInt8 *)buf);
96#else
97  return 0.0;
98#endif
99}
100
101wxString wxDataInputStream::ReadString()
102{
103    wxString ret;
104
105    const size_t len = Read32();
106    if ( len > 0 )
107    {
108#if wxUSE_UNICODE
109        wxCharBuffer tmp(len + 1);
110        if ( tmp )
111        {
112            m_input->Read(tmp.data(), len);
113            tmp.data()[len] = '\0';
114            ret = m_conv->cMB2WX(tmp.data());
115        }
116#else
117        wxStringBuffer buf(ret, len);
118        if ( buf )
119            m_input->Read(buf, len);
120#endif
121    }
122
123    return ret;
124}
125
126#if wxUSE_LONGLONG
127
128template <class T>
129static
130void DoReadLL(T *buffer, size_t size, wxInputStream *input, bool be_order)
131{
132    typedef T DataType;
133    unsigned char *pchBuffer = new unsigned char[size * 8];
134    // TODO: Check for overflow when size is of type uint and is > than 512m
135    input->Read(pchBuffer, size * 8);
136    size_t idx_base = 0;
137    if ( be_order )
138    {
139        for ( size_t uiIndex = 0; uiIndex != size; ++uiIndex )
140        {
141            buffer[uiIndex] = 0l;
142            for ( unsigned ui = 0; ui != 8; ++ui )
143            {
144                buffer[uiIndex] = buffer[uiIndex] * 256l +
145                            DataType((unsigned long) pchBuffer[idx_base + ui]);
146            }
147
148            idx_base += 8;
149        }
150    }
151    else // little endian
152    {
153        for ( size_t uiIndex=0; uiIndex!=size; ++uiIndex )
154        {
155            buffer[uiIndex] = 0l;
156            for ( unsigned ui=0; ui!=8; ++ui )
157                buffer[uiIndex] = buffer[uiIndex] * 256l +
158                    DataType((unsigned long) pchBuffer[idx_base + 7 - ui]);
159            idx_base += 8;
160        }
161    }
162    delete[] pchBuffer;
163}
164
165template <class T>
166static void DoWriteLL(const T *buffer, size_t size, wxOutputStream *output, bool be_order)
167{
168    typedef T DataType;
169    unsigned char *pchBuffer = new unsigned char[size * 8];
170    size_t idx_base = 0;
171    if ( be_order )
172    {
173        for ( size_t uiIndex = 0; uiIndex != size; ++uiIndex )
174        {
175            DataType i64 = buffer[uiIndex];
176            for ( unsigned ui = 0; ui != 8; ++ui )
177            {
178                pchBuffer[idx_base + 7 - ui] =
179                    (unsigned char) (i64.GetLo() & 255l);
180                i64 >>= 8l;
181            }
182
183            idx_base += 8;
184        }
185    }
186    else // little endian
187    {
188        for ( size_t uiIndex=0; uiIndex != size; ++uiIndex )
189        {
190            DataType i64 = buffer[uiIndex];
191            for (unsigned ui=0; ui!=8; ++ui)
192            {
193                pchBuffer[idx_base + ui] =
194                    (unsigned char) (i64.GetLo() & 255l);
195                i64 >>= 8l;
196            }
197
198            idx_base += 8;
199        }
200    }
201
202    // TODO: Check for overflow when size is of type uint and is > than 512m
203    output->Write(pchBuffer, size * 8);
204    delete[] pchBuffer;
205}
206
207#endif // wxUSE_LONGLONG
208
209#ifdef wxLongLong_t
210
211template <class T>
212static
213void DoReadI64(T *buffer, size_t size, wxInputStream *input, bool be_order)
214{
215    typedef T DataType;
216    unsigned char *pchBuffer = (unsigned char*) buffer;
217    // TODO: Check for overflow when size is of type uint and is > than 512m
218    input->Read(pchBuffer, size * 8);
219    if ( be_order )
220    {
221        for ( wxUint32 i = 0; i < size; i++ )
222        {
223            DataType v = wxUINT64_SWAP_ON_LE(*buffer);
224            *(buffer++) = v;
225        }
226    }
227    else // little endian
228    {
229        for ( wxUint32 i=0; i<size; i++ )
230        {
231            DataType v = wxUINT64_SWAP_ON_BE(*buffer);
232            *(buffer++) = v;
233        }
234    }
235}
236
237template <class T>
238static
239void DoWriteI64(const T *buffer, size_t size, wxOutputStream *output, bool be_order)
240{
241  typedef T DataType;
242  if ( be_order )
243  {
244    for ( size_t i = 0; i < size; i++ )
245    {
246      DataType i64 = wxUINT64_SWAP_ON_LE(*buffer);
247      buffer++;
248      output->Write(&i64, 8);
249    }
250  }
251  else // little endian
252  {
253    for ( size_t i=0; i < size; i++ )
254    {
255      DataType i64 = wxUINT64_SWAP_ON_BE(*buffer);
256      buffer++;
257      output->Write(&i64, 8);
258    }
259  }
260}
261
262#endif // wxLongLong_t
263
264
265#if wxHAS_INT64
266void wxDataInputStream::Read64(wxUint64 *buffer, size_t size)
267{
268#ifndef wxLongLong_t
269    DoReadLL(buffer, size, m_input, m_be_order);
270#else
271    DoReadI64(buffer, size, m_input, m_be_order);
272#endif
273}
274
275void wxDataInputStream::Read64(wxInt64 *buffer, size_t size)
276{
277#ifndef wxLongLong_t
278    DoReadLL(buffer, size, m_input, m_be_order);
279#else
280    DoReadI64(buffer, size, m_input, m_be_order);
281#endif
282}
283#endif // wxHAS_INT64
284
285#if defined(wxLongLong_t) && wxUSE_LONGLONG
286void wxDataInputStream::Read64(wxULongLong *buffer, size_t size)
287{
288    DoReadLL(buffer, size, m_input, m_be_order);
289}
290
291void wxDataInputStream::Read64(wxLongLong *buffer, size_t size)
292{
293    DoReadLL(buffer, size, m_input, m_be_order);
294}
295#endif // wxLongLong_t
296
297#if wxUSE_LONGLONG
298void wxDataInputStream::ReadLL(wxULongLong *buffer, size_t size)
299{
300    DoReadLL(buffer, size, m_input, m_be_order);
301}
302
303void wxDataInputStream::ReadLL(wxLongLong *buffer, size_t size)
304{
305    DoReadLL(buffer, size, m_input, m_be_order);
306}
307
308wxLongLong wxDataInputStream::ReadLL(void)
309{
310    wxLongLong ll;
311    DoReadLL(&ll, (size_t)1, m_input, m_be_order);
312    return ll;
313}
314#endif // wxUSE_LONGLONG
315
316void wxDataInputStream::Read32(wxUint32 *buffer, size_t size)
317{
318    m_input->Read(buffer, size * 4);
319
320    if (m_be_order)
321    {
322        for (wxUint32 i=0; i<size; i++)
323        {
324            wxUint32 v = wxUINT32_SWAP_ON_LE(*buffer);
325            *(buffer++) = v;
326        }
327    }
328    else
329    {
330        for (wxUint32 i=0; i<size; i++)
331        {
332            wxUint32 v = wxUINT32_SWAP_ON_BE(*buffer);
333            *(buffer++) = v;
334        }
335    }
336}
337
338void wxDataInputStream::Read16(wxUint16 *buffer, size_t size)
339{
340  m_input->Read(buffer, size * 2);
341
342  if (m_be_order)
343  {
344    for (wxUint32 i=0; i<size; i++)
345    {
346      wxUint16 v = wxUINT16_SWAP_ON_LE(*buffer);
347      *(buffer++) = v;
348    }
349  }
350  else
351  {
352    for (wxUint32 i=0; i<size; i++)
353    {
354      wxUint16 v = wxUINT16_SWAP_ON_BE(*buffer);
355      *(buffer++) = v;
356    }
357  }
358}
359
360void wxDataInputStream::Read8(wxUint8 *buffer, size_t size)
361{
362  m_input->Read(buffer, size);
363}
364
365void wxDataInputStream::ReadDouble(double *buffer, size_t size)
366{
367  for (wxUint32 i=0; i<size; i++)
368  {
369    *(buffer++) = ReadDouble();
370  }
371}
372
373wxDataInputStream& wxDataInputStream::operator>>(wxString& s)
374{
375  s = ReadString();
376  return *this;
377}
378
379wxDataInputStream& wxDataInputStream::operator>>(wxInt8& c)
380{
381  c = (wxInt8)Read8();
382  return *this;
383}
384
385wxDataInputStream& wxDataInputStream::operator>>(wxInt16& i)
386{
387  i = (wxInt16)Read16();
388  return *this;
389}
390
391wxDataInputStream& wxDataInputStream::operator>>(wxInt32& i)
392{
393  i = (wxInt32)Read32();
394  return *this;
395}
396
397wxDataInputStream& wxDataInputStream::operator>>(wxUint8& c)
398{
399  c = Read8();
400  return *this;
401}
402
403wxDataInputStream& wxDataInputStream::operator>>(wxUint16& i)
404{
405  i = Read16();
406  return *this;
407}
408
409wxDataInputStream& wxDataInputStream::operator>>(wxUint32& i)
410{
411  i = Read32();
412  return *this;
413}
414
415#if wxHAS_INT64
416wxDataInputStream& wxDataInputStream::operator>>(wxUint64& i)
417{
418  i = Read64();
419  return *this;
420}
421
422wxDataInputStream& wxDataInputStream::operator>>(wxInt64& i)
423{
424  i = Read64();
425  return *this;
426}
427#endif // wxHAS_INT64
428
429#if defined(wxLongLong_t) && wxUSE_LONGLONG
430wxDataInputStream& wxDataInputStream::operator>>(wxULongLong& i)
431{
432  i = ReadLL();
433  return *this;
434}
435
436wxDataInputStream& wxDataInputStream::operator>>(wxLongLong& i)
437{
438  i = ReadLL();
439  return *this;
440}
441#endif // wxLongLong_t
442
443wxDataInputStream& wxDataInputStream::operator>>(double& i)
444{
445  i = ReadDouble();
446  return *this;
447}
448
449wxDataInputStream& wxDataInputStream::operator>>(float& f)
450{
451  f = (float)ReadDouble();
452  return *this;
453}
454
455// ---------------------------------------------------------------------------
456// wxDataOutputStream
457// ---------------------------------------------------------------------------
458
459#if wxUSE_UNICODE
460wxDataOutputStream::wxDataOutputStream(wxOutputStream& s, const wxMBConv& conv)
461  : m_output(&s), m_be_order(false), m_conv(conv.Clone())
462#else
463wxDataOutputStream::wxDataOutputStream(wxOutputStream& s)
464  : m_output(&s), m_be_order(false)
465#endif
466{
467}
468
469wxDataOutputStream::~wxDataOutputStream()
470{
471#if wxUSE_UNICODE
472    delete m_conv;
473#endif // wxUSE_UNICODE
474}
475
476#if wxHAS_INT64
477void wxDataOutputStream::Write64(wxUint64 i)
478{
479  Write64(&i, 1);
480}
481
482void wxDataOutputStream::Write64(wxInt64 i)
483{
484  Write64(&i, 1);
485}
486#endif // wxHAS_INT64
487
488void wxDataOutputStream::Write32(wxUint32 i)
489{
490  wxUint32 i32;
491
492  if (m_be_order)
493    i32 = wxUINT32_SWAP_ON_LE(i);
494  else
495    i32 = wxUINT32_SWAP_ON_BE(i);
496  m_output->Write(&i32, 4);
497}
498
499void wxDataOutputStream::Write16(wxUint16 i)
500{
501  wxUint16 i16;
502
503  if (m_be_order)
504    i16 = wxUINT16_SWAP_ON_LE(i);
505  else
506    i16 = wxUINT16_SWAP_ON_BE(i);
507
508  m_output->Write(&i16, 2);
509}
510
511void wxDataOutputStream::Write8(wxUint8 i)
512{
513  m_output->Write(&i, 1);
514}
515
516void wxDataOutputStream::WriteString(const wxString& string)
517{
518#if wxUSE_UNICODE
519  const wxWX2MBbuf buf = string.mb_str(*m_conv);
520#else
521  const wxWX2MBbuf buf = string.mb_str();
522#endif
523  size_t len = strlen(buf);
524  Write32(len);
525  if (len > 0)
526      m_output->Write(buf, len);
527}
528
529void wxDataOutputStream::WriteDouble(double d)
530{
531  char buf[10];
532
533#if wxUSE_APPLE_IEEE
534  ConvertToIeeeExtended(d, (wxInt8 *)buf);
535#else
536#if !defined(__VMS__) && !defined(__GNUG__)
537# pragma warning "wxDataOutputStream::WriteDouble() not using IeeeExtended - will not work!"
538#endif
539   buf[0] = '\0';
540#endif
541  m_output->Write(buf, 10);
542}
543
544#if wxHAS_INT64
545void wxDataOutputStream::Write64(const wxUint64 *buffer, size_t size)
546{
547#ifndef wxLongLong_t
548    DoWriteLL(buffer, size, m_output, m_be_order);
549#else
550    DoWriteI64(buffer, size, m_output, m_be_order);
551#endif
552}
553
554void wxDataOutputStream::Write64(const wxInt64 *buffer, size_t size)
555{
556#ifndef wxLongLong_t
557    DoWriteLL(buffer, size, m_output, m_be_order);
558#else
559    DoWriteI64(buffer, size, m_output, m_be_order);
560#endif
561}
562#endif // wxHAS_INT64
563
564#if defined(wxLongLong_t) && wxUSE_LONGLONG
565void wxDataOutputStream::Write64(const wxULongLong *buffer, size_t size)
566{
567    DoWriteLL(buffer, size, m_output, m_be_order);
568}
569
570void wxDataOutputStream::Write64(const wxLongLong *buffer, size_t size)
571{
572    DoWriteLL(buffer, size, m_output, m_be_order);
573}
574#endif // wxLongLong_t
575
576#if wxUSE_LONGLONG
577void wxDataOutputStream::WriteLL(const wxULongLong *buffer, size_t size)
578{
579    DoWriteLL(buffer, size, m_output, m_be_order);
580}
581
582void wxDataOutputStream::WriteLL(const wxLongLong *buffer, size_t size)
583{
584    DoWriteLL(buffer, size, m_output, m_be_order);
585}
586
587void wxDataOutputStream::WriteLL(const wxLongLong &ll)
588{
589    WriteLL(&ll, 1);
590}
591
592void wxDataOutputStream::WriteLL(const wxULongLong &ll)
593{
594    WriteLL(&ll, 1);
595}
596#endif // wxUSE_LONGLONG
597
598void wxDataOutputStream::Write32(const wxUint32 *buffer, size_t size)
599{
600  if (m_be_order)
601  {
602    for (wxUint32 i=0; i<size ;i++)
603    {
604      wxUint32 i32 = wxUINT32_SWAP_ON_LE(*buffer);
605      buffer++;
606      m_output->Write(&i32, 4);
607    }
608  }
609  else
610  {
611    for (wxUint32 i=0; i<size ;i++)
612    {
613      wxUint32 i32 = wxUINT32_SWAP_ON_BE(*buffer);
614      buffer++;
615      m_output->Write(&i32, 4);
616    }
617  }
618}
619
620void wxDataOutputStream::Write16(const wxUint16 *buffer, size_t size)
621{
622  if (m_be_order)
623  {
624    for (wxUint32 i=0; i<size ;i++)
625    {
626      wxUint16 i16 = wxUINT16_SWAP_ON_LE(*buffer);
627      buffer++;
628      m_output->Write(&i16, 2);
629    }
630  }
631  else
632  {
633    for (wxUint32 i=0; i<size ;i++)
634    {
635      wxUint16 i16 = wxUINT16_SWAP_ON_BE(*buffer);
636      buffer++;
637      m_output->Write(&i16, 2);
638    }
639  }
640}
641
642void wxDataOutputStream::Write8(const wxUint8 *buffer, size_t size)
643{
644  m_output->Write(buffer, size);
645}
646
647void wxDataOutputStream::WriteDouble(const double *buffer, size_t size)
648{
649  for (wxUint32 i=0; i<size; i++)
650  {
651    WriteDouble(*(buffer++));
652  }
653}
654
655wxDataOutputStream& wxDataOutputStream::operator<<(const wxChar *string)
656{
657  Write32(wxStrlen(string));
658  m_output->Write((const char *)string, wxStrlen(string)*sizeof(wxChar));
659  return *this;
660}
661
662wxDataOutputStream& wxDataOutputStream::operator<<(const wxString& string)
663{
664  WriteString(string);
665  return *this;
666}
667
668wxDataOutputStream& wxDataOutputStream::operator<<(wxInt8 c)
669{
670  Write8((wxUint8)c);
671  return *this;
672}
673
674wxDataOutputStream& wxDataOutputStream::operator<<(wxInt16 i)
675{
676  Write16((wxUint16)i);
677  return *this;
678}
679
680wxDataOutputStream& wxDataOutputStream::operator<<(wxInt32 i)
681{
682  Write32((wxUint32)i);
683  return *this;
684}
685
686wxDataOutputStream& wxDataOutputStream::operator<<(wxUint8 c)
687{
688  Write8(c);
689  return *this;
690}
691
692wxDataOutputStream& wxDataOutputStream::operator<<(wxUint16 i)
693{
694  Write16(i);
695  return *this;
696}
697
698wxDataOutputStream& wxDataOutputStream::operator<<(wxUint32 i)
699{
700  Write32(i);
701  return *this;
702}
703
704#if wxHAS_INT64
705wxDataOutputStream& wxDataOutputStream::operator<<(wxUint64 i)
706{
707  Write64(i);
708  return *this;
709}
710
711wxDataOutputStream& wxDataOutputStream::operator<<(wxInt64 i)
712{
713  Write64(i);
714  return *this;
715}
716#endif // wxHAS_INT64
717
718#if defined(wxLongLong_t) && wxUSE_LONGLONG
719wxDataOutputStream& wxDataOutputStream::operator<<(const wxULongLong &i)
720{
721  WriteLL(i);
722  return *this;
723}
724
725wxDataOutputStream& wxDataOutputStream::operator<<(const wxLongLong &i)
726{
727  WriteLL(i);
728  return *this;
729}
730#endif // wxLongLong_t
731
732wxDataOutputStream& wxDataOutputStream::operator<<(double f)
733{
734  WriteDouble(f);
735  return *this;
736}
737
738wxDataOutputStream& wxDataOutputStream::operator<<(float f)
739{
740  WriteDouble((double)f);
741  return *this;
742}
743
744#endif
745  // wxUSE_STREAMS
746