blob: 0d3c8e0aced0a29e385c09f54aadd648b73d1baf [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- Stream.cpp ----------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Core/Stream.h"
Eli Friedman88966972010-06-09 08:50:27 +000011#include <stdio.h>
12#include <string.h>
13#include <stdlib.h>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000014
15using namespace lldb;
16using namespace lldb_private;
17
18Stream::Stream (uint32_t flags, uint32_t addr_size, ByteOrder byte_order) :
19 m_flags (flags),
20 m_addr_size (addr_size),
21 m_byte_order (byte_order),
22 m_indent_level(0)
23{
24}
25
26Stream::Stream () :
27 m_flags (0),
28 m_addr_size (4),
29 m_byte_order (eByteOrderHost),
30 m_indent_level(0)
31{
32}
33
34//------------------------------------------------------------------
35// Destructor
36//------------------------------------------------------------------
37Stream::~Stream ()
38{
39}
40
41ByteOrder
42Stream::SetByteOrder (ByteOrder byte_order)
43{
44 ByteOrder old_byte_order = m_byte_order;
45 m_byte_order = byte_order;
46 return old_byte_order;
47}
48
49//------------------------------------------------------------------
50// Put an offset "uval" out to the stream using the printf format
51// in "format".
52//------------------------------------------------------------------
53void
54Stream::Offset (uint32_t uval, const char *format)
55{
56 Printf (format, uval);
57}
58
59//------------------------------------------------------------------
60// Put an SLEB128 "uval" out to the stream using the printf format
61// in "format".
62//------------------------------------------------------------------
63int
64Stream::PutSLEB128 (int64_t sval)
65{
66 int bytes_written = 0;
67 if (m_flags.IsSet(eBinary))
68 {
69 bool more = true;
70 bool negative = (sval < 0);
71 while (more)
72 {
73 uint8_t byte = sval & 0x7fu;
74 sval >>= 7;
75 assert((!negative && sval >= 0) || (negative && sval < 0));
76 /* sign bit of byte is 2nd high order bit (0x40) */
77 if ((sval == 0 && !(byte & 0x40)) ||
78 (sval == -1 && (byte & 0x40)) )
79 more = false;
80 else
81 // more bytes to come
82 byte |= 0x80u;
83 bytes_written += Write(&byte, 1);
84 }
85 }
86 else
87 {
88 bytes_written = Printf ("0x%lli", sval);
89 }
90
91 return bytes_written;
92
93}
94
95//------------------------------------------------------------------
96// Put an ULEB128 "uval" out to the stream using the printf format
97// in "format".
98//------------------------------------------------------------------
99int
100Stream::PutULEB128 (uint64_t uval)
101{
102 int bytes_written = 0;
103 if (m_flags.IsSet(eBinary))
104 {
105 do
106 {
107
108 uint8_t byte = uval & 0x7fu;
109 uval >>= 7;
110 if (uval != 0)
111 {
112 // more bytes to come
113 byte |= 0x80u;
114 }
115 bytes_written += Write(&byte, 1);
116 } while (uval != 0);
117 }
118 else
119 {
120 bytes_written = Printf ("0x%llx", uval);
121 }
122 return bytes_written;
123}
124
125//------------------------------------------------------------------
126// Print a raw NULL terminated C string to the stream using the
127// printf format in "format".
128//------------------------------------------------------------------
129int
130Stream::PutCString (const char *cstr)
131{
132 int cstr_len = strlen(cstr);
133 // when in binary mode, emit the NULL terminator
134 if (m_flags.IsSet(eBinary))
135 ++cstr_len;
136 return Write (cstr, cstr_len);
137}
138
139//------------------------------------------------------------------
140// Print a double quoted NULL terminated C string to the stream
141// using the printf format in "format".
142//------------------------------------------------------------------
143void
144Stream::QuotedCString (const char *cstr, const char *format)
145{
146 Printf (format, cstr);
147}
148
149//------------------------------------------------------------------
150// Put an address "addr" out to the stream with optional prefix
151// and suffix strings.
152//------------------------------------------------------------------
153void
154Stream::Address (uint64_t addr, int addr_size, const char *prefix, const char *suffix)
155{
156 if (prefix == NULL)
157 prefix = "";
158 if (suffix == NULL)
159 suffix = "";
160// int addr_width = m_addr_size << 1;
161// Printf ("%s0x%0*llx%s", prefix, addr_width, addr, suffix);
162 Printf ("%s0x%0*llx%s", prefix, addr_size * 2, (uint64_t)addr, suffix);
163}
164
165//------------------------------------------------------------------
166// Put an address range out to the stream with optional prefix
167// and suffix strings.
168//------------------------------------------------------------------
169void
170Stream::AddressRange(uint64_t lo_addr, uint64_t hi_addr, int addr_size, const char *prefix, const char *suffix)
171{
172 if (prefix != NULL)
173 PutCString (prefix);
174 Address (lo_addr, addr_size, "[");
175 Address (hi_addr, addr_size, "-", ")");
176}
177
178
179int
180Stream::PutChar (char ch)
181{
182 return Write (&ch, 1);
183}
184
185
186//------------------------------------------------------------------
187// Print some formatted output to the stream.
188//------------------------------------------------------------------
189int
190Stream::Printf (const char *format, ...)
191{
192 va_list args;
193 va_start (args, format);
194 size_t result = PrintfVarArg(format, args);
195 va_end (args);
196 return result;
197}
198
199//------------------------------------------------------------------
200// Print some formatted output to the stream.
201//------------------------------------------------------------------
202int
203Stream::PrintfVarArg (const char *format, va_list args)
204{
205 char str[1024];
206 va_list args_copy;
207
208 va_copy (args_copy, args);
209
210 int bytes_written = 0;
211 // Try and format our string into a fixed buffer first and see if it fits
212 int length = vsnprintf (str, sizeof(str), format, args);
213 if (length < sizeof(str))
214 {
215 va_end (args);
216 // Include the NULL termination byte for binary output
217 if (m_flags.IsSet(eBinary))
218 length += 1;
219 // The formatted string fit into our stack based buffer, so we can just
220 // append that to our packet
221 bytes_written = Write (str, length);
222 }
223 else
224 {
225 // Our stack buffer wasn't big enough to contain the entire formatted
226 // string, so lets let vasprintf create the string for us!
227 char *str_ptr = NULL;
228 length = ::vasprintf (&str_ptr, format, args_copy);
229 if (str_ptr)
230 {
231 // Include the NULL termination byte for binary output
232 if (m_flags.IsSet(eBinary))
233 length += 1;
234 bytes_written = Write (str_ptr, length);
235 ::free (str_ptr);
236 }
237 }
238 va_end (args_copy);
239 return bytes_written;
240}
241
242//------------------------------------------------------------------
243// Print and End of Line character to the stream
244//------------------------------------------------------------------
245int
246Stream::EOL()
247{
248 return PutChar ('\n');
249}
250
251//------------------------------------------------------------------
252// Indent the current line using the current indentation level and
253// print an optional string following the idenatation spaces.
254//------------------------------------------------------------------
255int
256Stream::Indent(const char *s)
257{
258 return Printf ("%*.*s%s", m_indent_level, m_indent_level, "", s ? s : "");
259}
260
261//------------------------------------------------------------------
262// Stream a character "ch" out to this stream.
263//------------------------------------------------------------------
264Stream&
265Stream::operator<< (char ch)
266{
267 PutChar (ch);
268 return *this;
269}
270
271//------------------------------------------------------------------
272// Stream the NULL terminated C string out to this stream.
273//------------------------------------------------------------------
274Stream&
275Stream::operator<< (const char *s)
276{
277 Printf ("%s", s);
278 return *this;
279}
280
281//------------------------------------------------------------------
282// Stream the pointer value out to this stream.
283//------------------------------------------------------------------
284Stream&
285Stream::operator<< (void *p)
286{
287 Printf ("0x%.*tx", (int)sizeof(void*) * 2, (ptrdiff_t)p);
288 return *this;
289}
290
291//------------------------------------------------------------------
292// Stream a uint8_t "uval" out to this stream.
293//------------------------------------------------------------------
294Stream&
295Stream::operator<< (uint8_t uval)
296{
297 PutHex8(uval);
298 return *this;
299}
300
301//------------------------------------------------------------------
302// Stream a uint16_t "uval" out to this stream.
303//------------------------------------------------------------------
304Stream&
305Stream::operator<< (uint16_t uval)
306{
307 PutHex16(uval, m_byte_order);
308 return *this;
309}
310
311//------------------------------------------------------------------
312// Stream a uint32_t "uval" out to this stream.
313//------------------------------------------------------------------
314Stream&
315Stream::operator<< (uint32_t uval)
316{
317 PutHex32(uval, m_byte_order);
318 return *this;
319}
320
321//------------------------------------------------------------------
322// Stream a uint64_t "uval" out to this stream.
323//------------------------------------------------------------------
324Stream&
325Stream::operator<< (uint64_t uval)
326{
327 PutHex64(uval, m_byte_order);
328 return *this;
329}
330
331//------------------------------------------------------------------
332// Stream a int8_t "sval" out to this stream.
333//------------------------------------------------------------------
334Stream&
335Stream::operator<< (int8_t sval)
336{
337 Printf ("%i", (int)sval);
338 return *this;
339}
340
341//------------------------------------------------------------------
342// Stream a int16_t "sval" out to this stream.
343//------------------------------------------------------------------
344Stream&
345Stream::operator<< (int16_t sval)
346{
347 Printf ("%i", (int)sval);
348 return *this;
349}
350
351//------------------------------------------------------------------
352// Stream a int32_t "sval" out to this stream.
353//------------------------------------------------------------------
354Stream&
355Stream::operator<< (int32_t sval)
356{
357 Printf ("%i", (int)sval);
358 return *this;
359}
360
361//------------------------------------------------------------------
362// Stream a int64_t "sval" out to this stream.
363//------------------------------------------------------------------
364Stream&
365Stream::operator<< (int64_t sval)
366{
367 Printf ("%lli", sval);
368 return *this;
369}
370
371//------------------------------------------------------------------
372// Get the current indentation level
373//------------------------------------------------------------------
374int
375Stream::GetIndentLevel() const
376{
377 return m_indent_level;
378}
379
380//------------------------------------------------------------------
381// Set the current indentation level
382//------------------------------------------------------------------
383void
384Stream::SetIndentLevel(int indent_level)
385{
386 m_indent_level = indent_level;
387}
388
389//------------------------------------------------------------------
390// Increment the current indentation level
391//------------------------------------------------------------------
392void
393Stream::IndentMore(int amount)
394{
395 m_indent_level += amount;
396}
397
398//------------------------------------------------------------------
399// Decrement the current indentation level
400//------------------------------------------------------------------
401void
402Stream::IndentLess (int amount)
403{
404 if (m_indent_level >= amount)
405 m_indent_level -= amount;
406 else
407 m_indent_level = 0;
408}
409
410//------------------------------------------------------------------
411// Get the address size in bytes
412//------------------------------------------------------------------
413uint8_t
414Stream::GetAddressByteSize() const
415{
416 return m_addr_size;
417}
418
419//------------------------------------------------------------------
420// Set the address size in bytes
421//------------------------------------------------------------------
422void
423Stream::SetAddressByteSize(uint8_t addr_size)
424{
425 m_addr_size = addr_size;
426}
427
428//------------------------------------------------------------------
429// Returns true if the verbose flag bit is set in this stream.
430//------------------------------------------------------------------
431bool
432Stream::GetVerbose() const
433{
434 return m_flags.IsSet(eVerbose);
435}
436
437//------------------------------------------------------------------
438// Returns true if the debug flag bit is set in this stream.
439//------------------------------------------------------------------
440bool
441Stream::GetDebug() const
442{
443 return m_flags.IsSet(eDebug);
444}
445
446//------------------------------------------------------------------
447// The flags get accessor
448//------------------------------------------------------------------
449Flags&
450Stream::GetFlags()
451{
452 return m_flags;
453}
454
455//------------------------------------------------------------------
456// The flags const get accessor
457//------------------------------------------------------------------
458const Flags&
459Stream::GetFlags() const
460{
461 return m_flags;
462}
463
Sean Callanan609f8c52010-07-02 02:43:42 +0000464//------------------------------------------------------------------
465// The byte order get accessor
466//------------------------------------------------------------------
467
468lldb::ByteOrder
469Stream::GetByteOrder() const
470{
471 return m_byte_order;
472}
473
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000474int
475Stream::PrintfAsRawHex8 (const char *format, ...)
476{
477 va_list args;
478 va_list args_copy;
479 va_start (args, format);
480 va_copy (args, args_copy); // Copy this so we
481
482 int i;
483 char str[1024];
484 int bytes_written = 0;
485 // Try and format our string into a fixed buffer first and see if it fits
486 int length = vsnprintf (str, sizeof(str), format, args);
487 if (length < sizeof(str))
488 {
489 // The formatted string fit into our stack based buffer, so we can just
490 // append that to our packet
491 for (i=0; i<length; ++i)
492 bytes_written += _PutHex8 (str[i], false);
493 }
494 else
495 {
496 // Our stack buffer wasn't big enough to contain the entire formatted
497 // string, so lets let vasprintf create the string for us!
498 char *str_ptr = NULL;
499 length = ::vasprintf (&str_ptr, format, args_copy);
500 if (str_ptr)
501 {
502 for (i=0; i<length; ++i)
503 bytes_written += _PutHex8 (str_ptr[i], false);
504 ::free (str_ptr);
505 }
506 }
507 va_end (args);
508 va_end (args_copy);
509
510 return bytes_written;
511}
512
513int
514Stream::PutNHex8 (size_t n, uint8_t uvalue)
515{
516 int bytes_written = 0;
517 for (int i=0; i<n; ++i)
518 bytes_written += _PutHex8 (uvalue, m_flags.IsSet(eAddPrefix));
519 return bytes_written;
520}
521
522int
523Stream::_PutHex8 (uint8_t uvalue, bool add_prefix)
524{
525 int bytes_written = 0;
526 if (m_flags.IsSet(eBinary))
527 {
528 bytes_written = Write (&uvalue, 1);
529 }
530 else
531 {
532 if (add_prefix)
533 PutCString("0x");
534
535 static char g_hex_to_ascii_hex_char[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
536 char nibble_chars[2];
537 nibble_chars[0] = g_hex_to_ascii_hex_char[(uvalue >> 4) & 0xf];
538 nibble_chars[1] = g_hex_to_ascii_hex_char[(uvalue >> 0) & 0xf];
539 bytes_written = Write (nibble_chars, sizeof(nibble_chars));
540 }
541 return bytes_written;
542}
543
544int
545Stream::PutHex8 (uint8_t uvalue)
546{
547 return _PutHex8 (uvalue, m_flags.IsSet(eAddPrefix));
548}
549
550int
551Stream::PutHex16 (uint16_t uvalue, ByteOrder byte_order)
552{
553 if (byte_order == eByteOrderInvalid)
554 byte_order = m_byte_order;
555
556 bool add_prefix = m_flags.IsSet(eAddPrefix);
557 int bytes_written = 0;
558 int byte;
559 if (byte_order == eByteOrderLittle)
560 {
561 for (byte = 0; byte < sizeof(uvalue); ++byte, add_prefix = false)
562 bytes_written += _PutHex8 (uvalue >> (byte * 8), add_prefix);
563 }
564 else
565 {
566 for (byte = sizeof(uvalue)-1; byte >= 0; --byte, add_prefix = false)
567 bytes_written += _PutHex8 (uvalue >> (byte * 8), add_prefix);
568 }
569 return bytes_written;
570}
571
572int
573Stream::PutHex32(uint32_t uvalue, ByteOrder byte_order)
574{
575 if (byte_order == eByteOrderInvalid)
576 byte_order = m_byte_order;
577
578 bool add_prefix = m_flags.IsSet(eAddPrefix);
579 int bytes_written = 0;
580 int byte;
581 if (byte_order == eByteOrderLittle)
582 {
583 for (byte = 0; byte < sizeof(uvalue); ++byte, add_prefix = false)
584 bytes_written += _PutHex8 (uvalue >> (byte * 8), add_prefix);
585 }
586 else
587 {
588 for (byte = sizeof(uvalue)-1; byte >= 0; --byte, add_prefix = false)
589 bytes_written += _PutHex8 (uvalue >> (byte * 8), add_prefix);
590 }
591 return bytes_written;
592}
593
594int
595Stream::PutHex64(uint64_t uvalue, ByteOrder byte_order)
596{
597 if (byte_order == eByteOrderInvalid)
598 byte_order = m_byte_order;
599
600 bool add_prefix = m_flags.IsSet(eAddPrefix);
601 int bytes_written = 0;
602 int byte;
603 if (byte_order == eByteOrderLittle)
604 {
605 for (byte = 0; byte < sizeof(uvalue); ++byte, add_prefix = false)
606 bytes_written += _PutHex8 (uvalue >> (byte * 8), add_prefix);
607 }
608 else
609 {
610 for (byte = sizeof(uvalue)-1; byte >= 0; --byte, add_prefix = false)
611 bytes_written += _PutHex8 (uvalue >> (byte * 8), add_prefix);
612 }
613 return bytes_written;
614}
615
616int
617Stream::PutMaxHex64
618(
619 uint64_t uvalue,
620 size_t byte_size,
621 lldb::ByteOrder byte_order
622)
623{
624 switch (byte_size)
625 {
626 case 1: return PutHex8 (uvalue);
627 case 2: return PutHex16 (uvalue);
628 case 4: return PutHex32 (uvalue);
629 case 8: return PutHex64 (uvalue);
630 }
631 return 0;
632}
633
634int
635Stream::PutPointer (void *ptr)
636{
637 return PutRawBytes (&ptr, sizeof(ptr), eByteOrderHost, eByteOrderHost);
638}
639
640int
641Stream::PutFloat(float f, ByteOrder byte_order)
642{
643 if (byte_order == eByteOrderInvalid)
644 byte_order = m_byte_order;
645
646 return PutRawBytes (&f, sizeof(f), eByteOrderHost, byte_order);
647}
648
649int
650Stream::PutDouble(double d, ByteOrder byte_order)
651{
652 if (byte_order == eByteOrderInvalid)
653 byte_order = m_byte_order;
654
655 return PutRawBytes (&d, sizeof(d), eByteOrderHost, byte_order);
656}
657
658int
659Stream::PutLongDouble(long double ld, ByteOrder byte_order)
660{
661 if (byte_order == eByteOrderInvalid)
662 byte_order = m_byte_order;
663
664 return PutRawBytes (&ld, sizeof(ld), eByteOrderHost, byte_order);
665}
666
667int
668Stream::PutRawBytes (const void *s, size_t src_len, ByteOrder src_byte_order, ByteOrder dst_byte_order)
669{
670 if (src_byte_order == eByteOrderInvalid)
671 src_byte_order = m_byte_order;
672
673 if (dst_byte_order == eByteOrderInvalid)
674 dst_byte_order = m_byte_order;
675
676 int bytes_written = 0;
677 const uint8_t *src = (const uint8_t *)s;
678 int i;
679 bool binary_is_clear = m_flags.IsClear (eBinary);
680 m_flags.Set (eBinary);
681 if (src_byte_order == dst_byte_order)
682 {
683 for (i=0;i<src_len; ++i)
684 bytes_written += _PutHex8 (src[i], false);
685 }
686 else
687 {
688 for (i=src_len-1;i>=0; --i)
689 bytes_written += _PutHex8 (src[i], false);
690 }
691 if (binary_is_clear)
692 m_flags.Clear (eBinary);
693
694 return bytes_written;
695}
696
697int
698Stream::PutBytesAsRawHex8 (const void *s, size_t src_len, ByteOrder src_byte_order, ByteOrder dst_byte_order)
699{
700 if (src_byte_order == eByteOrderInvalid)
701 src_byte_order = m_byte_order;
702
703 if (dst_byte_order == eByteOrderInvalid)
704 dst_byte_order = m_byte_order;
705
706 int bytes_written = 0;
707 const uint8_t *src = (const uint8_t *)s;
708 int i;
709 bool binary_is_set = m_flags.IsSet(eBinary);
710 m_flags.Clear(eBinary);
711 if (src_byte_order == dst_byte_order)
712 {
713 for (i=0;i<src_len; ++i)
714 bytes_written += _PutHex8 (src[i], false);
715 }
716 else
717 {
718 for (i=src_len-1;i>=0; --i)
719 bytes_written += _PutHex8 (src[i], false);
720 }
721 if (binary_is_set)
722 m_flags.Set(eBinary);
723
724 return bytes_written;
725}
726
727int
728Stream::PutCStringAsRawHex8 (const char *s)
729{
730 int bytes_written = 0;
731 bool binary_is_set = m_flags.IsSet(eBinary);
732 m_flags.Clear(eBinary);
733 do
734 {
735 bytes_written += _PutHex8 (*s, false);
736 ++s;
737 } while (*s);
738 if (binary_is_set)
739 m_flags.Set(eBinary);
740 return bytes_written;
741}
742
743void
744Stream::UnitTest(Stream *s)
745{
746 s->PutHex8(0x12);
747
748 s->PutChar(' ');
749 s->PutHex16(0x3456, eByteOrderHost);
750 s->PutChar(' ');
751 s->PutHex16(0x3456, eByteOrderBig);
752 s->PutChar(' ');
753 s->PutHex16(0x3456, eByteOrderLittle);
754
755 s->PutChar(' ');
756 s->PutHex32(0x789abcde, eByteOrderHost);
757 s->PutChar(' ');
758 s->PutHex32(0x789abcde, eByteOrderBig);
759 s->PutChar(' ');
760 s->PutHex32(0x789abcde, eByteOrderLittle);
761
762 s->PutChar(' ');
763 s->PutHex64(0x1122334455667788ull, eByteOrderHost);
764 s->PutChar(' ');
765 s->PutHex64(0x1122334455667788ull, eByteOrderBig);
766 s->PutChar(' ');
767 s->PutHex64(0x1122334455667788ull, eByteOrderLittle);
768
769 const char *hola = "Hello World!!!";
770 s->PutChar(' ');
771 s->PutCString (hola);
772
773 s->PutChar(' ');
774 s->Write (hola, 5);
775
776 s->PutChar(' ');
777 s->PutCStringAsRawHex8 (hola);
778
779 s->PutChar(' ');
780 s->PutCStringAsRawHex8 ("01234");
781
782 s->PutChar(' ');
783 s->Printf ("pid=%i", 12733);
784
785 s->PutChar(' ');
786 s->PrintfAsRawHex8 ("pid=%i", 12733);
787 s->PutChar('\n');
788}
789