EASprintf.html 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  2. <html>
  3. <head>
  4. <meta http-equiv="content-type"
  5. content="text/html; charset=ISO-8859-1">
  6. <title>EASprintf</title>
  7. <link type="text/css" rel="stylesheet"
  8. href="UTFDoc.css">
  9. <meta name="author" content="Paul Pedriana">
  10. </head>
  11. <body style="background-color: rgb(255, 255, 255);">
  12. <h1>EASprintf</h1>
  13. <h2>Introduction</h2>
  14. <p>EAStdC provides a portable
  15. version of the C printf family of functions which improves on
  16. the C family in the following ways:</p>
  17. <ul>
  18. <li>Behaves identically on all
  19. platforms</li>
  20. <li>Provides the full gamut of
  21. printf functions, including vsnprintf</li>
  22. <li>Is more efficient; executes 20-80% faster. </li>
  23. <li>Never allocates memory</li>
  24. <li>Provides both 8 and 16 bit
  25. versions for all platforms</li>
  26. <li>Provides&nbsp;useful
  27. extended functionality</li>
  28. <li>Complies with the C99
  29. standard (except for the %a format, as of this writing)</li>
  30. <li>Is readable enough to be
  31. traced/debugged by non-experts</li>
  32. <li>Is savvy to UTF8 Unicode</li>
  33. </ul>
  34. <p>The primary disadvantages of
  35. EAStdC's printf are:</p>
  36. <ul>
  37. <li>It doesn't use
  38. locale-specific formatting</li>
  39. <li>It isn't part of the C/C++
  40. standard library</li>
  41. </ul>
  42. <p>EAStdC doesn't attempt to
  43. solve the locale formatting problem because users really are better off
  44. using serious locale libraries for such things rather than using the
  45. meager support provided by the C standard library. The EALocale library
  46. attempts to provide such functionality.</p>
  47. <p>EAStdC provides the
  48. following functions in 8, 16, and 32 bit versions:
  49. </p>
  50. <pre><span class="code-example">int Cprintf(WriteFunction8 pWriteFunction, void* pContext, const char8_t* pFormat, ...);
  51. int Fprintf(FILE* pFile, const char8_t* pFormat, ...);
  52. int Printf(const char8_t* pFormat, ...);
  53. int Sprintf(char8_t* pDestination, const char8_t* pFormat, ...);
  54. int Snprintf(char8_t* pDestination, size_t n, const char8_t* pFormat, ...);
  55. int Vcprintf(WriteFunction8 pWriteFunction8, void* pContext, const char8_t* pFormat, va_list arguments);
  56. int Vfprintf(FILE* pFile, const char8_t* pFormat, va_list arguments);
  57. int Vprintf(const char8_t* pFormat, va_list arguments);
  58. int Vsprintf(char8_t* pDestination, const char8_t* pFormat, va_list arguments);
  59. int Vsnprintf(char8_t* pDestination, size_t n, const char8_t* pFormat, va_list arguments);<br>int Vscprintf(const char8_t* EA_RESTRICT pFormat, va_list arguments);</span></pre>
  60. <p>Also there are:</p>
  61. <pre class="code-example">template &lt;typename String&gt;
  62. int StringPrintf(String&amp; s, const typename String::value_type* EA_RESTRICT pFormat, ...);</pre>
  63. <pre class="code-example">template &lt;typename String&gt;
  64. int StringVcprintf(String&amp; s, const typename String::value_type* EA_RESTRICT pFormat, va_list arguments);</pre>
  65. <blockquote></blockquote>
  66. <h2>Snprintf uses C99 behavior</h2>
  67. <p> The EASprintf 'n' functions (Snprintf and Vsnprintf) follow the C99 standard
  68. for return value, which is different from some C standard library implementations
  69. such as VC++. These functions return the number of characters that would have
  70. been written had n been sufficiently large, not counting the terminating null
  71. character, or a negative value if an encoding error occurred. Thus, the null-terminated
  72. output has been completely written if and only if the returned value is nonnegative
  73. and less than n. Another way of saying it is that the return value equal to
  74. the strlen of the intended output. See the examples below.</p>
  75. <h2>Watch out for common mistakes and security problems</h2>
  76. <p> The sprintf family of functions are very convenient but offer numerous opportunities
  77. for incorrect usage and security problems. Here is a list of some of the most
  78. common issues.</p>
  79. <ul>
  80. <li>Don't use sprintf unless you are absolutely certain the result will fit
  81. into the output buffer. Instead use snprintf.</li>
  82. <li>When printing a string, always use <font face="Courier New, Courier, mono" size="-1">printf(&quot;%s&quot;,
  83. pStr)</font> and never <font face="Courier New, Courier, mono" size="-1">printf(pStr)</font>,
  84. as the latter may have formatting characters in it.</li>
  85. <li>Watch out for platform differences between format types. For example, %u
  86. means unsigned int, and you can't use a size_t argument with it on 64 bit
  87. platforms. Instead, explicitly cast your arguments to the expected type or
  88. use the EASprintf extended format types (see below).</li>
  89. <li>Similarly, watch out when passing int8_t and int16_t arguments to EAPrintf
  90. (and regular printf), as the compiler will promote them to int and they might
  91. not print as you expected, depending on your output format.</li>
  92. <li>Watch out for EASprintf's C99 behaviour. C99 behaviour is standard C and
  93. is superior to previous C library behaviour, but the previous behaviour exists
  94. in the C library today with compilers such as VC++. This behaviour affects
  95. the return value of Snprintf/Vsnprintf, and affects the way some format specifiers
  96. are rendered.</li>
  97. </ul>
  98. <h2>Extended Functionality</h2>
  99. <p> Printf provides extended
  100. format functionality not found in the C99 standard but which is useful
  101. nevertheless:</p>
  102. <table style="text-align: left; width: 100%;" border="1" cellpadding="2"
  103. cellspacing="2">
  104. <tbody>
  105. <tr style="font-weight: bold;">
  106. <td>Format/modifier</td>
  107. <td>Description</td>
  108. <td>Example</td>
  109. <td>Example output</td>
  110. </tr>
  111. <tr style="font-weight: bold;">
  112. <td><span style="font-weight: normal;">b</span></td>
  113. <td style="font-weight: normal;">Binary
  114. output field type (joins d, i, x, o, etc.).</td>
  115. <td><span class="code-example-span">printf("0b%b", 255);<br>
  116. printf<span style="font-weight: normal;">("%<span style="font-weight: normal;"><span style="font-weight: normal;">#</span></span>b", 255);</span></span> <span class="code-example-span"><br>
  117. <span style="font-weight: normal;">printf<span style="font-weight: normal;">("%<span style="font-weight: normal;"><span style="font-weight: normal;">#</span></span>B", 255);</span> </span></span> </td>
  118. <td><span class="code-example-span">0b11111111<br>
  119. <span style="font-weight: normal;">0b11111111</span></span> <span class="code-example-span"><br>
  120. <span style="font-weight: normal;"><span style="font-weight: normal;">0B11111111</span> </span></span></td>
  121. </tr>
  122. <tr>
  123. <td>I8</td>
  124. <td>8 bit integer field
  125. modifier.</td>
  126. <td class="code-example-span">printf("%I8d", 0xff);</td>
  127. <td class="code-example-span">-1</td>
  128. </tr>
  129. <tr>
  130. <td>I16</td>
  131. <td>16 bit integer field
  132. modifier.</td>
  133. <td class="code-example-span">printf("%I16u", 0xffff);</td>
  134. <td class="code-example-span">65535</td>
  135. </tr>
  136. <tr>
  137. <td>I32</td>
  138. <td>32 bit integer field
  139. modifier.</td>
  140. <td class="code-example-span">printf("%I32d",
  141. 0xffffffff);</td>
  142. <td class="code-example-span">-1</td>
  143. </tr>
  144. <tr>
  145. <td>I64</td>
  146. <td>64 bit integer field
  147. modifier.</td>
  148. <td class="code-example-span">printf("%I64u",
  149. 0xffffffffffffffff);</td>
  150. <td class="code-example-span">18446744073709551615</td>
  151. </tr>
  152. <tr>
  153. <td>I128</td>
  154. <td>128 bit integer field
  155. modifier.</td>
  156. <td class="code-example-span">printf("%I128d",
  157. 0xffffffffffffffffffffffffffffffff);</td>
  158. <td class="code-example-span">-1</td>
  159. </tr>
  160. <tr>
  161. <td>'</td>
  162. <td>Display a thousands separator.</td>
  163. <td class="code-example-span">printf("%'I16u", 0xffff);</td>
  164. <td class="code-example-span">65,535</td>
  165. </tr>
  166. </tbody>
  167. </table>
  168. <h2>SprintfOrdered</h2>
  169. <p>EAStdC also provides an ordered sprintf</p>
  170. <p>Ordered printf is like printf except it works on &quot;ordered&quot; printf specifiers. This means that instead of using &quot;%4d %f&quot; we give an order to the arguments via an index and colon, as with &quot;%1:4d %2:f&quot;. The point, however, is that you can reorder the indexes, as with &quot;%2:f %1:4d&quot;. This is particularly useful for formatted string localization, as different locales use subjects and verbs in different orders.<br>
  171. <br>
  172. User indexes can start at either 0 or 1. Oprintf detects which is in use as it goes. So the following have identical effect:</p>
  173. <pre class="code-example">OPrintf(&quot;%1:s&quot; %0:f&quot;, 3.0, &quot;hello&quot;);
  174. OPrintf(&quot;%2:s&quot; %1:f&quot;, 3.0, &quot;hello&quot;);</pre>
  175. <p> // User indexes must be contiguous and the behaviour of Oprintf is undefined<br>
  176. // if the ordering is non-contiguous. There are debug checks to validate <br>
  177. // contiguity, so debug tests should catch mistakes. The following is an <br>
  178. // example of non-contiguous ordering, as it is missing a &quot;3:&quot; format:<br>
  179. // OPrintf(&quot;%1:d&quot; %0:d %3:d&quot;, 17, 18, 19, 20);<br>
  180. </p>
  181. <p>Example usage:</p>
  182. <pre><span class="code-example">char16_t buffer[80];</span></pre>
  183. <p>// The module provides ordered versions of the printf family of functions:<br>
  184. // int OCprintf(WriteFunction pFunction, void* pContext, const char_t* pFormat, ...);<br>
  185. // int OFprintf(FILE* pFile, const char_t* pFormat, ...);<br>
  186. // int OPrintf(cconst char_t* pFormat, ...);<br>
  187. // int OSprintf(char_t* pDestination, const char_t* pFormat, ...);<br>
  188. // int OSnprintf(char_t* pDestination, size_t n, const char_t* pFormat, ...);<br>
  189. //<br>
  190. // int OVcprintf(WriteFunction pFunction, void* pContext, const char_t* pFormat, va_list arguments);<br>
  191. // int OVfprintf(FILE* pFile, const char_t* pFormat, va_list arguments);<br>
  192. // int OVprintf(const char_t* pFormat, va_list arguments);<br>
  193. // int OVsprintf(char_t* pDestination, const char_t* pFormat, va_list arguments);<br>
  194. // int OVsnprintf(char_t* pDestination, size_t n, const char_t* pFormat, va_list arguments);<br>
  195. // int OVscprintf(const char* pFormat, va_list arguments);<br>
  196. //<br>
  197. // Ordered printf is like printf except it works on &quot;ordered&quot; printf specifiers.<br>
  198. // This means that instead of using &quot;%4d %f&quot; we give an order to the arguments via <br>
  199. // an index and colon, as with &quot;%1:4d %2:f&quot;. The point, however, is that you can <br>
  200. // reorder the indexes, as with &quot;%2:f %1:4d&quot;. This is particularly useful for <br>
  201. // formatted string localization, as different locales use subjects and verbs<br>
  202. // in different orders.<br>
  203. //<br>
  204. // User indexes can start at either 0 or 1. Oprintf detects which is in use as <br>
  205. // it goes. So the following have identical effect:<br>
  206. // OPrintf(&quot;%1:s&quot; %0:f&quot;, 3.0, &quot;hello&quot;);<br>
  207. // OPrintf(&quot;%2:s&quot; %1:f&quot;, 3.0, &quot;hello&quot;);<br>
  208. //<br>
  209. // User indexes must be contiguous and the behaviour of Oprintf is undefined<br>
  210. // if the ordering is non-contiguous. There are debug checks to validate <br>
  211. // contiguity, so debug tests should catch mistakes. The following is an <br>
  212. // example of non-contiguous ordering, as it is missing a &quot;3:&quot; format:<br>
  213. // OPrintf(&quot;%1:d&quot; %0:d %3:d&quot;, 17, 18, 19, 20);<br>
  214. /////////////////////////////////////////////////////////////////////////////<br>
  215. </p>
  216. <h2>Example usage</h2>
  217. <p>All examples presume the #include of EASprintf.h.</p>
  218. <p>Snprintf usage:</p>
  219. <pre><span class="code-example">char16_t buffer[80];
  220. int nStrlen = Snprintf16(buffer, 80, &quot;Columbus arrived in %d.&quot;, 1492);
  221. if((unsigned)nStrlen &lt; 80) // Cast to unsigned in order to make any negative values be positive and &gt; 80.
  222. puts(&quot;success&quot;);</span></pre>
  223. <p>How to write a function that takes variable arguments (e.g. ...) and passes
  224. them to EASprintf:</p>
  225. <pre><span class="code-example">#include &lt;stdarg.h&gt;
  226. void CustomFormattedOutput(const char* pFormat, ...)
  227. {
  228. va_list arguments;
  229. va_start(arguments, pFormat);
  230. Vprintf8(pFormat, arguments);
  231. va_end(arguments);
  232. }</span></pre>
  233. <p>How to write a function that does custom formatted output to a buffer that
  234. is resized as needed for it. This is useful for the implementation of fail-safe
  235. utility functions and for debug tracing systems, among other things.</p>
  236. <pre><span class="code-example">#include &lt;stdarg.h&gt;
  237. #include &lt;string&gt;
  238. <span class="code-example-comment">// This is a generic function for doing a sprintf into a C++ std::string object.
  239. // If the string object lacks enough space for the output, then the string will
  240. // be resized to exactly fit the output.
  241. </span>size_t StringSprintf(std::string&amp; s, const char* pFormat, ...)
  242. {
  243. va_list arguments;
  244. va_start(arguments, pFormat);
  245. if(s.size() &lt; s.capacity())
  246. s.resize(s.capacity());
  247. const int nStrlen = Vsnprintf8(const_cast&lt;char*&gt;(s.data()), s.capacity() + 1, pFormat, arguments);
  248. va_end(arguments);
  249. if(nStrlen &gt; (int)s.size())
  250. {
  251. s.resize(nStrlen);
  252. Vsnprintf8(const_cast&lt;char*&gt;(s.data()), s.capacity() + 1, pFormat, arguments);
  253. return (size_t)nStrlen;
  254. }</span></pre>
  255. <p>Write to the C stderr stream:</p>
  256. <pre><span class="code-example">#include &lt;stdio.h&gt;
  257. Fprintf8(stderr, &quot;Columbus arrived in %d.&quot;, 1492);</span></pre>
  258. <p>Vsscanf usage. A complete discussion of the ins and outs of vsscanf are currently
  259. beyond the scope of this document. The scanf found in EAPrintf acts the same
  260. as with the C++ standard, so you can read about that elsewhere for the time
  261. being.</p>
  262. <pre><span class="code-example">char16_t buffer[64] = EAText16(&quot;Columbus arrived in 1492&quot;);
  263. int year;
  264. Vsscanf16(buffer, &quot;Columbus arrived in %d.&quot;, &amp;year);</span></pre>
  265. <h2>Interface</h2>
  266. <p>Printf family</p>
  267. <pre><span class="code-example">int Fprintf8(FILE* pFile, const char8_t* pFormat, ...);<br>int Printf8(const char8_t* pFormat, ...);<br>int Sprintf8(char8_t* pDestination, const char8_t* pFormat, ...);<br>int Snprintf8(char8_t* pDestination, size_t n, const char8_t* pFormat, ...);<br><br>int Fprintf16(FILE* pFile, const char16_t* pFormat, ...);<br>int Printf16(const char16_t* pFormat, ...);<br>int Sprintf16(char16_t* pDestination, const char16_t* pFormat, ...);<br>int Snprintf16(char16_t* pDestination, size_t n, const char16_t* pFormat, ...);<br></span></pre>
  268. <p>Vprintf family</p>
  269. <pre><span class="code-example"><span class="code-example-comment">/// Note that vsnprintf was not added to the C standard until C99.<br>/// Here we follow the C99 standard and have the return value of vsnprintf <br>/// return the number of required characters to complete the formatted string.<br>/// This is more useful than the way some libraries implement vsnprintf by <br>/// returning -1 if there isn't enough space. The return value is -1 if there <br>/// was an "encoding error" or the implementation was unable to return a <br>/// value &gt; n upon lack of sufficient space as per the C99 standard.<br>///<br>/// Specification:<br>/// The vsnprintf function is equivalent to snprintf, with the variable <br>/// argument list replaced by arguments, which shall have been initialized <br>/// by the va_start macro (and possibly subsequent va_arg calls). <br>/// The vsnprintf function does not invoke the va_end macro. If copying <br>/// takes place between objects that overlap, the behavior is undefined.<br>///<br>/// The vsnprintf function returns the number of characters that would <br>/// have been written had n been sufficiently large, not counting the <br>/// terminating null character, or a neg ative value if an encoding error <br>/// occurred. Thus, the null-terminated output has been completely written <br>/// if and only if the returned value is nonnegative and less than n.<br>///<br></span>int Vfprintf8(FILE* pFile, const char8_t* pFormat, va_list arguments);<br>int Vprintf8(const char8_t* pFormat, va_list arguments);<br>int Vsprintf8(char8_t* pDestination, const char8_t* pFormat, va_list arguments);<br>int Vsnprintf8(char8_t* pDestination, size_t n, const char8_t* pFormat, va_list arguments);<br><br>int Vfprintf16(FILE* pFile, const char16_t* pFormat, va_list arguments);<br>int Vprintf16(const char16_t* pFormat, va_list arguments);<br>int Vsprintf16(char16_t* pDestination, const char16_t* pFormat, va_list arguments);<br>int Vsnprintf16(char16_t* pDestination, size_t n, const char16_t* pFormat, va_list arguments);<br></span><br>
  270. </pre>
  271. <hr>
  272. <p>&nbsp;</p>
  273. <p>&nbsp;</p>
  274. <p>&nbsp;</p>
  275. <p>&nbsp;</p>
  276. <p>&nbsp;</p>
  277. <p>&nbsp;</p>
  278. <p>&nbsp;</p>
  279. <p>&nbsp;</p>
  280. <p>&nbsp;</p>
  281. <p>&nbsp;</p>
  282. <p>&nbsp;</p>
  283. <p>&nbsp;</p>
  284. <p>&nbsp;</p>
  285. <p> </p>
  286. </body>
  287. </html>