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