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