{"id":43,"date":"2009-07-21T22:51:21","date_gmt":"2009-07-22T03:51:21","guid":{"rendered":"http:\/\/developer.casgrain.com\/?p=43"},"modified":"2009-07-21T22:51:23","modified_gmt":"2009-07-22T03:51:23","slug":"display-stdwstring-in-xcode-using-a-data-formatter","status":"publish","type":"post","link":"http:\/\/developer.casgrain.com\/?p=43","title":{"rendered":"Display std::wstring in Xcode using a Data Formatter"},"content":{"rendered":"<h2><code>std::wstring<\/code>: <a href=\"http:\/\/www.losingfight.com\/blog\/2006\/07\/28\/wchar_t-unsafe-at-any-size\/\">unsafe<\/a>, but sometimes necessary<\/h2>\n<p>When dealing with cross-platform code, especially Windows, it is not uncommon to encounter <code>wchar_t<\/code> and its companion string class, <code>std::wstring<\/code>.<\/p>\n<p>\nUnfortunately, Xcode does not display these types natively. Yes, you can <a href=\"http:\/\/www.yolinux.com\/TUTORIALS\/src\/dbinit_stl_views-1.01.txt\">add this file to your <code>.gdbinit<\/code><\/a> file and then you will be able to type:<\/p>\n<p><pre>\n    pwstring mystring\n<\/pre>\n<p>\nbut what you really want is for the values to show up in Xcode&#8217;s variable display, and in tooltips.<br \/>\n<br \/>\nWhat you need is called a <a href=\"http:\/\/developer.apple.com\/documentation\/developertools\/Conceptual\/XcodeDebugging\/600-Viewing_Variables_and_Memory\/variables_and_memory.html#\/\/apple_ref\/doc\/uid\/TP40007057-CH9-SW24\">Custom Data Formatter<\/a>.<\/p>\n<p>\nIn this post, I will adapt Apple&#8217;s sample <code>wchar_t<\/code> data formatter and modify it to display <code>std::wstring<\/code> variables. I will also explain where you should put this formatter in Xcode 3.1.<br \/>\n<br \/>\nComplete source code is available on <a href=\"http:\/\/bitbucket.org\/philippec\/wchardataformatter\/\">bitbucket.org<\/a>, with a MIT license.<\/p>\n<h2>Initial Data Formatter<\/h2>\n<p>Xcode Data Formatters are simple <a href=\"http:\/\/developer.apple.com\/documentation\/CoreFoundation\/Conceptual\/CFBundles\/CFBundles.html\">bundles<\/a> that are loaded by Xcode at startup. They are essentially plug-ins to extend Xcode.<\/p>\n<p>\nStarting with Apple&#8217;s own <a href=\"http:\/\/developer.apple.com\/samplecode\/WcharDataFormatter\/\">wchar_t Data Formatter sample<\/a>, we immediately notice that:<\/p>\n<ul>\n<li>This sample is quite outdated, almost 4 years old (the Release build actually builds only PPC!)\n<li>It won&#8217;t work as-is with <code>std::wstring<\/code> since it only contains .c files.\n<\/ul>\n<p>We will update this sample to work with <code>std::wstring<\/code> and build it as a 4-way universal binary.<\/p>\n<h2>Modernizing the Data Formatter<\/h2>\n<h3>Switching to C++<\/h3>\n<p>Since the data formatter will use <code>std::wstring<\/code>, we need to build it using C++. Just rename all the .c files to .cpp and voil\u00e0!<\/p>\n<h3>Modify CustomDataViews.plist<\/h3>\n<p>If you open CustomDataViews.plist, you will see that it has one entry per variable type that the formatter can handle. That entry contains a Data Formatter, much like the one you would type in Xcode itself (for example, to display the name of a notification\u2014of type NSNotification\u2014you can use <code>{(NSString *)[$VAR name]}<\/code>). <br \/>\nWhat is different here is the formatter contains a string that calls back in our custom Data Formatter: for example, <code>wchar_t<\/code> corresponds to <code>{(char *)myWCharDataFormatter((wchar_t) $VAR, (int) $ID)}:s<\/code>. <br \/>\nAdd two entries to that plist, for types <code>wstring<\/code> and <code>wstring*<\/code>, and replace the callback strings with a new unique string, for instance <code>myWStringDataFormatter<\/code> and <code>myWStringPointerDataFormatter<\/code>. Watch for capitalization, case matters.<\/p>\n<h3>Add new callback functions<\/h3>\n<p>Now add the two callback functions you referenced in the plist in <code>myCustomFormatter.cpp<\/code>:<\/p>\n<pre>\n#include &lt;string&gt;\n\nchar * myWStringDataFormatter(std::wstring wstr, int identifier)\n{\n\tsize_t bufLen = wstr.size() + 1; \n\treturn dataformatter_char_for_wchar(wstr.data(), identifier, bufLen);\n}\n\nchar * myWStringPointerDataFormatter(std::wstring *wstr, int identifier)\n{\n\tsize_t bufLen = wstr->size() + 1; \n\treturn dataformatter_char_for_wchar(wstr->data(), identifier, bufLen);\n}\n<\/pre>\n<p>As you can see, we are re-using the preexisting <code>wchar_t<\/code> code with our <code>std::wstring<\/code>.<\/p>\n<h3>Build a 4-way Universal Binary<\/h3>\n<p>Double-click the wchardataformatter project icon to bring up the Project Inspector. Select the Release configuration, and click the &#8220;Architectures&#8221; pop-up menu. Select 32\/64 bit universal, as shown below.<\/p>\n<p>\n<img decoding=\"async\" src=\"\/images\/wchardataformatter_universal.png\"  hspace=\"4\" vspace=\"8\" alt=\"Universal Architecture in Xcode\"><\/p>\n<h3>Modify the Test Code<\/h3>\n<p>Finally, update <code>wcharTest_main.cpp<\/code> to add new <code>std::wstring<\/code> variables to display in the debugger:<\/p>\n<pre>\n#include &lt;stdlib.h&gt;\n#include &lt;wchar.h&gt;\n#include &lt;string&gt;\n\nint main(int argc, char *argv[])\n{\n\twchar_t c = 'A';\n\twchar_t b[255];\n\twchar_t *d = &b[0];\n\tchar *a = \"a b c d e f g\";\n\tmbstowcs(d, a , strlen(a));\n\tstd::wstring s = L\"wide string\";\n\tstd::wstring *ps = &s;\n\treturn 0;\n}\n<\/pre>\n<p>Switch the target to <em>wCharTest<\/em> in Xcode, set a breakpoint on the last line, and hit &#8220;Build and Go&#8221;. Xcode should build the test application and stop in the Debugger. Since you have not installed the formatter, you should not see anything special in the Variable Display window.<\/p>\n<h2>Installing the Data Formatter<\/h2>\n<p>Build the Data Formatter (Debug or Release). Locate the bundle by control-clicking on the &#8220;Products \/ wcharDataFormatter.bundle&#8221; in the Xcode project.<br \/>\nDrag the bundle to this folder: <code>~\/Library\/Application\\ Support\/Developer\/Shared\/Xcode\/CustomDataViews<\/code>, creating intermediate folders along the way if they do not exist.<br \/>\nYou can remove the ~ to install for all users (not just you), and you can also replace &#8220;Shared&#8221; in the path with &#8220;3.0&#8221; or &#8220;3.1&#8221; if you only wanted to install the formatter for Xcode 3.0 or 3.1.<\/p>\n<h2>Testing the Formatter<\/h2>\n<p>Build the <em>wcharTest<\/em> target, and set a breakpoint in the main() function of wcharTest_main.cpp. You can step over each line, and you should see your data formatter being called and displaying in Xcode&#8217;s Variable Display, as well as in tooltips (Xcode 3.1 and later).<\/p>\n<p><img decoding=\"async\" align=\"center\" src=\"\/images\/wchardataformatter_display.png\" hspace=\"4\" vspace=\"8\" alt=\"Formatter Display in Xcode\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>std::wstring: unsafe, but sometimes necessary When dealing with cross-platform code, especially Windows, it is not uncommon to encounter wchar_t and its companion string class, std::wstring. Unfortunately, Xcode does not display these types natively. Yes, you can add this file to your .gdbinit file and then you will be able to type: pwstring mystring but what [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1,5],"tags":[],"class_list":["post-43","post","type-post","status-publish","format-standard","hentry","category-development","category-macosx"],"_links":{"self":[{"href":"http:\/\/developer.casgrain.com\/index.php?rest_route=\/wp\/v2\/posts\/43","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/developer.casgrain.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/developer.casgrain.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/developer.casgrain.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/developer.casgrain.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=43"}],"version-history":[{"count":1,"href":"http:\/\/developer.casgrain.com\/index.php?rest_route=\/wp\/v2\/posts\/43\/revisions"}],"predecessor-version":[{"id":44,"href":"http:\/\/developer.casgrain.com\/index.php?rest_route=\/wp\/v2\/posts\/43\/revisions\/44"}],"wp:attachment":[{"href":"http:\/\/developer.casgrain.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=43"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/developer.casgrain.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=43"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/developer.casgrain.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=43"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}