1 //===-- Stream.cpp ----------------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "lldb/Core/Stream.h"
11 #include "lldb/Host/Endian.h"
20 using namespace lldb_private;
22 Stream::Stream (uint32_t flags, uint32_t addr_size, ByteOrder byte_order) :
24 m_addr_size (addr_size),
25 m_byte_order (byte_order),
33 m_byte_order (lldb::endian::InlHostByteOrder()),
38 //------------------------------------------------------------------
40 //------------------------------------------------------------------
46 Stream::SetByteOrder (ByteOrder byte_order)
48 ByteOrder old_byte_order = m_byte_order;
49 m_byte_order = byte_order;
50 return old_byte_order;
53 //------------------------------------------------------------------
54 // Put an offset "uval" out to the stream using the printf format
56 //------------------------------------------------------------------
58 Stream::Offset (uint32_t uval, const char *format)
60 Printf (format, uval);
63 //------------------------------------------------------------------
64 // Put an SLEB128 "uval" out to the stream using the printf format
66 //------------------------------------------------------------------
68 Stream::PutSLEB128 (int64_t sval)
70 size_t bytes_written = 0;
71 if (m_flags.Test(eBinary))
76 uint8_t byte = sval & 0x7fu;
78 /* sign bit of byte is 2nd high order bit (0x40) */
79 if ((sval == 0 && !(byte & 0x40)) ||
80 (sval == -1 && (byte & 0x40)) )
85 bytes_written += Write(&byte, 1);
90 bytes_written = Printf ("0x%" PRIi64, sval);
97 //------------------------------------------------------------------
98 // Put an ULEB128 "uval" out to the stream using the printf format
100 //------------------------------------------------------------------
102 Stream::PutULEB128 (uint64_t uval)
104 size_t bytes_written = 0;
105 if (m_flags.Test(eBinary))
110 uint8_t byte = uval & 0x7fu;
114 // more bytes to come
117 bytes_written += Write(&byte, 1);
122 bytes_written = Printf ("0x%" PRIx64, uval);
124 return bytes_written;
127 //------------------------------------------------------------------
128 // Print a raw NULL terminated C string to the stream.
129 //------------------------------------------------------------------
131 Stream::PutCString (const char *cstr)
133 size_t cstr_len = strlen(cstr);
134 // when in binary mode, emit the NULL terminator
135 if (m_flags.Test(eBinary))
137 return Write (cstr, cstr_len);
140 //------------------------------------------------------------------
141 // Print a double quoted NULL terminated C string to the stream
142 // using the printf format in "format".
143 //------------------------------------------------------------------
145 Stream::QuotedCString (const char *cstr, const char *format)
147 Printf (format, cstr);
150 //------------------------------------------------------------------
151 // Put an address "addr" out to the stream with optional prefix
152 // and suffix strings.
153 //------------------------------------------------------------------
155 Stream::Address (uint64_t addr, uint32_t addr_size, const char *prefix, const char *suffix)
161 // int addr_width = m_addr_size << 1;
162 // Printf ("%s0x%0*" PRIx64 "%s", prefix, addr_width, addr, suffix);
163 Printf ("%s0x%0*" PRIx64 "%s", prefix, addr_size * 2, (uint64_t)addr, suffix);
166 //------------------------------------------------------------------
167 // Put an address range out to the stream with optional prefix
168 // and suffix strings.
169 //------------------------------------------------------------------
171 Stream::AddressRange(uint64_t lo_addr, uint64_t hi_addr, uint32_t addr_size, const char *prefix, const char *suffix)
173 if (prefix && prefix[0])
175 Address (lo_addr, addr_size, "[");
176 Address (hi_addr, addr_size, "-", ")");
177 if (suffix && suffix[0])
183 Stream::PutChar (char ch)
185 return Write (&ch, 1);
189 //------------------------------------------------------------------
190 // Print some formatted output to the stream.
191 //------------------------------------------------------------------
193 Stream::Printf (const char *format, ...)
196 va_start (args, format);
197 size_t result = PrintfVarArg(format, args);
202 //------------------------------------------------------------------
203 // Print some formatted output to the stream.
204 //------------------------------------------------------------------
206 Stream::PrintfVarArg (const char *format, va_list args)
211 va_copy (args_copy, args);
213 size_t bytes_written = 0;
214 // Try and format our string into a fixed buffer first and see if it fits
215 size_t length = ::vsnprintf (str, sizeof(str), format, args);
216 if (length < sizeof(str))
218 // Include the NULL termination byte for binary output
219 if (m_flags.Test(eBinary))
221 // The formatted string fit into our stack based buffer, so we can just
222 // append that to our packet
223 bytes_written = Write (str, length);
227 // Our stack buffer wasn't big enough to contain the entire formatted
228 // string, so lets let vasprintf create the string for us!
229 char *str_ptr = NULL;
230 length = ::vasprintf (&str_ptr, format, args_copy);
233 // Include the NULL termination byte for binary output
234 if (m_flags.Test(eBinary))
236 bytes_written = Write (str_ptr, length);
241 return bytes_written;
244 //------------------------------------------------------------------
245 // Print and End of Line character to the stream
246 //------------------------------------------------------------------
250 return PutChar ('\n');
253 //------------------------------------------------------------------
254 // Indent the current line using the current indentation level and
255 // print an optional string following the idenatation spaces.
256 //------------------------------------------------------------------
258 Stream::Indent(const char *s)
260 return Printf ("%*.*s%s", m_indent_level, m_indent_level, "", s ? s : "");
263 //------------------------------------------------------------------
264 // Stream a character "ch" out to this stream.
265 //------------------------------------------------------------------
267 Stream::operator<< (char ch)
273 //------------------------------------------------------------------
274 // Stream the NULL terminated C string out to this stream.
275 //------------------------------------------------------------------
277 Stream::operator<< (const char *s)
283 //------------------------------------------------------------------
284 // Stream the pointer value out to this stream.
285 //------------------------------------------------------------------
287 Stream::operator<< (void *p)
289 Printf ("0x%.*tx", (int)sizeof(void*) * 2, (ptrdiff_t)p);
293 //------------------------------------------------------------------
294 // Stream a uint8_t "uval" out to this stream.
295 //------------------------------------------------------------------
297 Stream::operator<< (uint8_t uval)
303 //------------------------------------------------------------------
304 // Stream a uint16_t "uval" out to this stream.
305 //------------------------------------------------------------------
307 Stream::operator<< (uint16_t uval)
309 PutHex16(uval, m_byte_order);
313 //------------------------------------------------------------------
314 // Stream a uint32_t "uval" out to this stream.
315 //------------------------------------------------------------------
317 Stream::operator<< (uint32_t uval)
319 PutHex32(uval, m_byte_order);
323 //------------------------------------------------------------------
324 // Stream a uint64_t "uval" out to this stream.
325 //------------------------------------------------------------------
327 Stream::operator<< (uint64_t uval)
329 PutHex64(uval, m_byte_order);
333 //------------------------------------------------------------------
334 // Stream a int8_t "sval" out to this stream.
335 //------------------------------------------------------------------
337 Stream::operator<< (int8_t sval)
339 Printf ("%i", (int)sval);
343 //------------------------------------------------------------------
344 // Stream a int16_t "sval" out to this stream.
345 //------------------------------------------------------------------
347 Stream::operator<< (int16_t sval)
349 Printf ("%i", (int)sval);
353 //------------------------------------------------------------------
354 // Stream a int32_t "sval" out to this stream.
355 //------------------------------------------------------------------
357 Stream::operator<< (int32_t sval)
359 Printf ("%i", (int)sval);
363 //------------------------------------------------------------------
364 // Stream a int64_t "sval" out to this stream.
365 //------------------------------------------------------------------
367 Stream::operator<< (int64_t sval)
369 Printf ("%" PRIi64, sval);
373 //------------------------------------------------------------------
374 // Get the current indentation level
375 //------------------------------------------------------------------
377 Stream::GetIndentLevel() const
379 return m_indent_level;
382 //------------------------------------------------------------------
383 // Set the current indentation level
384 //------------------------------------------------------------------
386 Stream::SetIndentLevel(int indent_level)
388 m_indent_level = indent_level;
391 //------------------------------------------------------------------
392 // Increment the current indentation level
393 //------------------------------------------------------------------
395 Stream::IndentMore(int amount)
397 m_indent_level += amount;
400 //------------------------------------------------------------------
401 // Decrement the current indentation level
402 //------------------------------------------------------------------
404 Stream::IndentLess (int amount)
406 if (m_indent_level >= amount)
407 m_indent_level -= amount;
412 //------------------------------------------------------------------
413 // Get the address size in bytes
414 //------------------------------------------------------------------
416 Stream::GetAddressByteSize() const
421 //------------------------------------------------------------------
422 // Set the address size in bytes
423 //------------------------------------------------------------------
425 Stream::SetAddressByteSize(uint32_t addr_size)
427 m_addr_size = addr_size;
430 //------------------------------------------------------------------
431 // Returns true if the verbose flag bit is set in this stream.
432 //------------------------------------------------------------------
434 Stream::GetVerbose() const
436 return m_flags.Test(eVerbose);
439 //------------------------------------------------------------------
440 // Returns true if the debug flag bit is set in this stream.
441 //------------------------------------------------------------------
443 Stream::GetDebug() const
445 return m_flags.Test(eDebug);
448 //------------------------------------------------------------------
449 // The flags get accessor
450 //------------------------------------------------------------------
457 //------------------------------------------------------------------
458 // The flags const get accessor
459 //------------------------------------------------------------------
461 Stream::GetFlags() const
466 //------------------------------------------------------------------
467 // The byte order get accessor
468 //------------------------------------------------------------------
471 Stream::GetByteOrder() const
477 Stream::PrintfAsRawHex8 (const char *format, ...)
481 va_start (args, format);
482 va_copy (args, args_copy); // Copy this so we
485 size_t bytes_written = 0;
486 // Try and format our string into a fixed buffer first and see if it fits
487 size_t length = ::vsnprintf (str, sizeof(str), format, args);
488 if (length < sizeof(str))
490 // The formatted string fit into our stack based buffer, so we can just
491 // append that to our packet
492 for (size_t i=0; i<length; ++i)
493 bytes_written += _PutHex8 (str[i], false);
497 // Our stack buffer wasn't big enough to contain the entire formatted
498 // string, so lets let vasprintf create the string for us!
499 char *str_ptr = NULL;
500 length = ::vasprintf (&str_ptr, format, args_copy);
503 for (size_t i=0; i<length; ++i)
504 bytes_written += _PutHex8 (str_ptr[i], false);
511 return bytes_written;
515 Stream::PutNHex8 (size_t n, uint8_t uvalue)
517 size_t bytes_written = 0;
518 for (size_t i=0; i<n; ++i)
519 bytes_written += _PutHex8 (uvalue, m_flags.Test(eAddPrefix));
520 return bytes_written;
524 Stream::_PutHex8 (uint8_t uvalue, bool add_prefix)
526 size_t bytes_written = 0;
527 if (m_flags.Test(eBinary))
529 bytes_written = Write (&uvalue, 1);
536 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' };
537 char nibble_chars[2];
538 nibble_chars[0] = g_hex_to_ascii_hex_char[(uvalue >> 4) & 0xf];
539 nibble_chars[1] = g_hex_to_ascii_hex_char[(uvalue >> 0) & 0xf];
540 bytes_written = Write (nibble_chars, sizeof(nibble_chars));
542 return bytes_written;
546 Stream::PutHex8 (uint8_t uvalue)
548 return _PutHex8 (uvalue, m_flags.Test(eAddPrefix));
552 Stream::PutHex16 (uint16_t uvalue, ByteOrder byte_order)
554 if (byte_order == eByteOrderInvalid)
555 byte_order = m_byte_order;
557 bool add_prefix = m_flags.Test(eAddPrefix);
558 size_t bytes_written = 0;
559 if (byte_order == eByteOrderLittle)
561 for (size_t byte = 0; byte < sizeof(uvalue); ++byte, add_prefix = false)
562 bytes_written += _PutHex8 ((uint8_t)(uvalue >> (byte * 8)), add_prefix);
566 for (size_t byte = sizeof(uvalue)-1; byte < sizeof(uvalue); --byte, add_prefix = false)
567 bytes_written += _PutHex8 ((uint8_t)(uvalue >> (byte * 8)), add_prefix);
569 return bytes_written;
573 Stream::PutHex32(uint32_t uvalue, ByteOrder byte_order)
575 if (byte_order == eByteOrderInvalid)
576 byte_order = m_byte_order;
578 bool add_prefix = m_flags.Test(eAddPrefix);
579 size_t bytes_written = 0;
580 if (byte_order == eByteOrderLittle)
582 for (size_t byte = 0; byte < sizeof(uvalue); ++byte, add_prefix = false)
583 bytes_written += _PutHex8 ((uint8_t)(uvalue >> (byte * 8)), add_prefix);
587 for (size_t byte = sizeof(uvalue)-1; byte < sizeof(uvalue); --byte, add_prefix = false)
588 bytes_written += _PutHex8 ((uint8_t)(uvalue >> (byte * 8)), add_prefix);
590 return bytes_written;
594 Stream::PutHex64(uint64_t uvalue, ByteOrder byte_order)
596 if (byte_order == eByteOrderInvalid)
597 byte_order = m_byte_order;
599 bool add_prefix = m_flags.Test(eAddPrefix);
600 size_t bytes_written = 0;
601 if (byte_order == eByteOrderLittle)
603 for (size_t byte = 0; byte < sizeof(uvalue); ++byte, add_prefix = false)
604 bytes_written += _PutHex8 ((uint8_t)(uvalue >> (byte * 8)), add_prefix);
608 for (size_t byte = sizeof(uvalue)-1; byte < sizeof(uvalue); --byte, add_prefix = false)
609 bytes_written += _PutHex8 ((uint8_t)(uvalue >> (byte * 8)), add_prefix);
611 return bytes_written;
619 lldb::ByteOrder byte_order
624 case 1: return PutHex8 ((uint8_t)uvalue);
625 case 2: return PutHex16 ((uint16_t)uvalue);
626 case 4: return PutHex32 ((uint32_t)uvalue);
627 case 8: return PutHex64 (uvalue);
633 Stream::PutPointer (void *ptr)
635 return PutRawBytes (&ptr, sizeof(ptr), lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder());
639 Stream::PutFloat(float f, ByteOrder byte_order)
641 if (byte_order == eByteOrderInvalid)
642 byte_order = m_byte_order;
644 return PutRawBytes (&f, sizeof(f), lldb::endian::InlHostByteOrder(), byte_order);
648 Stream::PutDouble(double d, ByteOrder byte_order)
650 if (byte_order == eByteOrderInvalid)
651 byte_order = m_byte_order;
653 return PutRawBytes (&d, sizeof(d), lldb::endian::InlHostByteOrder(), byte_order);
657 Stream::PutLongDouble(long double ld, ByteOrder byte_order)
659 if (byte_order == eByteOrderInvalid)
660 byte_order = m_byte_order;
662 return PutRawBytes (&ld, sizeof(ld), lldb::endian::InlHostByteOrder(), byte_order);
666 Stream::PutRawBytes (const void *s, size_t src_len, ByteOrder src_byte_order, ByteOrder dst_byte_order)
668 if (src_byte_order == eByteOrderInvalid)
669 src_byte_order = m_byte_order;
671 if (dst_byte_order == eByteOrderInvalid)
672 dst_byte_order = m_byte_order;
674 size_t bytes_written = 0;
675 const uint8_t *src = (const uint8_t *)s;
676 bool binary_was_set = m_flags.Test (eBinary);
678 m_flags.Set (eBinary);
679 if (src_byte_order == dst_byte_order)
681 for (size_t i = 0; i < src_len; ++i)
682 bytes_written += _PutHex8 (src[i], false);
686 for (size_t i = src_len-1; i < src_len; --i)
687 bytes_written += _PutHex8 (src[i], false);
690 m_flags.Clear (eBinary);
692 return bytes_written;
696 Stream::PutBytesAsRawHex8 (const void *s, size_t src_len, ByteOrder src_byte_order, ByteOrder dst_byte_order)
698 if (src_byte_order == eByteOrderInvalid)
699 src_byte_order = m_byte_order;
701 if (dst_byte_order == eByteOrderInvalid)
702 dst_byte_order = m_byte_order;
704 size_t bytes_written = 0;
705 const uint8_t *src = (const uint8_t *)s;
706 bool binary_is_set = m_flags.Test(eBinary);
707 m_flags.Clear(eBinary);
708 if (src_byte_order == dst_byte_order)
710 for (size_t i = 0; i < src_len; ++i)
711 bytes_written += _PutHex8 (src[i], false);
715 for (size_t i = src_len-1; i < src_len; --i)
716 bytes_written += _PutHex8 (src[i], false);
719 m_flags.Set(eBinary);
721 return bytes_written;
725 Stream::PutCStringAsRawHex8 (const char *s)
727 size_t bytes_written = 0;
728 bool binary_is_set = m_flags.Test(eBinary);
729 m_flags.Clear(eBinary);
732 bytes_written += _PutHex8 (*s, false);
736 m_flags.Set(eBinary);
737 return bytes_written;
741 Stream::UnitTest(Stream *s)
746 s->PutHex16(0x3456, lldb::endian::InlHostByteOrder());
748 s->PutHex16(0x3456, eByteOrderBig);
750 s->PutHex16(0x3456, eByteOrderLittle);
753 s->PutHex32(0x789abcde, lldb::endian::InlHostByteOrder());
755 s->PutHex32(0x789abcde, eByteOrderBig);
757 s->PutHex32(0x789abcde, eByteOrderLittle);
760 s->PutHex64(0x1122334455667788ull, lldb::endian::InlHostByteOrder());
762 s->PutHex64(0x1122334455667788ull, eByteOrderBig);
764 s->PutHex64(0x1122334455667788ull, eByteOrderLittle);
766 const char *hola = "Hello World!!!";
768 s->PutCString (hola);
774 s->PutCStringAsRawHex8 (hola);
777 s->PutCStringAsRawHex8 ("01234");
780 s->Printf ("pid=%i", 12733);
783 s->PrintfAsRawHex8 ("pid=%i", 12733);