Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I am looking for a proper way to display a UUID via NatVis in VS2012

I am looking for a proper way to display a UUID via NatVis in VS2012. My own uuid type uses UUID big-endian internally so a cast to (GUID*) does not work as GUID uses little-endian in Windows. So I always see a misrepresented uuid.

Furthermore any format specifier in Natvis looks not nice because i can't get rid of the 0x in the output when using the hex notation. Any ideas?

like image 253
HelloWorld Avatar asked Jul 02 '13 22:07

HelloWorld


1 Answers

Here's a more compact version of ComicSansMS solution. I'm using a SHA1 struct and visualizer as example instead.

struct SHA1 { char hash[20]; };

namespace natvis
{
    struct x4lo { unsigned __int8 v : 4;    unsigned __int8 _ : 4; };
    struct x4hi { unsigned __int8 _ : 4;    unsigned __int8 v : 4; };
    struct x8 { unsigned __int8 _; };
    struct x32 { __int32 _; };
}

natvis

<Type Name="natvis::x4hi">
  <AlternativeType Name="natvis::x4lo" />
  <DisplayString Condition="v==0">0</DisplayString>
  <DisplayString Condition="v==1">1</DisplayString>
  <DisplayString Condition="v==2">2</DisplayString>
  <DisplayString Condition="v==3">3</DisplayString>
  <DisplayString Condition="v==4">4</DisplayString>
  <DisplayString Condition="v==5">5</DisplayString>
  <DisplayString Condition="v==6">6</DisplayString>
  <DisplayString Condition="v==7">7</DisplayString>
  <DisplayString Condition="v==8">8</DisplayString>
  <DisplayString Condition="v==9">9</DisplayString>
  <DisplayString Condition="v==10">a</DisplayString>
  <DisplayString Condition="v==11">b</DisplayString>
  <DisplayString Condition="v==12">c</DisplayString>
  <DisplayString Condition="v==13">d</DisplayString>
  <DisplayString Condition="v==14">e</DisplayString>
  <DisplayString>f</DisplayString>
</Type>
<Type Name="natvis::x8">
    <DisplayString>{*(natvis::x4hi*)(this)}{*(natvis::x4lo*)(this)}</DisplayString>
</Type>
<Type Name="natvis::x32">
    <DisplayString>{((natvis::x8*)this)[0]}{((natvis::x8*)this)[1]}{((natvis::x8*)this)[2]}{((natvis::x8*)this)[3]}</DisplayString>
</Type>
<Type Name="SHA1">
    <DisplayString>{((natvis::x32*)hash)[0]}{((natvis::x32*)hash)[1]}{((natvis::x32*)hash)[2]} {((natvis::x32*)hash)[3]}{((natvis::x32*)hash)[4]}</DisplayString>
</Type>

If you can access a character array defined in code you can use the ,1sb string format and avoid any branching. Add [DLL export/extern/static] const char* hex_chars="0123456789abcdef"; to the natvis namespace and replace the 16 conditional DisplayStrings with a single one:

<Type Name="natvis::x4hi">
  <AlternativeType Name="natvis::x4lo" />
  <DisplayString>{(hex_chars+v),1sb}</DisplayString>
</Type>

To my knowledge there is no way to use the context operator {,,mylib[d].dll}natvis::hex_chars in a way that works with both static and DLL builds. You can use static const char* hex_chars = "..." but that'll add the string to every .obj file that includes the header.

Please leave a comment if you know a solution that doesn't cause bloat :)

like image 79
Johan Torp Avatar answered Sep 21 '22 14:09

Johan Torp