<rdar://problem/12790664>

Single-character Unicode data formatters

llvm-svn: 172492
This commit is contained in:
Enrico Granata 2013-01-14 23:53:26 +00:00
parent e6f4c68373
commit 93d5966513
6 changed files with 212 additions and 73 deletions

View File

@ -41,7 +41,7 @@ namespace lldb_private {
const char* key);
bool
Char16StringSummaryProvider (ValueObject& valobj, Stream& stream); // char16_t*
Char16StringSummaryProvider (ValueObject& valobj, Stream& stream); // char16_t* and unichar*
bool
Char32StringSummaryProvider (ValueObject& valobj, Stream& stream); // char32_t*
@ -49,6 +49,15 @@ namespace lldb_private {
bool
WCharStringSummaryProvider (ValueObject& valobj, Stream& stream); // wchar_t*
bool
Char16SummaryProvider (ValueObject& valobj, Stream& stream); // char16_t and unichar
bool
Char32SummaryProvider (ValueObject& valobj, Stream& stream); // char32_t
bool
WCharSummaryProvider (ValueObject& valobj, Stream& stream); // wchar_t
bool
LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream); // libc++ std::string

View File

@ -370,6 +370,9 @@ CommandObjectExpression::EvaluateExpression
.SetSummary()
.SetShowSummary(!m_varobj_options.use_objc)
.SetHideRootType(m_varobj_options.use_objc);
if (m_varobj_options.be_raw)
options.SetRawDisplay(true);
ValueObject::DumpValueObject (*(output_stream),
result_valobj_sp.get(), // Variable object to dump

View File

@ -135,55 +135,34 @@ lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
return valobj_sp;
}
template<typename SourceDataType, ConversionResult (*ConvertFunction) (const SourceDataType**,
const SourceDataType*,
UTF8**,
UTF8*,
ConversionFlags)>
// use this call if you already have an LLDB-side buffer for the data
template<typename SourceDataType>
static bool
ReadUTFBufferAndDumpToStream (uint64_t location,
const ProcessSP& process_sp,
Stream& stream,
char prefix_token = '@',
bool want_quotes = true)
DumpUTFBufferToStream (ConversionResult (*ConvertFunction) (const SourceDataType**,
const SourceDataType*,
UTF8**,
UTF8*,
ConversionFlags),
DataExtractor& data,
Stream& stream,
char prefix_token = '@',
char quote = '"',
int sourceSize = 0)
{
if (location == 0 || location == LLDB_INVALID_ADDRESS)
return false;
if (!process_sp)
return false;
const int origin_encoding = 8*sizeof(SourceDataType);
if (origin_encoding != 8 && origin_encoding != 16 && origin_encoding != 32)
return false;
// if not UTF8, I need a conversion function to return proper UTF8
if (origin_encoding != 8 && !ConvertFunction)
return false;
const int sourceSize = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
const int bufferSPSize = sourceSize * (origin_encoding >> 2);
Error error;
lldb::DataBufferSP buffer_sp(new DataBufferHeap(bufferSPSize,0));
if (!buffer_sp->GetBytes())
return false;
size_t data_read = process_sp->ReadMemoryFromInferior(location, (char*)buffer_sp->GetBytes(), bufferSPSize, error);
if (error.Fail())
if (prefix_token != 0)
stream.Printf("%c",prefix_token);
if (quote != 0)
stream.Printf("%c",quote);
if (data.GetByteSize() && data.GetDataStart() && data.GetDataEnd())
{
stream.Printf("unable to read data");
return true;
}
else
{
if (prefix_token != 0)
stream.Printf("%c",prefix_token);
if (want_quotes)
stream.Printf("\"");
}
if (data_read)
{
SourceDataType *data_ptr = (SourceDataType*)buffer_sp->GetBytes();
const int bufferSPSize = data.GetByteSize();
if (sourceSize == 0)
{
const int origin_encoding = 8*sizeof(SourceDataType);
sourceSize = bufferSPSize/(origin_encoding >> 2);
}
SourceDataType *data_ptr = (SourceDataType*)data.GetDataStart();
SourceDataType *data_end_ptr = data_ptr + sourceSize;
while (data_ptr < data_end_ptr)
@ -197,12 +176,12 @@ ReadUTFBufferAndDumpToStream (uint64_t location,
}
*data_ptr = 0;
data_ptr = (SourceDataType*)buffer_sp->GetBytes();
data_ptr = (SourceDataType*)data.GetDataStart();
lldb::DataBufferSP utf8_data_buffer_sp;
UTF8* utf8_data_ptr = nullptr;
UTF8* utf8_data_end_ptr = nullptr;
if (ConvertFunction)
{
utf8_data_buffer_sp.reset(new DataBufferHeap(bufferSPSize,0));
@ -228,13 +207,58 @@ ReadUTFBufferAndDumpToStream (uint64_t location,
break;
stream.Printf("%c",*utf8_data_ptr);
}
if (want_quotes)
stream.Printf("\"");
}
if (quote != 0)
stream.Printf("%c",quote);
return true;
}
template<typename SourceDataType>
static bool
ReadUTFBufferAndDumpToStream (ConversionResult (*ConvertFunction) (const SourceDataType**,
const SourceDataType*,
UTF8**,
UTF8*,
ConversionFlags),
uint64_t location,
const ProcessSP& process_sp,
Stream& stream,
char prefix_token = '@',
char quote = '"',
int sourceSize = 0)
{
if (location == 0 || location == LLDB_INVALID_ADDRESS)
return false;
if (!process_sp)
return false;
const int origin_encoding = 8*sizeof(SourceDataType);
if (origin_encoding != 8 && origin_encoding != 16 && origin_encoding != 32)
return false;
// if not UTF8, I need a conversion function to return proper UTF8
if (origin_encoding != 8 && !ConvertFunction)
return false;
if (sourceSize == 0)
sourceSize = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
const int bufferSPSize = sourceSize * (origin_encoding >> 2);
Error error;
lldb::DataBufferSP buffer_sp(new DataBufferHeap(bufferSPSize,0));
if (!buffer_sp->GetBytes())
return false;
size_t data_read = process_sp->ReadMemoryFromInferior(location, (char*)buffer_sp->GetBytes(), bufferSPSize, error);
if (error.Fail() || data_read == 0)
{
stream.Printf("unable to read data");
return true;
}
if (want_quotes)
stream.Printf("\"");
return true;
DataExtractor data(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize());
return DumpUTFBufferToStream(ConvertFunction, data, stream, prefix_token, quote, sourceSize);
}
bool
@ -249,11 +273,10 @@ lldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stre
if (!valobj_addr)
return false;
if (!ReadUTFBufferAndDumpToStream<UTF16, ConvertUTF16toUTF8>(valobj_addr,
if (!ReadUTFBufferAndDumpToStream<UTF16>(ConvertUTF16toUTF8,valobj_addr,
process_sp,
stream,
'u',
true)) // but use quotes
'u'))
{
stream.Printf("Summary Unavailable");
return true;
@ -274,11 +297,10 @@ lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stre
if (!valobj_addr)
return false;
if (!ReadUTFBufferAndDumpToStream<UTF32, ConvertUTF32toUTF8>(valobj_addr,
if (!ReadUTFBufferAndDumpToStream<UTF32>(ConvertUTF32toUTF8,valobj_addr,
process_sp,
stream,
'U',
true)) // but use quotes
'U'))
{
stream.Printf("Summary Unavailable");
return true;
@ -315,25 +337,107 @@ lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Strea
{
case 8:
// utf 8
return ReadUTFBufferAndDumpToStream<UTF8, nullptr>(data_addr,
return ReadUTFBufferAndDumpToStream<UTF8>(nullptr, data_addr,
process_sp,
stream,
'L',
true); // but use quotes
'L');
case 16:
// utf 16
return ReadUTFBufferAndDumpToStream<UTF16, ConvertUTF16toUTF8>(data_addr,
return ReadUTFBufferAndDumpToStream<UTF16>(ConvertUTF16toUTF8, data_addr,
process_sp,
stream,
'L',
true); // but use quotes
'L');
case 32:
// utf 32
return ReadUTFBufferAndDumpToStream<UTF32, ConvertUTF32toUTF8>(data_addr,
return ReadUTFBufferAndDumpToStream<UTF32>(ConvertUTF32toUTF8, data_addr,
process_sp,
stream,
'L',
true); // but use quotes
'L');
default:
stream.Printf("size for wchar_t is not valid");
return true;
}
return true;
}
bool
lldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& stream)
{
DataExtractor data;
valobj.GetData(data);
std::string value;
valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
if (!value.empty())
stream.Printf("%s ", value.c_str());
return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8,data,stream, 'u','\'',1);
}
bool
lldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& stream)
{
DataExtractor data;
valobj.GetData(data);
std::string value;
valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
if (!value.empty())
stream.Printf("%s ", value.c_str());
return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8,data,stream, 'U','\'',1);
}
bool
lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream)
{
DataExtractor data;
valobj.GetData(data);
clang::ASTContext* ast = valobj.GetClangAST();
if (!ast)
return false;
std::string value;
uint32_t wchar_size = ClangASTType::GetClangTypeBitWidth(ast, ClangASTType::GetBasicType(ast, lldb::eBasicTypeWChar).GetOpaqueQualType());
switch (wchar_size)
{
case 8:
// utf 8
valobj.GetValueAsCString(lldb::eFormatChar, value);
if (!value.empty())
stream.Printf("%s ", value.c_str());
return DumpUTFBufferToStream<UTF8>(nullptr,
data,
stream,
'L',
'\'',
1);
case 16:
// utf 16
valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
if (!value.empty())
stream.Printf("%s ", value.c_str());
return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8,
data,
stream,
'L',
'\'',
1);
case 32:
// utf 32
valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
if (!value.empty())
stream.Printf("%s ", value.c_str());
return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8,
data,
stream,
'L',
'\'',
1);
default:
stream.Printf("size for wchar_t is not valid");
return true;
@ -827,7 +931,7 @@ lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream&
if (error.Fail())
return false;
if (has_explicit_length and is_unicode)
return ReadUTFBufferAndDumpToStream<UTF16,ConvertUTF16toUTF8> (location, process_sp, stream, '@');
return ReadUTFBufferAndDumpToStream<UTF16> (ConvertUTF16toUTF8,location, process_sp, stream, '@');
else
{
location++;
@ -870,12 +974,12 @@ lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream&
if (error.Fail())
return false;
}
return ReadUTFBufferAndDumpToStream<UTF16,ConvertUTF16toUTF8> (location, process_sp, stream, '@');
return ReadUTFBufferAndDumpToStream<UTF16> (ConvertUTF16toUTF8, location, process_sp, stream, '@');
}
else if (is_special)
{
uint64_t location = valobj_addr + (ptr_size == 8 ? 12 : 8);
return ReadUTFBufferAndDumpToStream<UTF16,ConvertUTF16toUTF8> (location, process_sp, stream, '@');
return ReadUTFBufferAndDumpToStream<UTF16> (ConvertUTF16toUTF8, location, process_sp, stream, '@');
}
else if (is_inline)
{

View File

@ -968,6 +968,25 @@ FormatManager::LoadSystemFormatters()
AddCXXSummary(sys_category_sp, lldb_private::formatters::WCharStringSummaryProvider, "wchar_t * summary provider", ConstString("wchar_t *"), string_flags);
AddCXXSummary(sys_category_sp, lldb_private::formatters::WCharStringSummaryProvider, "wchar_t * summary provider", ConstString("const wchar_t *"), string_flags);
AddCXXSummary(sys_category_sp, lldb_private::formatters::Char16StringSummaryProvider, "unichar * summary provider", ConstString("unichar *"), string_flags);
AddCXXSummary(sys_category_sp, lldb_private::formatters::Char16StringSummaryProvider, "unichar * summary provider", ConstString("const unichar *"), string_flags);
TypeSummaryImpl::Flags widechar_flags;
widechar_flags.SetDontShowValue(true)
.SetSkipPointers(true)
.SetSkipReferences(false)
.SetCascades(true)
.SetDontShowChildren(true)
.SetHideItemNames(true)
.SetShowMembersOneLiner(false);
AddCXXSummary(sys_category_sp, lldb_private::formatters::Char16SummaryProvider, "char16_t summary provider", ConstString("char16_t"), widechar_flags);
AddCXXSummary(sys_category_sp, lldb_private::formatters::Char32SummaryProvider, "char32_t summary provider", ConstString("char32_t"), widechar_flags);
AddCXXSummary(sys_category_sp, lldb_private::formatters::WCharSummaryProvider, "wchar_t summary provider", ConstString("wchar_t"), widechar_flags);
AddCXXSummary(sys_category_sp, lldb_private::formatters::Char16SummaryProvider, "unichar summary provider", ConstString("unichar"), widechar_flags);
#endif
}

View File

@ -74,6 +74,10 @@ class Char1632TestCase(TestBase):
self.expect("frame variable s16 s32",
substrs = ['(char16_t *) s16 = 0x','(char32_t *) s32 = ','"色ハ匂ヘト散リヌルヲ"','""'])
# Check that we can run expressions that return charN_t
self.expect("expression u'a'",substrs = ['(char16_t) $',"61 u'a'"])
self.expect("expression U'a'",substrs = ['(char32_t) $',"61 U'a'"])
if __name__ == '__main__':
import atexit
lldb.SBDebugger.Initialize()

View File

@ -67,7 +67,7 @@ class CxxWCharTTestCase(TestBase):
substrs = ['(int) foo_x.object = '])
# Check that we can run expressions that return wchar_t
self.expect("expression L'a'",substrs = ['(wchar_t) $'])
self.expect("expression L'a'",substrs = ['(wchar_t) $',"61 L'a'"])
# Mazel Tov if this works!
self.expect("frame variable mazeltov",