Difference between revisions of "VisualStudioVisualizer"

From Apache OpenOffice Wiki
Jump to: navigation, search
m (Typo)
(added std::auto_ptr)
Line 13: Line 13:
 
=== Visualizers for STL types ===
 
=== Visualizers for STL types ===
  
 +
* Auto_ptr
 +
** <tt>std::auto_ptr<T></tt>: The preview shows the address and the contents of the referenced object. The children tree shows the contents of the object.
 
* Vector
 
* Vector
 
** <tt>[http://www.sgi.com/tech/stl/Vector.html std::vector<T>]</tt>: The preview shows the memory address and size of the vector. The children tree shows all elements of the vector.
 
** <tt>[http://www.sgi.com/tech/stl/Vector.html std::vector<T>]</tt>: The preview shows the memory address and size of the vector. The children tree shows all elements of the vector.
Line 40: Line 42:
 
<pre>
 
<pre>
 
[Visualizer]
 
[Visualizer]
 +
 +
; standard classes
 +
 +
_STL::auto_ptr<*> {
 +
  preview (
 +
    #if ($e._M_p == 0) (
 +
      #( "[empty]" )
 +
    ) #else (
 +
      #( $e._M_p, " data=", *($T1*)$e._M_p )
 +
    )
 +
  )
 +
  children (
 +
    #if ($e._M_p != 0) (
 +
      #( data : *($T1*)$e._M_p )
 +
    )
 +
  )
 +
}
  
 
; STL implementation structures
 
; STL implementation structures

Revision as of 19:18, 17 February 2009

Description

It is quite inconvenient to work with containers in the Visual Studio debugger. To make things a bit better, "visualizers" can be written telling the debugger what it has to show for specific data types. Visualizers are described in the special file "AUTOEXP.DAT" which can be found in the directory [visual-studio-installation-path]\Common7\Packages\Debugger\. To add the new visualizers, copy the code below and append it to this file.

Note that the STL visualizers will only work for stl_port data types in Windows debug builds.

Visualizers consist of two parts:

  • The preview part describes what is shown in the tooltip and quick watch window.
  • The children part describes what is shown when expanding the object to show its contents (debugger default behaviour is to show the members of classes and structs).

Supported Types

Visualizers for STL types

  • Auto_ptr
    • std::auto_ptr<T>: The preview shows the address and the contents of the referenced object. The children tree shows the contents of the object.
  • Vector
    • std::vector<T>: The preview shows the memory address and size of the vector. The children tree shows all elements of the vector.
    • std::vector<T>::iterator, std::vector<T>::const_iterator, std::vector<T>::reverse_iterator, std::vector<T>::const_reverse_iterator: The preview shows the data element pointed to, if the iterator is valid. Otherwise, one of the special values [invalid] (empty iterator) or [end] (iterator pointing to the end of the vector) is shown. The children tree shows the index of the element in the vector, the element data, and the complete vector containing the element.
  • Deque
    • std::deque<T>: The preview shows the memory address and size of the deque. The children tree shows all elements of the deque.
    • std::deque<T>::iterator, std::deque<T>::const_iterator, std::deque<T>::reverse_iterator, std::deque<T>::const_reverse_iterator: Same as vector iterators, see above, except that the index of the element is not shown.
  • List
    • std::list<T>: The preview shows the memory address of the list. The children tree shows all elements of the list.
    • std::list<T>::iterator, std::list<T>::const_iterator, std::list<T>::reverse_iterator, std::list<T>::const_reverse_iterator: Same as vector iterators, see above, except that the index of the element is not shown.
  • Set, multiset
    • std::set<T>, std::multiset<T>: The preview shows the memory address and element count of the set or multiset. The children tree shows all elements of the set in ascending order.
    • std::set<T>::iterator, std::set<T>::const_iterator, std::multiset<T>::iterator, std::multiset<T>::const_iterator: Same as vector iterators, see above, except that the index of the element is not shown.
  • Map, multimap
    • std::map<K,T>, std::multimap<K,T>: The preview shows the memory address and element count of the map or multimap. The children tree shows all elements of the map (key/data pairs) in ascending order.
    • std::map<K,T>::iterator, std::map<K,T>::const_iterator, std::multimap<K,T>::iterator, std::multimap<K,T>::const_iterator: Same as vector iterators, see above, except that the index of the element is not shown.

Visualizers for reverse set/map iterators are not implemented yet. In general, reverse iterators do not point to the element they refer to, but to their successor. While it is quite easy to find the predesessor in a vector or list, doing so in a red/black tree is a bit more complicated.

Visualizers for UNO types

  • com::sun::star::uno::Sequence<T>: Similarly to the STL vector, the preview shows the memory address and size of the sequence, and the children tree shows all elements of the sequence.
  • com::sun::star::uno::Any: Shows the contents of an Any for atomic types (boolean, integer, floating-point, enum, string). Complex types (structs, sequences, interfaces, etc.) are not supported.

Visualizers Source Code

Append the following code to [visual-studio-installation-path]\Common7\Packages\Debugger\AUTOEXP.DAT.

[Visualizer]

; standard classes

_STL::auto_ptr<*> {
  preview (
    #if ($e._M_p == 0) (
      #( "[empty]" )
    ) #else (
      #( $e._M_p, " data=", *($T1*)$e._M_p )
    )
  )
  children (
    #if ($e._M_p != 0) (
      #( data : *($T1*)$e._M_p )
    )
  )
}

; STL implementation structures

_STL::_Rb_tree_node<_STL::pair<*,*> > {
  preview (
    #( "key=", $e._M_value_field.first, " data=", $e._M_value_field.second )
  )
  children (
    #(
      [key] : $e._M_value_field.first,
      data : $e._M_value_field.second
     )
  )
}

; STL containers

_STL::vector<*,*> {
  preview (
    #if ($e._M_start >= $e._M_finish) (
      #( (void*)(&$e), " [empty]" )
    ) #else (
      #( (void*)(&$e), " {size=", $e._M_finish - $e._M_start, "}" )
    )
  )
  children (
    #array (
      expr : ($e._M_start)[$i],
      size : $e._M_finish - $e._M_start
    )
  )
}

_STL::deque<*,*> {
  preview (
    #if ($e._M_start._M_cur == $e._M_finish._M_cur) (
      #( (void*)(&$e), " [empty]" )
    ) #else (
      #(
        (void*)(&$e), " {size=",
        ($e._M_finish._M_node - $e._M_start._M_node + 1) * ($e._M_start._M_last - $e._M_start._M_first) - ($e._M_start._M_cur - $e._M_start._M_first) - ($e._M_finish._M_last - $e._M_finish._M_cur),
        "}"
      )
    )
  )
  children (
    #array (
      expr : ($e._M_start._M_node)[ ($i + $e._M_start._M_cur - $e._M_start._M_first) / ($e._M_start._M_last - $e._M_start._M_first) ][ ($i + $e._M_start._M_cur - $e._M_start._M_first) % ($e._M_start._M_last - $e._M_start._M_first) ],
      size : ($e._M_finish._M_node - $e._M_start._M_node + 1) * ($e._M_start._M_last - $e._M_start._M_first) - ($e._M_start._M_cur - $e._M_start._M_first) - ($e._M_finish._M_last - $e._M_finish._M_cur)
    )
  )
}

_STL::list<*,*> {
  preview (
    #if ($e._M_node._M_data->_M_next == $e._M_node._M_data->_M_prev) (
      #( (void*)(&$e), " [empty]" )
    ) #else (
      #( (void*)(&$e) )
    )
  )
  children (
    #list (
      head : $e._M_node._M_data->_M_next,
      skip : $e._M_node._M_data,
      next : _M_next
    ) : ((_STL::_List_node<$T1>*)(&$e))->_M_data
  )
}

_STL::set<*,*,*>|_STL::multiset<*,*,*> {
  preview (
    #if ($e._M_t._M_node_count <= 0) (
      #( (void*)(&$e), " [empty]" )
    ) #else (
      #( (void*)(&$e), " {size=", $e._M_t._M_node_count, "}" )
    )
  )
  children (
    #tree (
      head : $e._M_t._M_header._M_data->_M_parent,
      skip : $e._M_t._M_header._M_data,
      left : _M_left,
      right : _M_right,
      size : $e._M_t._M_node_count
    ) : ((_STL::_Rb_tree_node<$T1>*)(&$e))->_M_value_field
  )
}

_STL::map<*,*,*,*>|_STL::multimap<*,*,*,*> {
  preview (
    #if ($e._M_t._M_node_count <= 0) (
      #( (void*)(&$e), " [empty]" )
    ) #else (
      #( (void*)(&$e), " {size=", $e._M_t._M_node_count, "}" )
    )
  )
  children (
    #tree (
      head : $e._M_t._M_header._M_data->_M_parent,
      skip : $e._M_t._M_header._M_data,
      left : _M_left,
      right : _M_right,
      size : $e._M_t._M_node_count
    ) : *((_STL::_Rb_tree_node<_STL::pair<$T1 const ,$T2> >*)(&$e))
    ; there must be a space after "const" above!
  )
}

; STL iterators

_STL::_DBG_iter<_STL::__vector<*,*>,*> {
  preview (
    #if (!$e._M_owner || !$e._M_owner->_M_node._M_owner || !$e._M_iterator) (
      "[invalid]"
    ) #elif ($e._M_iterator >= ((_STL::vector<$T1,$T2>*)($e._M_owner->_M_node._M_owner))->_M_finish) (
      "[end]"
    ) #else (
      *$e._M_iterator
    )
  )
  children (
    #if ($e._M_owner && $e._M_owner->_M_node._M_owner && $e._M_iterator) (
      #(
        [index] : $e._M_iterator - ((_STL::vector<$T1,$T2>*)($e._M_owner->_M_node._M_owner))->_M_start,
        data : *$e._M_iterator,
        parent : (_STL::vector<$T1,$T2>*)($e._M_owner->_M_node._M_owner)
      )
    )
  )
}

_STL::reverse_iterator<_STL::_DBG_iter<_STL::__vector<*,*>,*> > {
  preview (
    #if (!$e.current._M_owner || !$e.current._M_owner->_M_node._M_owner || !$e.current._M_iterator) (
      "[invalid]"
    ) #elif ($e.current._M_iterator <= ((_STL::vector<$T1,$T2>*)($e.current._M_owner->_M_node._M_owner))->_M_start) (
      "[end]"
    ) #else (
      *($e.current._M_iterator-1)
    )
  )
  children (
    #if ($e.current._M_owner && $e.current._M_owner->_M_node._M_owner && $e.current._M_iterator) (
      #(
        [index] : ((_STL::vector<$T1,$T2>*)($e.current._M_owner->_M_node._M_owner))->_M_finish - $e.current._M_iterator,
        data : *($e.current._M_iterator - 1),
        parent : (_STL::vector<$T1,$T2>*)($e.current._M_owner->_M_node._M_owner)
      )
    )
  )
}

_STL::_DBG_iter<_STL::__deque<*,*>,*> {
  preview (
    #if (!$e._M_owner || !$e._M_owner->_M_node._M_owner || !$e._M_iterator._M_cur) (
      "[invalid]"
    ) #elif ($e._M_iterator._M_cur == ((_STL::deque<$T1,$T2>*)($e._M_owner->_M_node._M_owner))->_M_finish._M_cur) (
      "[end]"
    ) #else (
      *$e._M_iterator._M_cur
    )
  )
  children (
    #if ($e._M_owner && $e._M_owner->_M_node._M_owner && $e._M_iterator._M_cur) (
      #(
        data : *$e._M_iterator._M_cur,
        parent : (_STL::deque<$T1,$T2>*)($e._M_owner->_M_node._M_owner)
      )
    )
  )
}

_STL::reverse_iterator<_STL::_DBG_iter<_STL::__deque<*,*>,*> > {
  preview (
    #if (!$e.current._M_owner || !$e.current._M_owner->_M_node._M_owner || !$e.current._M_iterator._M_cur) (
      "[invalid]"
    ) #elif ($e.current._M_iterator._M_cur == ((_STL::deque<$T1,$T2>*)($e.current._M_owner->_M_node._M_owner))->_M_start._M_cur) (
      "[end]"
    ) #elif ($e.current._M_iterator._M_cur == $e.current._M_iterator._M_first) (
      ($e.current._M_iterator._M_node - 1)[ $e.current._M_iterator._M_last - $e.current._M_iterator._M_first - 1 ]
    ) #else (
      $e.current._M_iterator._M_cur[ -1 ]
    )
  )
  children (
    #if ($e.current._M_owner && $e.current._M_owner->_M_node._M_owner && $e.current._M_iterator._M_cur) (
      #if ($e.current._M_iterator._M_cur == $e.current._M_iterator._M_first) (
        #(
          data : ($e.current._M_iterator._M_node - 1)[ $e.current._M_iterator._M_last - $e.current._M_iterator._M_first - 1 ],
          parent : (_STL::deque<$T1,$T2>*)($e.current._M_owner->_M_node._M_owner)
        )
      ) #else (
        #(
          data : $e.current._M_iterator._M_cur[ -1 ],
          parent : (_STL::deque<$T1,$T2>*)($e.current._M_owner->_M_node._M_owner)
        )
      )
    )
  )
}

_STL::_DBG_iter<_STL::__list<*,*>,*> {
  preview (
    #if (!$e._M_owner || !$e._M_owner->_M_node._M_owner || !$e._M_iterator._M_node) (
      "[invalid]"
    ) #elif ($e._M_iterator._M_node == ((_STL::list<$T1,$T2>*)($e._M_owner->_M_node._M_owner))->_M_node._M_data) (
      "[end]"
    ) #else (
      ((_STL::_List_node<$T1>*)($e._M_iterator._M_node))->_M_data
    )
  )
  children (
    #if ($e._M_owner && $e._M_owner->_M_node._M_owner && $e._M_iterator._M_node) (
      #(
        data : ((_STL::_List_node<$T1>*)($e._M_iterator._M_node))->_M_data,
        parent : (_STL::list<$T1,$T2>*)($e._M_owner->_M_node._M_owner)
      )
    )
  )
}

_STL::reverse_iterator<_STL::_DBG_iter<_STL::__list<*,*>,*> > {
  preview (
    #if (!$e.current._M_owner || !$e.current._M_owner->_M_node._M_owner || !$e.current._M_iterator._M_node) (
      "[invalid]"
    ) #elif ($e.current._M_iterator._M_node->_M_prev == ((_STL::list<$T1,$T2>*)($e.current._M_owner->_M_node._M_owner))->_M_node._M_data) (
      "[end]"
    ) #else (
      ((_STL::_List_node<$T1>*)($e.current._M_iterator._M_node->_M_prev))->_M_data
    )
  )
  children (
    #if ($e.current._M_owner && $e.current._M_owner->_M_node._M_owner && $e.current._M_iterator._M_node) (
      #(
        data : ((_STL::_List_node<$T1>*)($e.current._M_iterator._M_node->_M_prev))->_M_data,
        parent : (_STL::list<$T1,$T2>*)($e.current._M_owner->_M_node._M_owner)
      )
    )
  )
}

_STL::_DBG_iter<_STL::__Rb_tree<*,_STL::pair<*,*>,*,*,*>,*> {
  preview (
    #if (!$e._M_owner || !$e._M_owner->_M_node._M_owner || !$e._M_iterator._M_node) (
      "[invalid]"
    ) #elif ($e._M_iterator._M_node == ((_STL::map<$T1,$T3,$T5,$T6>*)($e._M_owner->_M_node._M_owner))->_M_t._M_header._M_data) (
      "[end]"
    ) #else (
      #(
        "key=", ((_STL::_Rb_tree_node<_STL::pair<$T2,$T3> >*)($e._M_iterator._M_node))->_M_value_field.first,
        " data=", ((_STL::_Rb_tree_node<_STL::pair<$T2,$T3> >*)($e._M_iterator._M_node))->_M_value_field.second
      )
    )
  )
  children (
    #if ($e._M_owner && $e._M_owner->_M_node._M_owner && $e._M_iterator._M_node) (
      #(
        [key] : ((_STL::_Rb_tree_node<_STL::pair<$T2,$T3> >*)($e._M_iterator._M_node))->_M_value_field.first,
        data : ((_STL::_Rb_tree_node<_STL::pair<$T2,$T3> >*)($e._M_iterator._M_node))->_M_value_field.second,
        parent : (_STL::map<$T1,$T3,$T5,$T6>*)($e._M_owner->_M_node._M_owner)
      )
    )
  )
}

_STL::_DBG_iter<_STL::__Rb_tree<*,*,*,*,*>,*> {
  preview (
    #if (!$e._M_owner || !$e._M_owner->_M_node._M_owner || !$e._M_iterator._M_node) (
      "[invalid]"
    ) #elif ($e._M_iterator._M_node == ((_STL::set<$T2,$T4,$T5>*)($e._M_owner->_M_node._M_owner))->_M_t._M_header._M_data) (
      "[end]"
    ) #else (
      ((_STL::_Rb_tree_node<$T2>*)($e._M_iterator._M_node))->_M_value_field
    )
  )
  children (
    #if ($e._M_owner && $e._M_owner->_M_node._M_owner && $e._M_iterator._M_node) (
      #(
        data : ((_STL::_Rb_tree_node<$T2>*)($e._M_iterator._M_node))->_M_value_field,
        parent : (_STL::set<$T2,$T4,$T5>*)($e._M_owner->_M_node._M_owner)
      )
    )
  )
}

; UNO structures

com::sun::star::uno::Sequence<*> {
  preview (
    #if (!$e._pSequence || ($e._pSequence->nElements == 0)) (
      #( (void*)(&$e), " [empty]" )
    ) #else (
      #( (void*)(&$e), " {size=", $e._pSequence->nElements, "}" )
    )
  )
  children (
    #array (
      expr : (($T1*)($e._pSequence->elements))[$i],
      size : $e._pSequence->nElements
    )
  )
}

com::sun::star::uno::Any {
  preview (
    #(
      (void*)(&$e),
      #switch ((int)$e._uno_Any.pType->eTypeClass)
      #case 0 ( #( " <void>" ) )
      #case 2 ( #( " <sal_uInt8> {", *((sal_uInt8*)$e._uno_Any.pData), "}" ) )
      #case 3 ( #( " <sal_Int8> {", *((sal_Int8*)$e._uno_Any.pData), "}" ) )
      #case 4 ( #( " <sal_Int16> {", *((sal_Int16*)$e._uno_Any.pData), "}" ) )
      #case 6 ( #( " <sal_Int32> {", *((sal_Int32*)$e._uno_Any.pData), "}" ) )
      #case 7 ( #( " <sal_uInt32> {", *((sal_uInt32*)$e._uno_Any.pData), "}" ) )
      #case 8 ( #( " <sal_Int64> {", *((sal_Int64*)$e._uno_Any.pData), "}" ) )
      #case 9 ( #( " <sal_uInt64> {", *((sal_uInt64*)$e._uno_Any.pData), "}" ) )
      #case 10 ( #( " <float> {", *((float*)$e._uno_Any.pData), "}" ) )
      #case 11 ( #( " <double> {", *((double*)$e._uno_Any.pData), "}" ) )
      #case 12 ( #( " <OUString> {", *((rtl::OUString*)$e._uno_Any.pData), "}" ) )
      #case 15 ( #( " <", [$e._uno_Any.pType->pTypeName->buffer,su], "> {", *((sal_Int32*)$e._uno_Any.pData), "}" ) )
      #case 17 ( #( " <", [$e._uno_Any.pType->pTypeName->buffer,su], ">" ) )
      #case 20 ( #( " <", [$e._uno_Any.pType->pTypeName->buffer,su], ">" ) )
      #case 22 ( #( " <", [$e._uno_Any.pType->pTypeName->buffer,su], ">" ) )
    )
  )
  children (
    #(
      [raw] : [$e,!],
      #switch ((int)$e._uno_Any.pType->eTypeClass)
      #case 2 ( #( data : *((sal_uInt8*)$e._uno_Any.pData) ) )
      #case 3 ( #( data : *((sal_Int8*)$e._uno_Any.pData) ) )
      #case 4 ( #( data : *((sal_Int16*)$e._uno_Any.pData) ) )
      #case 6 ( #( data : *((sal_Int32*)$e._uno_Any.pData) ) )
      #case 7 ( #( data : *((sal_uInt32*)$e._uno_Any.pData) ) )
      #case 8 ( #( data : *((sal_Int64*)$e._uno_Any.pData) ) )
      #case 9 ( #( data : *((sal_uInt64*)$e._uno_Any.pData) ) )
      #case 10 ( #( data : *((float*)$e._uno_Any.pData) ) )
      #case 11 ( #( data : *((double*)$e._uno_Any.pData) ) )
      #case 12 ( #( data : *((rtl::OUString*)$e._uno_Any.pData) ) )
      #case 15 ( #( data : *((sal_Int32*)$e._uno_Any.pData) ) )
    )
  )
}
Personal tools