]> git.saurik.com Git - wxWidgets.git/blob - src/common/datstrm.cpp
Make code reading BMP files more robust.
[wxWidgets.git] / src / common / datstrm.cpp
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$
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 namespace
28 {
29
30 // helper unions used to swap bytes of floats and doubles
31 union Float32Data
32 {
33 wxFloat32 f;
34 wxUint32 i;
35 };
36
37 union Float64Data
38 {
39 wxFloat64 f;
40 wxUint32 i[2];
41 };
42
43 } // anonymous namespace
44
45 // ----------------------------------------------------------------------------
46 // wxDataStreamBase
47 // ----------------------------------------------------------------------------
48
49 wxDataStreamBase::wxDataStreamBase(const wxMBConv& conv)
50 #if wxUSE_UNICODE
51 : m_conv(conv.Clone())
52 #endif // wxUSE_UNICODE
53 {
54 // It is unused in non-Unicode build, so suppress a warning there.
55 wxUnusedVar(conv);
56
57 m_be_order = false;
58
59 // For compatibility with the existing data files, we use extended
60 // precision if it is available, i.e. if wxUSE_APPLE_IEEE is on.
61 #if wxUSE_APPLE_IEEE
62 m_useExtendedPrecision = true;
63 #endif // wxUSE_APPLE_IEEE
64 }
65
66 #if wxUSE_UNICODE
67 void wxDataStreamBase::SetConv( const wxMBConv &conv )
68 {
69 delete m_conv;
70 m_conv = conv.Clone();
71 }
72 #endif
73
74 wxDataStreamBase::~wxDataStreamBase()
75 {
76 #if wxUSE_UNICODE
77 delete m_conv;
78 #endif // wxUSE_UNICODE
79 }
80
81 // ---------------------------------------------------------------------------
82 // wxDataInputStream
83 // ---------------------------------------------------------------------------
84
85 wxDataInputStream::wxDataInputStream(wxInputStream& s, const wxMBConv& conv)
86 : wxDataStreamBase(conv),
87 m_input(&s)
88 {
89 }
90
91 #if wxHAS_INT64
92 wxUint64 wxDataInputStream::Read64()
93 {
94 wxUint64 tmp;
95 Read64(&tmp, 1);
96 return tmp;
97 }
98 #endif // wxHAS_INT64
99
100 wxUint32 wxDataInputStream::Read32()
101 {
102 wxUint32 i32;
103
104 m_input->Read(&i32, 4);
105
106 if (m_be_order)
107 return wxUINT32_SWAP_ON_LE(i32);
108 else
109 return wxUINT32_SWAP_ON_BE(i32);
110 }
111
112 wxUint16 wxDataInputStream::Read16()
113 {
114 wxUint16 i16;
115
116 m_input->Read(&i16, 2);
117
118 if (m_be_order)
119 return wxUINT16_SWAP_ON_LE(i16);
120 else
121 return wxUINT16_SWAP_ON_BE(i16);
122 }
123
124 wxUint8 wxDataInputStream::Read8()
125 {
126 wxUint8 buf;
127
128 m_input->Read(&buf, 1);
129 return (wxUint8)buf;
130 }
131
132 double wxDataInputStream::ReadDouble()
133 {
134 #if wxUSE_APPLE_IEEE
135 if ( m_useExtendedPrecision )
136 {
137 char buf[10];
138
139 m_input->Read(buf, 10);
140 return wxConvertFromIeeeExtended((const wxInt8 *)buf);
141 }
142 else
143 #endif // wxUSE_APPLE_IEEE
144 {
145 Float64Data floatData;
146
147 if ( m_be_order == (wxBYTE_ORDER == wxBIG_ENDIAN) )
148 {
149 floatData.i[0] = Read32();
150 floatData.i[1] = Read32();
151 }
152 else
153 {
154 floatData.i[1] = Read32();
155 floatData.i[0] = Read32();
156 }
157
158 return static_cast<double>(floatData.f);
159 }
160 }
161
162 float wxDataInputStream::ReadFloat()
163 {
164 #if wxUSE_APPLE_IEEE
165 if ( m_useExtendedPrecision )
166 {
167 return (float)ReadDouble();
168 }
169 else
170 #endif // wxUSE_APPLE_IEEE
171 {
172 Float32Data floatData;
173
174 floatData.i = Read32();
175 return static_cast<float>(floatData.f);
176 }
177 }
178
179 wxString wxDataInputStream::ReadString()
180 {
181 wxString ret;
182
183 const size_t len = Read32();
184 if ( len > 0 )
185 {
186 #if wxUSE_UNICODE
187 wxCharBuffer tmp(len);
188 if ( tmp )
189 {
190 m_input->Read(tmp.data(), len);
191 ret = m_conv->cMB2WX(tmp.data());
192 }
193 #else
194 wxStringBuffer buf(ret, len);
195 if ( buf )
196 m_input->Read(buf, len);
197 #endif
198 }
199
200 return ret;
201 }
202
203 #if wxUSE_LONGLONG
204
205 template <class T>
206 static
207 void DoReadLL(T *buffer, size_t size, wxInputStream *input, bool be_order)
208 {
209 typedef T DataType;
210 unsigned char *pchBuffer = new unsigned char[size * 8];
211 // TODO: Check for overflow when size is of type uint and is > than 512m
212 input->Read(pchBuffer, size * 8);
213 size_t idx_base = 0;
214 if ( be_order )
215 {
216 for ( size_t uiIndex = 0; uiIndex != size; ++uiIndex )
217 {
218 buffer[uiIndex] = 0l;
219 for ( unsigned ui = 0; ui != 8; ++ui )
220 {
221 buffer[uiIndex] = buffer[uiIndex] * 256l +
222 DataType((unsigned long) pchBuffer[idx_base + ui]);
223 }
224
225 idx_base += 8;
226 }
227 }
228 else // little endian
229 {
230 for ( size_t uiIndex=0; uiIndex!=size; ++uiIndex )
231 {
232 buffer[uiIndex] = 0l;
233 for ( unsigned ui=0; ui!=8; ++ui )
234 buffer[uiIndex] = buffer[uiIndex] * 256l +
235 DataType((unsigned long) pchBuffer[idx_base + 7 - ui]);
236 idx_base += 8;
237 }
238 }
239 delete[] pchBuffer;
240 }
241
242 template <class T>
243 static void DoWriteLL(const T *buffer, size_t size, wxOutputStream *output, bool be_order)
244 {
245 typedef T DataType;
246 unsigned char *pchBuffer = new unsigned char[size * 8];
247 size_t idx_base = 0;
248 if ( be_order )
249 {
250 for ( size_t uiIndex = 0; uiIndex != size; ++uiIndex )
251 {
252 DataType i64 = buffer[uiIndex];
253 for ( unsigned ui = 0; ui != 8; ++ui )
254 {
255 pchBuffer[idx_base + 7 - ui] =
256 (unsigned char) (i64.GetLo() & 255l);
257 i64 >>= 8l;
258 }
259
260 idx_base += 8;
261 }
262 }
263 else // little endian
264 {
265 for ( size_t uiIndex=0; uiIndex != size; ++uiIndex )
266 {
267 DataType i64 = buffer[uiIndex];
268 for (unsigned ui=0; ui!=8; ++ui)
269 {
270 pchBuffer[idx_base + ui] =
271 (unsigned char) (i64.GetLo() & 255l);
272 i64 >>= 8l;
273 }
274
275 idx_base += 8;
276 }
277 }
278
279 // TODO: Check for overflow when size is of type uint and is > than 512m
280 output->Write(pchBuffer, size * 8);
281 delete[] pchBuffer;
282 }
283
284 #endif // wxUSE_LONGLONG
285
286 #ifdef wxLongLong_t
287
288 template <class T>
289 static
290 void DoReadI64(T *buffer, size_t size, wxInputStream *input, bool be_order)
291 {
292 typedef T DataType;
293 unsigned char *pchBuffer = (unsigned char*) buffer;
294 // TODO: Check for overflow when size is of type uint and is > than 512m
295 input->Read(pchBuffer, size * 8);
296 if ( be_order )
297 {
298 for ( wxUint32 i = 0; i < size; i++ )
299 {
300 DataType v = wxUINT64_SWAP_ON_LE(*buffer);
301 *(buffer++) = v;
302 }
303 }
304 else // little endian
305 {
306 for ( wxUint32 i=0; i<size; i++ )
307 {
308 DataType v = wxUINT64_SWAP_ON_BE(*buffer);
309 *(buffer++) = v;
310 }
311 }
312 }
313
314 template <class T>
315 static
316 void DoWriteI64(const T *buffer, size_t size, wxOutputStream *output, bool be_order)
317 {
318 typedef T DataType;
319 if ( be_order )
320 {
321 for ( size_t i = 0; i < size; i++ )
322 {
323 DataType i64 = wxUINT64_SWAP_ON_LE(*buffer);
324 buffer++;
325 output->Write(&i64, 8);
326 }
327 }
328 else // little endian
329 {
330 for ( size_t i=0; i < size; i++ )
331 {
332 DataType i64 = wxUINT64_SWAP_ON_BE(*buffer);
333 buffer++;
334 output->Write(&i64, 8);
335 }
336 }
337 }
338
339 #endif // wxLongLong_t
340
341
342 #if wxHAS_INT64
343 void wxDataInputStream::Read64(wxUint64 *buffer, size_t size)
344 {
345 #ifndef wxLongLong_t
346 DoReadLL(buffer, size, m_input, m_be_order);
347 #else
348 DoReadI64(buffer, size, m_input, m_be_order);
349 #endif
350 }
351
352 void wxDataInputStream::Read64(wxInt64 *buffer, size_t size)
353 {
354 #ifndef wxLongLong_t
355 DoReadLL(buffer, size, m_input, m_be_order);
356 #else
357 DoReadI64(buffer, size, m_input, m_be_order);
358 #endif
359 }
360 #endif // wxHAS_INT64
361
362 #if defined(wxLongLong_t) && wxUSE_LONGLONG
363 void wxDataInputStream::Read64(wxULongLong *buffer, size_t size)
364 {
365 DoReadLL(buffer, size, m_input, m_be_order);
366 }
367
368 void wxDataInputStream::Read64(wxLongLong *buffer, size_t size)
369 {
370 DoReadLL(buffer, size, m_input, m_be_order);
371 }
372 #endif // wxLongLong_t
373
374 #if wxUSE_LONGLONG
375 void wxDataInputStream::ReadLL(wxULongLong *buffer, size_t size)
376 {
377 DoReadLL(buffer, size, m_input, m_be_order);
378 }
379
380 void wxDataInputStream::ReadLL(wxLongLong *buffer, size_t size)
381 {
382 DoReadLL(buffer, size, m_input, m_be_order);
383 }
384
385 wxLongLong wxDataInputStream::ReadLL(void)
386 {
387 wxLongLong ll;
388 DoReadLL(&ll, (size_t)1, m_input, m_be_order);
389 return ll;
390 }
391 #endif // wxUSE_LONGLONG
392
393 void wxDataInputStream::Read32(wxUint32 *buffer, size_t size)
394 {
395 m_input->Read(buffer, size * 4);
396
397 if (m_be_order)
398 {
399 for (wxUint32 i=0; i<size; i++)
400 {
401 wxUint32 v = wxUINT32_SWAP_ON_LE(*buffer);
402 *(buffer++) = v;
403 }
404 }
405 else
406 {
407 for (wxUint32 i=0; i<size; i++)
408 {
409 wxUint32 v = wxUINT32_SWAP_ON_BE(*buffer);
410 *(buffer++) = v;
411 }
412 }
413 }
414
415 void wxDataInputStream::Read16(wxUint16 *buffer, size_t size)
416 {
417 m_input->Read(buffer, size * 2);
418
419 if (m_be_order)
420 {
421 for (wxUint32 i=0; i<size; i++)
422 {
423 wxUint16 v = wxUINT16_SWAP_ON_LE(*buffer);
424 *(buffer++) = v;
425 }
426 }
427 else
428 {
429 for (wxUint32 i=0; i<size; i++)
430 {
431 wxUint16 v = wxUINT16_SWAP_ON_BE(*buffer);
432 *(buffer++) = v;
433 }
434 }
435 }
436
437 void wxDataInputStream::Read8(wxUint8 *buffer, size_t size)
438 {
439 m_input->Read(buffer, size);
440 }
441
442 void wxDataInputStream::ReadDouble(double *buffer, size_t size)
443 {
444 for (wxUint32 i=0; i<size; i++)
445 {
446 *(buffer++) = ReadDouble();
447 }
448 }
449
450 void wxDataInputStream::ReadFloat(float *buffer, size_t size)
451 {
452 for (wxUint32 i=0; i<size; i++)
453 {
454 *(buffer++) = ReadFloat();
455 }
456 }
457
458 wxDataInputStream& wxDataInputStream::operator>>(wxString& s)
459 {
460 s = ReadString();
461 return *this;
462 }
463
464 wxDataInputStream& wxDataInputStream::operator>>(wxInt8& c)
465 {
466 c = (wxInt8)Read8();
467 return *this;
468 }
469
470 wxDataInputStream& wxDataInputStream::operator>>(wxInt16& i)
471 {
472 i = (wxInt16)Read16();
473 return *this;
474 }
475
476 wxDataInputStream& wxDataInputStream::operator>>(wxInt32& i)
477 {
478 i = (wxInt32)Read32();
479 return *this;
480 }
481
482 wxDataInputStream& wxDataInputStream::operator>>(wxUint8& c)
483 {
484 c = Read8();
485 return *this;
486 }
487
488 wxDataInputStream& wxDataInputStream::operator>>(wxUint16& i)
489 {
490 i = Read16();
491 return *this;
492 }
493
494 wxDataInputStream& wxDataInputStream::operator>>(wxUint32& i)
495 {
496 i = Read32();
497 return *this;
498 }
499
500 #if wxHAS_INT64
501 wxDataInputStream& wxDataInputStream::operator>>(wxUint64& i)
502 {
503 i = Read64();
504 return *this;
505 }
506
507 wxDataInputStream& wxDataInputStream::operator>>(wxInt64& i)
508 {
509 i = Read64();
510 return *this;
511 }
512 #endif // wxHAS_INT64
513
514 #if defined(wxLongLong_t) && wxUSE_LONGLONG
515 wxDataInputStream& wxDataInputStream::operator>>(wxULongLong& i)
516 {
517 i = ReadLL();
518 return *this;
519 }
520
521 wxDataInputStream& wxDataInputStream::operator>>(wxLongLong& i)
522 {
523 i = ReadLL();
524 return *this;
525 }
526 #endif // wxLongLong_t
527
528 wxDataInputStream& wxDataInputStream::operator>>(double& d)
529 {
530 d = ReadDouble();
531 return *this;
532 }
533
534 wxDataInputStream& wxDataInputStream::operator>>(float& f)
535 {
536 f = ReadFloat();
537 return *this;
538 }
539
540 // ---------------------------------------------------------------------------
541 // wxDataOutputStream
542 // ---------------------------------------------------------------------------
543
544 wxDataOutputStream::wxDataOutputStream(wxOutputStream& s, const wxMBConv& conv)
545 : wxDataStreamBase(conv),
546 m_output(&s)
547 {
548 }
549
550 #if wxHAS_INT64
551 void wxDataOutputStream::Write64(wxUint64 i)
552 {
553 Write64(&i, 1);
554 }
555
556 void wxDataOutputStream::Write64(wxInt64 i)
557 {
558 Write64(&i, 1);
559 }
560 #endif // wxHAS_INT64
561
562 void wxDataOutputStream::Write32(wxUint32 i)
563 {
564 wxUint32 i32;
565
566 if (m_be_order)
567 i32 = wxUINT32_SWAP_ON_LE(i);
568 else
569 i32 = wxUINT32_SWAP_ON_BE(i);
570 m_output->Write(&i32, 4);
571 }
572
573 void wxDataOutputStream::Write16(wxUint16 i)
574 {
575 wxUint16 i16;
576
577 if (m_be_order)
578 i16 = wxUINT16_SWAP_ON_LE(i);
579 else
580 i16 = wxUINT16_SWAP_ON_BE(i);
581
582 m_output->Write(&i16, 2);
583 }
584
585 void wxDataOutputStream::Write8(wxUint8 i)
586 {
587 m_output->Write(&i, 1);
588 }
589
590 void wxDataOutputStream::WriteString(const wxString& string)
591 {
592 #if wxUSE_UNICODE
593 const wxWX2MBbuf buf = string.mb_str(*m_conv);
594 #else
595 const wxWX2MBbuf buf = string.mb_str();
596 #endif
597 size_t len = strlen(buf);
598 Write32(len);
599 if (len > 0)
600 m_output->Write(buf, len);
601 }
602
603 void wxDataOutputStream::WriteDouble(double d)
604 {
605 #if wxUSE_APPLE_IEEE
606 if ( m_useExtendedPrecision )
607 {
608 char buf[10];
609
610 wxConvertToIeeeExtended(d, (wxInt8 *)buf);
611 m_output->Write(buf, 10);
612 }
613 else
614 #endif // wxUSE_APPLE_IEEE
615 {
616 Float64Data floatData;
617
618 floatData.f = (wxFloat64)d;
619
620 if ( m_be_order == (wxBYTE_ORDER == wxBIG_ENDIAN) )
621 {
622 Write32(floatData.i[0]);
623 Write32(floatData.i[1]);
624 }
625 else
626 {
627 Write32(floatData.i[1]);
628 Write32(floatData.i[0]);
629 }
630 }
631 }
632
633 void wxDataOutputStream::WriteFloat(float f)
634 {
635 #if wxUSE_APPLE_IEEE
636 if ( m_useExtendedPrecision )
637 {
638 WriteDouble((double)f);
639 }
640 else
641 #endif // wxUSE_APPLE_IEEE
642 {
643 Float32Data floatData;
644
645 floatData.f = (wxFloat32)f;
646 Write32(floatData.i);
647 }
648 }
649
650 #if wxHAS_INT64
651 void wxDataOutputStream::Write64(const wxUint64 *buffer, size_t size)
652 {
653 #ifndef wxLongLong_t
654 DoWriteLL(buffer, size, m_output, m_be_order);
655 #else
656 DoWriteI64(buffer, size, m_output, m_be_order);
657 #endif
658 }
659
660 void wxDataOutputStream::Write64(const wxInt64 *buffer, size_t size)
661 {
662 #ifndef wxLongLong_t
663 DoWriteLL(buffer, size, m_output, m_be_order);
664 #else
665 DoWriteI64(buffer, size, m_output, m_be_order);
666 #endif
667 }
668 #endif // wxHAS_INT64
669
670 #if defined(wxLongLong_t) && wxUSE_LONGLONG
671 void wxDataOutputStream::Write64(const wxULongLong *buffer, size_t size)
672 {
673 DoWriteLL(buffer, size, m_output, m_be_order);
674 }
675
676 void wxDataOutputStream::Write64(const wxLongLong *buffer, size_t size)
677 {
678 DoWriteLL(buffer, size, m_output, m_be_order);
679 }
680 #endif // wxLongLong_t
681
682 #if wxUSE_LONGLONG
683 void wxDataOutputStream::WriteLL(const wxULongLong *buffer, size_t size)
684 {
685 DoWriteLL(buffer, size, m_output, m_be_order);
686 }
687
688 void wxDataOutputStream::WriteLL(const wxLongLong *buffer, size_t size)
689 {
690 DoWriteLL(buffer, size, m_output, m_be_order);
691 }
692
693 void wxDataOutputStream::WriteLL(const wxLongLong &ll)
694 {
695 WriteLL(&ll, 1);
696 }
697
698 void wxDataOutputStream::WriteLL(const wxULongLong &ll)
699 {
700 WriteLL(&ll, 1);
701 }
702 #endif // wxUSE_LONGLONG
703
704 void wxDataOutputStream::Write32(const wxUint32 *buffer, size_t size)
705 {
706 if (m_be_order)
707 {
708 for (wxUint32 i=0; i<size ;i++)
709 {
710 wxUint32 i32 = wxUINT32_SWAP_ON_LE(*buffer);
711 buffer++;
712 m_output->Write(&i32, 4);
713 }
714 }
715 else
716 {
717 for (wxUint32 i=0; i<size ;i++)
718 {
719 wxUint32 i32 = wxUINT32_SWAP_ON_BE(*buffer);
720 buffer++;
721 m_output->Write(&i32, 4);
722 }
723 }
724 }
725
726 void wxDataOutputStream::Write16(const wxUint16 *buffer, size_t size)
727 {
728 if (m_be_order)
729 {
730 for (wxUint32 i=0; i<size ;i++)
731 {
732 wxUint16 i16 = wxUINT16_SWAP_ON_LE(*buffer);
733 buffer++;
734 m_output->Write(&i16, 2);
735 }
736 }
737 else
738 {
739 for (wxUint32 i=0; i<size ;i++)
740 {
741 wxUint16 i16 = wxUINT16_SWAP_ON_BE(*buffer);
742 buffer++;
743 m_output->Write(&i16, 2);
744 }
745 }
746 }
747
748 void wxDataOutputStream::Write8(const wxUint8 *buffer, size_t size)
749 {
750 m_output->Write(buffer, size);
751 }
752
753 void wxDataOutputStream::WriteDouble(const double *buffer, size_t size)
754 {
755 for (wxUint32 i=0; i<size; i++)
756 {
757 WriteDouble(*(buffer++));
758 }
759 }
760
761 void wxDataOutputStream::WriteFloat(const float *buffer, size_t size)
762 {
763 for (wxUint32 i=0; i<size; i++)
764 {
765 WriteFloat(*(buffer++));
766 }
767 }
768
769 wxDataOutputStream& wxDataOutputStream::operator<<(const wxString& string)
770 {
771 WriteString(string);
772 return *this;
773 }
774
775 wxDataOutputStream& wxDataOutputStream::operator<<(wxInt8 c)
776 {
777 Write8((wxUint8)c);
778 return *this;
779 }
780
781 wxDataOutputStream& wxDataOutputStream::operator<<(wxInt16 i)
782 {
783 Write16((wxUint16)i);
784 return *this;
785 }
786
787 wxDataOutputStream& wxDataOutputStream::operator<<(wxInt32 i)
788 {
789 Write32((wxUint32)i);
790 return *this;
791 }
792
793 wxDataOutputStream& wxDataOutputStream::operator<<(wxUint8 c)
794 {
795 Write8(c);
796 return *this;
797 }
798
799 wxDataOutputStream& wxDataOutputStream::operator<<(wxUint16 i)
800 {
801 Write16(i);
802 return *this;
803 }
804
805 wxDataOutputStream& wxDataOutputStream::operator<<(wxUint32 i)
806 {
807 Write32(i);
808 return *this;
809 }
810
811 #if wxHAS_INT64
812 wxDataOutputStream& wxDataOutputStream::operator<<(wxUint64 i)
813 {
814 Write64(i);
815 return *this;
816 }
817
818 wxDataOutputStream& wxDataOutputStream::operator<<(wxInt64 i)
819 {
820 Write64(i);
821 return *this;
822 }
823 #endif // wxHAS_INT64
824
825 #if defined(wxLongLong_t) && wxUSE_LONGLONG
826 wxDataOutputStream& wxDataOutputStream::operator<<(const wxULongLong &i)
827 {
828 WriteLL(i);
829 return *this;
830 }
831
832 wxDataOutputStream& wxDataOutputStream::operator<<(const wxLongLong &i)
833 {
834 WriteLL(i);
835 return *this;
836 }
837 #endif // wxLongLong_t
838
839 wxDataOutputStream& wxDataOutputStream::operator<<(double d)
840 {
841 WriteDouble(d);
842 return *this;
843 }
844
845 wxDataOutputStream& wxDataOutputStream::operator<<(float f)
846 {
847 WriteFloat(f);
848 return *this;
849 }
850
851 #endif
852 // wxUSE_STREAMS