Я ищу подходящий способ отображения UUID через NatVis в VS2012 - программирование
Подтвердить что ты не робот

Я ищу подходящий способ отображения UUID через NatVis в VS2012

Я ищу подходящий способ отображения UUID через NatVis в VS2012. Мой собственный тип uuid использует UUID big-endian внутри, поэтому приведение к GUID * не работает, поскольку GUID использует little-endian в Windows. Поэтому я всегда вижу искаженный uuid.

Кроме того, любой спецификатор формата в Natvis выглядит не очень хорошо, потому что я не могу избавиться от 0x в выходе при использовании шестнадцатеричной нотации. Любые идеи?

4b9b3361

Ответ 1

Здесь более компактная версия решения ComicSansMS. Вместо этого я использую структуру SHA1 и визуализатор.

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>

Если вы можете получить доступ к массиву символов, определенному в коде, вы можете использовать формат строки ,1sb и избегать любого разветвления. Добавьте [DLL export/extern/static] const char* hex_chars="0123456789abcdef"; в пространство имен natvis и замените 16 условных DisplayStrings на один:

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

Насколько я знаю, нет способа использовать оператор контекста {,,mylib[d].dll}natvis::hex_chars таким образом, который работает как с статическими, так и с DLL-сборками. Вы можете использовать static const char* hex_chars = "...", но это добавит строку в каждый .obj файл, который включает заголовок.

Пожалуйста, оставьте комментарий, если вы знаете решение, которое не вызывает раздувание:)

Ответ 2

Этот подход далеко не хорош, но он выполняет свою работу.

Во-первых, вам нужен фиктивный тип где-то в вашем коде, который обрабатывает отображение одного байта в шестнадцатеричном виде без каких-либо префиксов. Это похоже на действительно грязный взлом, поскольку мы должны ввести дополнительный код в наш код только для правильной визуализации отладки.

namespace dummy {
    struct hex_dummy {
        unsigned char c;
    };
}

Этот тип может быть размещен практически везде, пока отладчик может найти его в контексте, где мы хотим посмотреть uuid.

Следующий шаг, к сожалению, почти так же плох. Чтобы иметь возможность печатать байты в шестнадцатеричном формате без префикса 0x, мы вводим визуализатор отладки для hex_dummy с колоссальным 256 различными DisplayStrings:

<Type Name="dummy::hex_dummy">
    <DisplayString Condition="(c == 0x00)">00</DisplayString>
    <DisplayString Condition="(c == 0x01)">01</DisplayString>
    <DisplayString Condition="(c == 0x02)">02</DisplayString>
    <DisplayString Condition="(c == 0x03)">03</DisplayString>
    <DisplayString Condition="(c == 0x04)">04</DisplayString>
    <DisplayString Condition="(c == 0x05)">05</DisplayString>
    <DisplayString Condition="(c == 0x06)">06</DisplayString>
    <DisplayString Condition="(c == 0x07)">07</DisplayString>
    <DisplayString Condition="(c == 0x08)">08</DisplayString>
    <DisplayString Condition="(c == 0x09)">09</DisplayString>
    <DisplayString Condition="(c == 0x0a)">0A</DisplayString>
    <DisplayString Condition="(c == 0x0b)">0B</DisplayString>
    <DisplayString Condition="(c == 0x0c)">0C</DisplayString>
    <DisplayString Condition="(c == 0x0d)">0D</DisplayString>
    <DisplayString Condition="(c == 0x0e)">0E</DisplayString>
    <DisplayString Condition="(c == 0x0f)">0F</DisplayString>

    <DisplayString Condition="(c == 0x10)">10</DisplayString>
    <DisplayString Condition="(c == 0x11)">11</DisplayString>
 ...

Вы получаете идею.

С этим на месте визуализация uuid проста. Я использовал boost::uuid для тестирования этого:

<Type Name="boost::uuids::uuid">
    <DisplayString>uuid {*(dummy::hex_dummy*)(&amp;data[0])}{*(dummy::hex_dummy*)(&amp;data[1])}{*(dummy::hex_dummy*)(&amp;data[2])}{*(dummy::hex_dummy*)(&amp;data[3])}-{*(dummy::hex_dummy*)(&amp;data[4])}{*(dummy::hex_dummy*)(&amp;data[5])}-{*(dummy::hex_dummy*)(&amp;data[6])}{*(dummy::hex_dummy*)(&amp;data[7])}-{*(dummy::hex_dummy*)(&amp;data[8])}{*(dummy::hex_dummy*)(&amp;data[9])}-{*(dummy::hex_dummy*)(&amp;data[10])}{*(dummy::hex_dummy*)(&amp;data[11])}{*(dummy::hex_dummy*)(&amp;data[12])}{*(dummy::hex_dummy*)(&amp;data[13])}{*(dummy::hex_dummy*)(&amp;data[14])}{*(dummy::hex_dummy*)(&amp;data[15])}</DisplayString>
</Type>

Вы можете легко убедиться, что он работает, тестируя его с помощью uuid, созданного boost uuid_generator:

boost::uuids::uuid const test_id =
    boost::uuids::string_generator()("{01234567-89AB-CDEF-0123-456789ABCDEF}");

enter image description here

Теперь это решение не только абиссально уродливое, но и кажется, что отладчик некоторое время работает через массивное ветвление hex_dummy, что приводит к заметной задержке появления окна часового пояса при наведении курсора мыши на uuid while отладки.

Я не очень доволен этим решением, но пока это лучшее, что я мог бы придумать. Если кто-либо увидит какой-либо потенциал для улучшения, не жертвуя ясностью конечного результата, я был бы очень рад услышать их.

Изменить: Небольшое улучшение - путем введения двух фиктивных типов вместо одного я мог бы по крайней мере избавиться от задержки всплывающего окна. Идея состоит в двух использовании отдельных манекенов для печати верхнего и нижнего полубайта каждого байта, поэтому нам нужно сделать две 16-сторонние ветки на каждый байт вместо одной 256-way-ветки.

namespace dummy {
    struct hex_dummy_low {
        unsigned char c;
    };

    struct hex_dummy_high {
        unsigned char c;
    };
}

Прокси-визуализаторы:

<Type Name="dummy::hex_dummy_low">
    <DisplayString Condition="((c &amp; 0x0f) == 0x00)">0</DisplayString>
    <DisplayString Condition="((c &amp; 0x0f) == 0x01)">1</DisplayString>
    <DisplayString Condition="((c &amp; 0x0f) == 0x02)">2</DisplayString>
    <DisplayString Condition="((c &amp; 0x0f) == 0x03)">3</DisplayString>
    <DisplayString Condition="((c &amp; 0x0f) == 0x04)">4</DisplayString>
    <DisplayString Condition="((c &amp; 0x0f) == 0x05)">5</DisplayString>
    <DisplayString Condition="((c &amp; 0x0f) == 0x06)">6</DisplayString>
    <DisplayString Condition="((c &amp; 0x0f) == 0x07)">7</DisplayString>
    <DisplayString Condition="((c &amp; 0x0f) == 0x08)">8</DisplayString>
    <DisplayString Condition="((c &amp; 0x0f) == 0x09)">9</DisplayString>
    <DisplayString Condition="((c &amp; 0x0f) == 0x0a)">A</DisplayString>
    <DisplayString Condition="((c &amp; 0x0f) == 0x0b)">B</DisplayString>
    <DisplayString Condition="((c &amp; 0x0f) == 0x0c)">C</DisplayString>
    <DisplayString Condition="((c &amp; 0x0f) == 0x0d)">D</DisplayString>
    <DisplayString Condition="((c &amp; 0x0f) == 0x0e)">E</DisplayString>
    <DisplayString Condition="((c &amp; 0x0f) == 0x0f)">F</DisplayString>
</Type>

<Type Name="dummy::hex_dummy_high">
    <DisplayString Condition="((c >> 4) == 0x00)">0</DisplayString>
    <DisplayString Condition="((c >> 4) == 0x01)">1</DisplayString>
    <DisplayString Condition="((c >> 4) == 0x02)">2</DisplayString>
    <DisplayString Condition="((c >> 4) == 0x03)">3</DisplayString>
    <DisplayString Condition="((c >> 4) == 0x04)">4</DisplayString>
    <DisplayString Condition="((c >> 4) == 0x05)">5</DisplayString>
    <DisplayString Condition="((c >> 4) == 0x06)">6</DisplayString>
    <DisplayString Condition="((c >> 4) == 0x07)">7</DisplayString>
    <DisplayString Condition="((c >> 4) == 0x08)">8</DisplayString>
    <DisplayString Condition="((c >> 4) == 0x09)">9</DisplayString>
    <DisplayString Condition="((c >> 4) == 0x0a)">A</DisplayString>
    <DisplayString Condition="((c >> 4) == 0x0b)">B</DisplayString>
    <DisplayString Condition="((c >> 4) == 0x0c)">C</DisplayString>
    <DisplayString Condition="((c >> 4) == 0x0d)">D</DisplayString>
    <DisplayString Condition="((c >> 4) == 0x0e)">E</DisplayString>
    <DisplayString Condition="((c >> 4) == 0x0f)">F</DisplayString>
</Type>

И последний визуализатор uuid:

<Type Name="boost::uuids::uuid">
    <DisplayString>uuid {*(dummy::hex_dummy_high*)(&amp;data[0])}{*(dummy::hex_dummy_low*)(&amp;data[0])}{*(dummy::hex_dummy_high*)(&amp;data[1])}{*(dummy::hex_dummy_low*)(&amp;data[1])}{*(dummy::hex_dummy_high*)(&amp;data[2])}{*(dummy::hex_dummy_low*)(&amp;data[2])}{*(dummy::hex_dummy_high*)(&amp;data[3])}{*(dummy::hex_dummy_low*)(&amp;data[3])}-{*(dummy::hex_dummy_high*)(&amp;data[4])}{*(dummy::hex_dummy_low*)(&amp;data[4])}{*(dummy::hex_dummy_high*)(&amp;data[5])}{*(dummy::hex_dummy_low*)(&amp;data[5])}-{*(dummy::hex_dummy_high*)(&amp;data[6])}{*(dummy::hex_dummy_low*)(&amp;data[6])}{*(dummy::hex_dummy_high*)(&amp;data[7])}{*(dummy::hex_dummy_low*)(&amp;data[7])}-{*(dummy::hex_dummy_high*)(&amp;data[8])}{*(dummy::hex_dummy_low*)(&amp;data[8])}{*(dummy::hex_dummy_high*)(&amp;data[9])}{*(dummy::hex_dummy_low*)(&amp;data[9])}-{*(dummy::hex_dummy_high*)(&amp;data[10])}{*(dummy::hex_dummy_low*)(&amp;data[10])}{*(dummy::hex_dummy_high*)(&amp;data[11])}{*(dummy::hex_dummy_low*)(&amp;data[11])}{*(dummy::hex_dummy_high*)(&amp;data[12])}{*(dummy::hex_dummy_low*)(&amp;data[12])}{*(dummy::hex_dummy_high*)(&amp;data[13])}{*(dummy::hex_dummy_low*)(&amp;data[13])}{*(dummy::hex_dummy_high*)(&amp;data[14])}{*(dummy::hex_dummy_low*)(&amp;data[14])}{*(dummy::hex_dummy_high*)(&amp;data[15])}{*(dummy::hex_dummy_low*)(&amp;data[15])}</DisplayString>
</Type>

Ответ 3

Вы можете попробовать мое расширение С++ Debugger Visualizer. Версия 1.0.16 поддерживает boost:: uuids:: uuid визуализатор, используя AddIn dll.

Ответ 4

Здесь простое решение, которое не требует дополнительных фиктивных структур в коде:

<Type Name="boost::uuids::uuid">
   <DisplayString>{((((int32)data[3] &amp; 0xFF)) + (((int32)data[2] &amp; 0xFF) &lt;&lt; 8) + (((int32)data[1] &amp; 0xFF) &lt;&lt; 16) + (((int32)data[0] &amp; 0xFF) &lt;&lt; 24)),X} - {((((int32)data[7] &amp; 0xFF)) + (((int32)data[6] &amp; 0xFF) &lt;&lt; 8) + (((int32)data[5] &amp; 0xFF) &lt;&lt; 16) + (((int32)data[4] &amp; 0xFF) &lt;&lt; 24)),X} - {((((int32)data[11] &amp; 0xFF)) + (((int32)data[10] &amp; 0xFF) &lt;&lt; 8) + (((int32)data[9] &amp; 0xFF) &lt;&lt; 16) + (((int32)data[8] &amp; 0xFF) &lt;&lt; 24)),X} - {((((int32)data[15] &amp; 0xFF)) + (((int32)data[14] &amp; 0xFF) &lt;&lt; 8) + (((int32)data[13] &amp; 0xFF) &lt;&lt; 16) + (((int32)data[12] &amp; 0xFF) &lt;&lt; 24)),X}</DisplayString>
</Type>

Он не показывает UUID так же хорошо, как другие решения, он просто показывает его как 4 блока из 32-битных целых чисел, но он выполняет задание:

uuid visualizer