blob: d363c7736543bd2e1684a0889cf101f7129277e4 [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
464int
465Stream::PrintfAsRawHex8 (const char *format, ...)
466{
467 va_list args;
468 va_list args_copy;
469 va_start (args, format);
470 va_copy (args, args_copy); // Copy this so we
471
472 int i;
473 char str[1024];
474 int bytes_written = 0;
475 // Try and format our string into a fixed buffer first and see if it fits
476 int length = vsnprintf (str, sizeof(str), format, args);
477 if (length < sizeof(str))
478 {
479 // The formatted string fit into our stack based buffer, so we can just
480 // append that to our packet
481 for (i=0; i<length; ++i)
482 bytes_written += _PutHex8 (str[i], false);
483 }
484 else
485 {
486 // Our stack buffer wasn't big enough to contain the entire formatted
487 // string, so lets let vasprintf create the string for us!
488 char *str_ptr = NULL;
489 length = ::vasprintf (&str_ptr, format, args_copy);
490 if (str_ptr)
491 {
492 for (i=0; i<length; ++i)
493 bytes_written += _PutHex8 (str_ptr[i], false);
494 ::free (str_ptr);
495 }
496 }
497 va_end (args);
498 va_end (args_copy);
499
500 return bytes_written;
501}
502
503int
504Stream::PutNHex8 (size_t n, uint8_t uvalue)
505{
506 int bytes_written = 0;
507 for (int i=0; i<n; ++i)
508 bytes_written += _PutHex8 (uvalue, m_flags.IsSet(eAddPrefix));
509 return bytes_written;
510}
511
512int
513Stream::_PutHex8 (uint8_t uvalue, bool add_prefix)
514{
515 int bytes_written = 0;
516 if (m_flags.IsSet(eBinary))
517 {
518 bytes_written = Write (&uvalue, 1);
519 }
520 else
521 {
522 if (add_prefix)
523 PutCString("0x");
524
525 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' };
526 char nibble_chars[2];
527 nibble_chars[0] = g_hex_to_ascii_hex_char[(uvalue >> 4) & 0xf];
528 nibble_chars[1] = g_hex_to_ascii_hex_char[(uvalue >> 0) & 0xf];
529 bytes_written = Write (nibble_chars, sizeof(nibble_chars));
530 }
531 return bytes_written;
532}
533
534int
535Stream::PutHex8 (uint8_t uvalue)
536{
537 return _PutHex8 (uvalue, m_flags.IsSet(eAddPrefix));
538}
539
540int
541Stream::PutHex16 (uint16_t uvalue, ByteOrder byte_order)
542{
543 if (byte_order == eByteOrderInvalid)
544 byte_order = m_byte_order;
545
546 bool add_prefix = m_flags.IsSet(eAddPrefix);
547 int bytes_written = 0;
548 int byte;
549 if (byte_order == eByteOrderLittle)
550 {
551 for (byte = 0; byte < sizeof(uvalue); ++byte, add_prefix = false)
552 bytes_written += _PutHex8 (uvalue >> (byte * 8), add_prefix);
553 }
554 else
555 {
556 for (byte = sizeof(uvalue)-1; byte >= 0; --byte, add_prefix = false)
557 bytes_written += _PutHex8 (uvalue >> (byte * 8), add_prefix);
558 }
559 return bytes_written;
560}
561
562int
563Stream::PutHex32(uint32_t uvalue, ByteOrder byte_order)
564{
565 if (byte_order == eByteOrderInvalid)
566 byte_order = m_byte_order;
567
568 bool add_prefix = m_flags.IsSet(eAddPrefix);
569 int bytes_written = 0;
570 int byte;
571 if (byte_order == eByteOrderLittle)
572 {
573 for (byte = 0; byte < sizeof(uvalue); ++byte, add_prefix = false)
574 bytes_written += _PutHex8 (uvalue >> (byte * 8), add_prefix);
575 }
576 else
577 {
578 for (byte = sizeof(uvalue)-1; byte >= 0; --byte, add_prefix = false)
579 bytes_written += _PutHex8 (uvalue >> (byte * 8), add_prefix);
580 }
581 return bytes_written;
582}
583
584int
585Stream::PutHex64(uint64_t uvalue, ByteOrder byte_order)
586{
587 if (byte_order == eByteOrderInvalid)
588 byte_order = m_byte_order;
589
590 bool add_prefix = m_flags.IsSet(eAddPrefix);
591 int bytes_written = 0;
592 int byte;
593 if (byte_order == eByteOrderLittle)
594 {
595 for (byte = 0; byte < sizeof(uvalue); ++byte, add_prefix = false)
596 bytes_written += _PutHex8 (uvalue >> (byte * 8), add_prefix);
597 }
598 else
599 {
600 for (byte = sizeof(uvalue)-1; byte >= 0; --byte, add_prefix = false)
601 bytes_written += _PutHex8 (uvalue >> (byte * 8), add_prefix);
602 }
603 return bytes_written;
604}
605
606int
607Stream::PutMaxHex64
608(
609 uint64_t uvalue,
610 size_t byte_size,
611 lldb::ByteOrder byte_order
612)
613{
614 switch (byte_size)
615 {
616 case 1: return PutHex8 (uvalue);
617 case 2: return PutHex16 (uvalue);
618 case 4: return PutHex32 (uvalue);
619 case 8: return PutHex64 (uvalue);
620 }
621 return 0;
622}
623
624int
625Stream::PutPointer (void *ptr)
626{
627 return PutRawBytes (&ptr, sizeof(ptr), eByteOrderHost, eByteOrderHost);
628}
629
630int
631Stream::PutFloat(float f, ByteOrder byte_order)
632{
633 if (byte_order == eByteOrderInvalid)
634 byte_order = m_byte_order;
635
636 return PutRawBytes (&f, sizeof(f), eByteOrderHost, byte_order);
637}
638
639int
640Stream::PutDouble(double d, ByteOrder byte_order)
641{
642 if (byte_order == eByteOrderInvalid)
643 byte_order = m_byte_order;
644
645 return PutRawBytes (&d, sizeof(d), eByteOrderHost, byte_order);
646}
647
648int
649Stream::PutLongDouble(long double ld, ByteOrder byte_order)
650{
651 if (byte_order == eByteOrderInvalid)
652 byte_order = m_byte_order;
653
654 return PutRawBytes (&ld, sizeof(ld), eByteOrderHost, byte_order);
655}
656
657int
658Stream::PutRawBytes (const void *s, size_t src_len, ByteOrder src_byte_order, ByteOrder dst_byte_order)
659{
660 if (src_byte_order == eByteOrderInvalid)
661 src_byte_order = m_byte_order;
662
663 if (dst_byte_order == eByteOrderInvalid)
664 dst_byte_order = m_byte_order;
665
666 int bytes_written = 0;
667 const uint8_t *src = (const uint8_t *)s;
668 int i;
669 bool binary_is_clear = m_flags.IsClear (eBinary);
670 m_flags.Set (eBinary);
671 if (src_byte_order == dst_byte_order)
672 {
673 for (i=0;i<src_len; ++i)
674 bytes_written += _PutHex8 (src[i], false);
675 }
676 else
677 {
678 for (i=src_len-1;i>=0; --i)
679 bytes_written += _PutHex8 (src[i], false);
680 }
681 if (binary_is_clear)
682 m_flags.Clear (eBinary);
683
684 return bytes_written;
685}
686
687int
688Stream::PutBytesAsRawHex8 (const void *s, size_t src_len, ByteOrder src_byte_order, ByteOrder dst_byte_order)
689{
690 if (src_byte_order == eByteOrderInvalid)
691 src_byte_order = m_byte_order;
692
693 if (dst_byte_order == eByteOrderInvalid)
694 dst_byte_order = m_byte_order;
695
696 int bytes_written = 0;
697 const uint8_t *src = (const uint8_t *)s;
698 int i;
699 bool binary_is_set = m_flags.IsSet(eBinary);
700 m_flags.Clear(eBinary);
701 if (src_byte_order == dst_byte_order)
702 {
703 for (i=0;i<src_len; ++i)
704 bytes_written += _PutHex8 (src[i], false);
705 }
706 else
707 {
708 for (i=src_len-1;i>=0; --i)
709 bytes_written += _PutHex8 (src[i], false);
710 }
711 if (binary_is_set)
712 m_flags.Set(eBinary);
713
714 return bytes_written;
715}
716
717int
718Stream::PutCStringAsRawHex8 (const char *s)
719{
720 int bytes_written = 0;
721 bool binary_is_set = m_flags.IsSet(eBinary);
722 m_flags.Clear(eBinary);
723 do
724 {
725 bytes_written += _PutHex8 (*s, false);
726 ++s;
727 } while (*s);
728 if (binary_is_set)
729 m_flags.Set(eBinary);
730 return bytes_written;
731}
732
733void
734Stream::UnitTest(Stream *s)
735{
736 s->PutHex8(0x12);
737
738 s->PutChar(' ');
739 s->PutHex16(0x3456, eByteOrderHost);
740 s->PutChar(' ');
741 s->PutHex16(0x3456, eByteOrderBig);
742 s->PutChar(' ');
743 s->PutHex16(0x3456, eByteOrderLittle);
744
745 s->PutChar(' ');
746 s->PutHex32(0x789abcde, eByteOrderHost);
747 s->PutChar(' ');
748 s->PutHex32(0x789abcde, eByteOrderBig);
749 s->PutChar(' ');
750 s->PutHex32(0x789abcde, eByteOrderLittle);
751
752 s->PutChar(' ');
753 s->PutHex64(0x1122334455667788ull, eByteOrderHost);
754 s->PutChar(' ');
755 s->PutHex64(0x1122334455667788ull, eByteOrderBig);
756 s->PutChar(' ');
757 s->PutHex64(0x1122334455667788ull, eByteOrderLittle);
758
759 const char *hola = "Hello World!!!";
760 s->PutChar(' ');
761 s->PutCString (hola);
762
763 s->PutChar(' ');
764 s->Write (hola, 5);
765
766 s->PutChar(' ');
767 s->PutCStringAsRawHex8 (hola);
768
769 s->PutChar(' ');
770 s->PutCStringAsRawHex8 ("01234");
771
772 s->PutChar(' ');
773 s->Printf ("pid=%i", 12733);
774
775 s->PutChar(' ');
776 s->PrintfAsRawHex8 ("pid=%i", 12733);
777 s->PutChar('\n');
778}
779