<html><head><meta http-equiv="Content-Type" content="text/html charset=windows-1252"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">On Apr 28, 2014, at 3:01 PM, Poenitz Andre <<a href="mailto:Andre.Poenitz@digia.com">Andre.Poenitz@digia.com</a>> wrote:<br><div><br class="Apple-interchange-newline"><blockquote type="cite"><div style="font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; direction: ltr; font-family: Tahoma; font-size: 10pt;"><br>Enrico Granata wrote:<br>> Eran Ifrah wrote:<br><div style="font-family: 'Times New Roman'; font-size: 16px;">> You can't use expressions in summary strings.<div><div>> We have thought about this several times and have a couple ideas on how<span class="Apple-converted-space"> </span><br>> it could be done but for now it's not there.</div><div>><br></div><div>> If you need to resort to an expression, you can use a python formatter<br>> instead and then you are free to call as many expressions as you like.</div><div>><br></div><div>> However, this will cause a slowdown - running expressions is not<br>> free - and if you ever need to make sure nothing is altering your<br>> program state, running expressions might not be a safe bet.</div><div>> Is there really no other way to get to those UTF8 bytes?<br><br>QString is stored in UTF16 internally. It can be accessed directly<span class="Apple-converted-space"> </span><br>through structure member access and pointer arithmetic and converted<span class="Apple-converted-space"> </span><br>using Python. "Running expressions" is not needed.<br><br>Andre'</div></div></div></div></blockquote></div><div><br></div><div>Here’s a small example for general reference:</div><div>Assume I have the following data structure:</div><div><br></div><div><div><font face="Menlo"><span style="font-size: 11px;">#include <string><br>#include <memory><br><br>class UTF16String {<br>public:<br> UTF16String (const char16_t *data) {<br> len = std::char_traits<char16_t>::length(data);<br> str_data.reset(new char16_t[len]);<br> memcpy(str_data.get(),data,sizeof(char16_t)*(len+1));<br> }<br> <br>private:<br> std::unique_ptr<char16_t[]> str_data;<br> size_t len;<br>};<br><br>int main() {<br> UTF16String string {u"Just some data in UTF16 here"};<br> return 0;<br>}<br></span></font><br><br></div></div><div>This is what it looks like “raw” on OS X:</div><div><font face="Menlo"><span style="font-size: 11px;">(UTF16String) string = {<br> str_data = {<br> __ptr_ = {<br> std::__1::__libcpp_compressed_pair_imp<char16_t *, std::__1::default_delete<char16_t> > = {<br> __first_ = 0x00000001001037e0<br> }<br> }<br> }<br> len = 28<br>}<br></span></font><br></div><div>To define a formatter for it you essentially want to grab two elements: the data pointer (__first_ = 0x00000001001037e0) and the length (len = 30)</div><div>In our example, the length is defined in UTF16-characters rather than bytes. This is something you want to know when writing a formatter</div><div><br></div><div>So let’s delve right in:</div><div><div><font face="Menlo"><span style="font-size: 11px;">def utf16string_summary(value,*rest):</span></font></div><div><font face="Menlo"><span style="font-size: 11px;"> str_data = value.GetChildMemberWithName("str_data").GetChildMemberWithName("__ptr_").GetChildMemberWithName("__first_")</span></font></div><div><font face="Menlo"><span style="font-size: 11px;"> length_vo = value.GetChildMemberWithName("len")</span></font></div></div><div><br></div><div>Now we have SBValues for the string data and for the length - we want the “number stored inside” the length:</div><div><div><font face="Menlo"><span style="font-size: 11px;"> length = length_vo.GetValueAsUnsigned(0)</span></font></div><div><font face="Menlo"><span style="font-size: 11px;"> if length == 0:</span></font></div><div><font face="Menlo"><span style="font-size: 11px;"> return '""'</span></font></div></div><div><br></div><div>As a special case - if the length is zero, just return an empty string. I am not going to go in detail over all the possible checks here (hint: what if str_data’s value is zero?)</div><div><br></div><div>Now let’s grab the bytes - we want length char16_t at the location pointed to by our str_data:</div><div><div><font face="Menlo"><span style="font-size: 11px;"> data = str_data.GetPointeeData(0,length)</span></font></div></div><div><br></div><div>And now let’s grab a Python string out of those bytes:</div><div><div><font face="Menlo"><span style="font-size: 11px;"> error = lldb.SBError()</span></font></div><div><font face="Menlo"><span style="font-size: 11px;"> bytes = data.ReadRawData(error,0,2*length)<br></span></font><br></div></div><div>The 2*length argument is <i>carefully</i> crafted to ensure we get all the bytes we need - it of course depends on sizeof(char16_t) == 2</div><div><br></div><div>Python is pretty good at string management, all we have to do now is tell it to turn our string from UTF16 into UTF8:</div><div><div><font face="Menlo"><span style="font-size: 11px;"> return '"%s"' % (bytes.decode('utf-16').encode('utf-8'))</span></font></div></div><div><br></div><div>You’re done. To add the summary automatically to LLDB whenever you command script import the python file with the formatter:</div><div><div><font face="Menlo"><span style="font-size: 11px;">def __lldb_init_module(debugger,*rest):</span></font></div><div><font face="Menlo"><span style="font-size: 11px;"> summary = lldb.SBTypeSummary.CreateWithFunctionName("qstring.utf16string_summary")</span></font></div><div><font face="Menlo"><span style="font-size: 11px;"> summary.SetOptions(lldb.eTypeOptionHideChildren)</span></font></div><div><font face="Menlo"><span style="font-size: 11px;"> debugger.GetDefaultCategory().AddTypeSummary(lldb.SBTypeNameSpecifier("UTF16String",False),summary)</span></font></div><div><br></div></div><div>This is what you get with the summary enabled:</div><div>(UTF16String) string = "Just some data in UTF16 here”<br><br></div><div>Find the C++ and the Python parts of the example attached for reference - and of course feel free to ping back with any additional questions</div><div><br></div></body></html>