summaryrefslogtreecommitdiffstats
path: root/www/printf.html
diff options
context:
space:
mode:
Diffstat (limited to 'www/printf.html')
-rw-r--r--www/printf.html564
1 files changed, 564 insertions, 0 deletions
diff --git a/www/printf.html b/www/printf.html
new file mode 100644
index 0000000..f5f8802
--- /dev/null
+++ b/www/printf.html
@@ -0,0 +1,564 @@
+<!DOCTYPE html>
+<html><head>
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<link href="sqlite.css" rel="stylesheet">
+<title>SQLite's Built-in printf()</title>
+<!-- path= -->
+</head>
+<body>
+<div class=nosearch>
+<a href="index.html">
+<img class="logo" src="images/sqlite370_banner.gif" alt="SQLite" border="0">
+</a>
+<div><!-- IE hack to prevent disappearing logo --></div>
+<div class="tagline desktoponly">
+Small. Fast. Reliable.<br>Choose any three.
+</div>
+<div class="menu mainmenu">
+<ul>
+<li><a href="index.html">Home</a>
+<li class='mobileonly'><a href="javascript:void(0)" onclick='toggle_div("submenu")'>Menu</a>
+<li class='wideonly'><a href='about.html'>About</a>
+<li class='desktoponly'><a href="docs.html">Documentation</a>
+<li class='desktoponly'><a href="download.html">Download</a>
+<li class='wideonly'><a href='copyright.html'>License</a>
+<li class='desktoponly'><a href="support.html">Support</a>
+<li class='desktoponly'><a href="prosupport.html">Purchase</a>
+<li class='search' id='search_menubutton'>
+<a href="javascript:void(0)" onclick='toggle_search()'>Search</a>
+</ul>
+</div>
+<div class="menu submenu" id="submenu">
+<ul>
+<li><a href='about.html'>About</a>
+<li><a href='docs.html'>Documentation</a>
+<li><a href='download.html'>Download</a>
+<li><a href='support.html'>Support</a>
+<li><a href='prosupport.html'>Purchase</a>
+</ul>
+</div>
+<div class="searchmenu" id="searchmenu">
+<form method="GET" action="search">
+<select name="s" id="searchtype">
+<option value="d">Search Documentation</option>
+<option value="c">Search Changelog</option>
+</select>
+<input type="text" name="q" id="searchbox" value="">
+<input type="submit" value="Go">
+</form>
+</div>
+</div>
+<script>
+function toggle_div(nm) {
+var w = document.getElementById(nm);
+if( w.style.display=="block" ){
+w.style.display = "none";
+}else{
+w.style.display = "block";
+}
+}
+function toggle_search() {
+var w = document.getElementById("searchmenu");
+if( w.style.display=="block" ){
+w.style.display = "none";
+} else {
+w.style.display = "block";
+setTimeout(function(){
+document.getElementById("searchbox").focus()
+}, 30);
+}
+}
+function div_off(nm){document.getElementById(nm).style.display="none";}
+window.onbeforeunload = function(e){div_off("submenu");}
+/* Disable the Search feature if we are not operating from CGI, since */
+/* Search is accomplished using CGI and will not work without it. */
+if( !location.origin || !location.origin.match || !location.origin.match(/http/) ){
+document.getElementById("search_menubutton").style.display = "none";
+}
+/* Used by the Hide/Show button beside syntax diagrams, to toggle the */
+function hideorshow(btn,obj){
+var x = document.getElementById(obj);
+var b = document.getElementById(btn);
+if( x.style.display!='none' ){
+x.style.display = 'none';
+b.innerHTML='show';
+}else{
+x.style.display = '';
+b.innerHTML='hide';
+}
+return false;
+}
+var antiRobot = 0;
+function antiRobotGo(){
+if( antiRobot!=3 ) return;
+antiRobot = 7;
+var j = document.getElementById("mtimelink");
+if(j && j.hasAttribute("data-href")) j.href=j.getAttribute("data-href");
+}
+function antiRobotDefense(){
+document.body.onmousedown=function(){
+antiRobot |= 2;
+antiRobotGo();
+document.body.onmousedown=null;
+}
+document.body.onmousemove=function(){
+antiRobot |= 2;
+antiRobotGo();
+document.body.onmousemove=null;
+}
+setTimeout(function(){
+antiRobot |= 1;
+antiRobotGo();
+}, 100)
+antiRobotGo();
+}
+antiRobotDefense();
+</script>
+<div class=fancy>
+<div class=nosearch>
+<div class="fancy_title">
+SQLite's Built-in printf()
+</div>
+<div class="fancy_toc">
+<a onclick="toggle_toc()">
+<span class="fancy_toc_mark" id="toc_mk">&#x25ba;</span>
+Table Of Contents
+</a>
+<div id="toc_sub"><div class="fancy-toc1"><a href="#overview">1. Overview</a></div>
+<div class="fancy-toc2"><a href="#advantages">1.1. Advantages</a></div>
+<div class="fancy-toc2"><a href="#disadvantages">1.2. Disadvantages</a></div>
+<div class="fancy-toc1"><a href="#formatting_details">2. Formatting Details</a></div>
+<div class="fancy-toc2"><a href="#substitution_types">2.1. Substitution Types</a></div>
+<div class="fancy-toc2"><a href="#the_optional_length_field">2.2. The Optional Length Field</a></div>
+<div class="fancy-toc2"><a href="#the_optional_width_field">2.3. The Optional Width Field</a></div>
+<div class="fancy-toc2"><a href="#the_optional_precision_field">2.4. The Optional Precision Field</a></div>
+<div class="fancy-toc2"><a href="#the_options_flags_field">2.5. The Options Flags Field</a></div>
+<div class="fancy-toc1"><a href="#implementation_and_history">3. Implementation And History</a></div>
+</div>
+</div>
+<script>
+function toggle_toc(){
+var sub = document.getElementById("toc_sub")
+var mk = document.getElementById("toc_mk")
+if( sub.style.display!="block" ){
+sub.style.display = "block";
+mk.innerHTML = "&#x25bc;";
+} else {
+sub.style.display = "none";
+mk.innerHTML = "&#x25ba;";
+}
+}
+</script>
+</div>
+
+
+
+
+<h1 id="overview"><span>1. </span>Overview</h1>
+
+<p>SQLite contains its own implementation of the string formatting routine "printf()",
+accessible via the following interfaces:
+
+</p><ul>
+<li> <a href="lang_corefunc.html#format">format()</a> &rarr; an SQL function returning the formatted string
+</li><li> <a href="c3ref/mprintf.html">sqlite3_mprintf()</a> &rarr; Store the formatted string in memory obtained
+ <a href="c3ref/free.html">sqlite3_malloc64()</a>.
+</li><li> <a href="c3ref/mprintf.html">sqlite3_snprintf()</a> &rarr; Store the formatted string in a static buffer
+</li><li> <a href="c3ref/str_append.html">sqlite3_str_appendf()</a> &rarr; Append formatted text to a dynamic string
+</li><li> <a href="c3ref/mprintf.html">sqlite3_vmprintf()</a> &rarr; Varargs version of sqlite3_mprintf()
+</li><li> <a href="c3ref/mprintf.html">sqlite3_vsnprintf()</a> &rarr; Varargs version of sqlite3_snprintf()
+</li><li> <a href="c3ref/str_append.html">sqlite3_str_vappendf()</a> &rarr; Varargs version of sqlite3_str_appendf()
+</li></ul>
+
+<p>The same core string formatter is also used internally by SQLite.
+
+</p><h2 id="advantages"><span>1.1. </span>Advantages</h2>
+
+<p>Why does SQLite have its own private built-in printf() implementation?
+Why not use the printf() implementation from the standard C library?
+Several reasons:
+
+</p><p>
+</p><ol>
+<li><p>
+By using its own built-in implementation, SQLite guarantees that the
+output will be the same on all platforms and in all LOCALEs.
+This is important for consistency and for testing. It would be problematic
+if one machine gave an answer of "5.25e+08" and another gave an answer
+of "5.250e+008". Both answers are correct, but it is better when SQLite
+always gives the same answer.
+
+</p></li><li><p>
+We know of no way to use the standard library printf() C interface to
+implement the <a href="lang_corefunc.html#format">format() SQL function</a> feature of SQLite. The built-in
+printf() implementation can be easily adapted to that task, however.
+
+</p></li><li><p>
+The printf() in SQLite supports new non-standard substitution
+types (<a href="printf.html#percentq">%q</a>, <a href="printf.html#percentq">%Q</a>, <a href="printf.html#percentw">%w</a>, and <a href="printf.html#percentz">%z</a>), and enhanced substitution
+behavior (%s and <a href="printf.html#percentz">%z</a>) that are useful both internally to SQLite
+and to applications using SQLite.
+Standard library printf()s cannot normally be extended in this way.
+
+</p></li><li><p>
+Via the <a href="c3ref/mprintf.html">sqlite3_mprintf()</a> and <a href="c3ref/mprintf.html">sqlite3_vmprintf()</a> interfaces,
+the built-in printf() implementation supports the ability to render an
+arbitrary-length string into a memory buffer obtained from <a href="c3ref/free.html">sqlite3_malloc64()</a>.
+This is safer and less error prone than trying to precompute an upper size
+limit on the result string, allocate an appropriately sized buffer, and
+then calling snprintf().
+
+</p></li><li><p>
+The SQLite-specific printf() supports a new flag (!) called the
+"alternate-form-2" flag. The alternate-form-2 flag changes the processing
+of floating-point conversions in subtle ways so that the output is always
+an SQL-compatible text representation of a floating-point number - something
+that is not possible to achieve with standard-library printf(). For
+string substitutions, the alternate-form-2 flag causes the width and
+precision to be measured in characters instead of bytes, which simplifies
+processing of strings containing multi-byte UTF8 characters.
+
+</p></li><li><p>
+The built-in SQLite has compile-time options such as
+SQLITE_PRINTF_PRECISION_LIMIT that provide defense against
+denial-of-service attacks for application that expose the
+printf() functionality to untrusted users.
+
+</p></li><li><p>
+Using a built-in printf() implementation means that SQLite has one
+fewer dependency on the host environment, making it more portable.
+</p></li></ol>
+
+<h2 id="disadvantages"><span>1.2. </span>Disadvantages</h2>
+
+<p>
+In fairness, having a built-in implementation of printf() also comes with
+some disadvantages. To wit:
+
+</p><ol>
+<li><p>
+The built-in printf() implementation uses extra code space
+(about 7800 bytes on GCC 5.4 with -Os).
+
+</p></li><li><p>
+The floating-point to text conversion subfunction for the built-in printf()
+is limited in precision to 16 significant digits or 26 significant digits
+if the "!" alternate-form-2 flag is used.
+Every IEEE-754 double can be represented <i>exactly</i> as a decimal
+value, but for many doubles the exact decimal representation requires
+more than 16 or 26 significant digits.
+The SQLite printf() function only renders the first 16 or 26 significant digits
+because that can be done efficient and because 16 decimal digits it is sufficient
+to distinguish every possible double value. Use the <a href="floatingpoint.html#decext">decimal extension</a> to get
+the exact decimal equivalent of double value for the rare cases where that is
+required.
+
+</p></li><li><p>
+The order of the buffer pointer and buffer size parameters in the built-in
+snprintf() implementation is reversed from the order used in standard-library
+implementations.
+
+</p></li><li><p>
+The built-in printf() implementation does not handle posix positional referencing
+modifiers that allow the order of arguments to printf() to be different from the
+order of the %-substitutions. In the built-in printf(), the order of the arguments
+must exactly match the order of the %-substitutions.
+</p></li></ol>
+
+<p>
+In spite of the disadvantages, the developers believe that having a built-in
+printf() implementation inside of SQLite is a net positive.
+
+</p><h1 id="formatting_details"><span>2. </span>Formatting Details</h1>
+
+<p>The format string for printf() is a template for the generated
+string. Substitutions are made whenever a "%" character appears in
+the format string. The "%" is followed by one or more additional
+characters that describe the substitution. Each substitution has
+the following format:
+
+</p><blockquote>
+<b>%</b><i>&#91;flags&#93;&#91;width&#93;&#91;</i><b>.</b><i>precision&#93;&#91;length&#93;type</i>
+</blockquote>
+
+<p>All substitutions begin with a single "%" and end with a single type character.
+The other elements of the substitution are optional.
+
+</p><p>To include a single "%" character in the output, put two consecutive
+"%" characters in the template.
+
+</p><h2 id="substitution_types"><span>2.1. </span>Substitution Types</h2>
+
+<p>The following chart shows the substitution types supported by SQLite:
+
+</p><center>
+<table border="1" cellpadding="10" width="80%">
+<tr>
+<th>Substitution Type</th><th>Meaning
+</th></tr><tr>
+<td>%
+</td><td>Two "%" characters in a row are translated into a single "%" in the output,
+ without substituting any values.
+</td></tr><tr>
+<td>d, i
+</td><td>The argument is a signed integer which is displayed in decimal.
+</td></tr><tr>
+<td>u
+</td><td>The argument is an unsigned integer which is displayed in decimal.
+</td></tr><tr>
+<td>f
+</td><td>The argument is a double which is displayed in decimal.
+</td></tr><tr>
+<td>e, E
+</td><td>The argument is a double which is displayed in exponential notation.
+ The exponent character is 'e' or 'E' depending on the type.
+</td></tr><tr>
+<td>g, G
+</td><td>The argument is a double which is displayed in either normal decimal
+ notation or if the exponent is not close to zero, in exponential
+ notation.
+</td></tr><tr>
+<td>x, X
+</td><td>The argument is an integer which is displayed in hexadecimal.
+ Lower-case hexadecimal is used for %x and upper-case is used
+ for %X
+</td></tr><tr>
+<td>o
+</td><td>The argument is an integer which is displayed in octal.
+</td></tr><tr>
+<td>s, z
+</td><td>
+<a name="percentz"></a>
+
+ The argument is either a zero-terminated string that is displayed,
+ or a null pointer which is treated as an empty string. For
+ the %z type in C-language interfaces, <a href="c3ref/free.html">sqlite3_free()</a> is invoked
+ on the string after it has been copied into the output. The %s and %z
+ substitutions are identical for the SQL printf() function, with
+ a NULL argument treated as an empty string.<br><br>
+ The %s substitution is universal among printf functions, but
+ the %z substitution and safe treatment of null pointers
+ are SQLite enhancements, not found in other
+ printf() implementations.
+</td></tr><tr>
+<td>c
+</td><td>For the C-language interfaces, the argument is an integer which
+ is interpreted as a character. For the <a href="lang_corefunc.html#format">format() SQL function</a> the
+ argument is a string from which the first character is extracted and
+ displayed.
+</td></tr><tr>
+<td>p
+</td><td>The argument is a pointer which is displayed as a hexadecimal address.
+ Since the SQL language has no concept of a pointer, the %p substitution
+ for the <a href="lang_corefunc.html#format">format() SQL function</a> works like %x.
+</td></tr><tr>
+<td>n
+</td><td>The argument is a pointer to an integer. Nothing is displayed for
+ this substitution type. Instead, the integer to which the argument
+ points is overwritten with the number of characters in the generated
+ string that result from all format symbols to the left of the %n.
+</td></tr><tr>
+<td>q, Q
+</td><td><a name="percentq"></a>
+
+ The argument is a zero-terminated string. The string is printed with
+ all single quote (') characters doubled so that the string can safely
+ appear inside an SQL string literal. The %Q substitution type also
+ puts single-quotes on both ends of the substituted string.
+ <br><br>If the argument
+ to %Q is a null pointer then the output is an unquoted "NULL". In other
+ words, a null pointer generates an SQL NULL, and a non-null pointer generates
+ a valid SQL string literal. If the argument to %q is a null pointer
+ then no output is generated. Thus a null-pointer to %q is the same as
+ an empty string.
+ <br><br>For these substitutions, the precision is the number of bytes or
+ characters taken from the argument, not the number of bytes or characters that
+ are written into the output.
+ <br><br>
+ The %q and %Q substitutions are SQLite enhancements, not found in
+ most other printf() implementations.
+</td></tr><tr>
+<td>w
+</td><td><a name="percentw"></a>
+
+ This substitution works like %q except that it doubles all double-quote
+ characters (") instead of single-quotes, making the result suitable for
+ using with a double-quoted identifier name in an SQL statement.
+ <br><br>
+ The %w substitution is an SQLite enhancements, not found in
+ most other printf() implementations.
+</td></tr></table>
+</center>
+
+<h2 id="the_optional_length_field"><span>2.2. </span>The Optional Length Field</h2>
+
+<p>The length of the argument value can be specified by one or more letters
+that occur just prior to the substitution type letter. In SQLite, the
+length only matter for integer types. The length is ignored for the
+<a href="lang_corefunc.html#format">format() SQL function</a> which always uses 64-bit values. The following
+table shows the length specifiers allowed by SQLite:
+
+</p><center>
+<table border="1" cellpadding="10" width="80%">
+<tr>
+<th>Length Specifier
+</th><th>Meaning
+</th></tr><tr>
+<td><i>(default)</i>
+</td><td>An "int" or "unsigned int". 32-bits on all modern systems.
+</td></tr><tr>
+<td>l
+</td><td>A "long int" or "long unsigned int". Also 32-bits on all modern systems.
+</td></tr><tr>
+<td>ll
+</td><td>A "long long int" or "long long unsigned" or an "sqlite3_int64" or
+ "sqlite3_uint64" value. These are 64-bit integers on all modern systems.
+</td></tr></table>
+</center>
+
+<p>Only the "ll" length modifier ever makes a difference for SQLite. And
+it only makes a difference when using the C-language interfaces.
+
+</p><h2 id="the_optional_width_field"><span>2.3. </span>The Optional Width Field</h2>
+
+<p>The width field specifies the minimum width of the substituted value in
+the output. If the string or number that is written into the output is shorter
+than the width, then the value is padded. Padding is on the left (the
+value is right-justified) by default. If the "-" flag is used, then the
+padding is on the right and the value is left-justified.
+
+</p><p>The width is measured in bytes by default. However, if the "!" flag is
+present then the width is in characters. This only makes a difference for
+multi-byte utf-8 characters, and those only occur on string substitutions.
+
+</p><p>If the width is a single "*" character instead of a number, then the
+actual width value is read as an integer from the argument list. If the
+value read is negative, then the absolute value is used for the width and
+the value is left-justified as if the "-" flag were present.
+
+</p><p>If the value being substituted is larger than the width, then full value
+is added to the output. In other words, the width is the minimum width of
+the value as it is rendered in the output.
+
+</p><h2 id="the_optional_precision_field"><span>2.4. </span>The Optional Precision Field</h2>
+
+<p>The precision field, if it is present, must follow the width separated
+by a single "." character. If there is no width, then the "." that introduces
+the precision immediately follows either the flags (if there are any) or
+the initial "%".
+
+</p><p>For string substitutions (%s, %z, %q, %Q, or %w) the precision is the number
+of byte or character used from the argument. The number is bytes by default but
+is characters if the "!" flag is present. If there is no precision, then the
+entire string is substituted. Examples: "%.3s" substitutes the first 3 bytes
+of the argument string. "%!.3s" substitutes the first three characters of the
+argument string.
+
+</p><p>For integer substitutions (%d, %i, %x, %X, %o, and %p) the precision specifies
+minimum number of digits to display. Leading zeros are added if necessary, to
+expand the output to the minimum number of digits.
+
+</p><p>For floating-point substitutions (%e, %E, %f, %g, %G) the precision specifies
+the number of digits to display to the right of the decimal point.
+
+</p><p>For the character substitution (%c) a precision N greater than 1 causes the
+character to be repeated N times. This is a non-standard extension found only
+in SQLite.
+
+</p><p>If the precision is a single "*" character instead of a number, then the
+actual precision value is read as an integer from the argument list.
+
+</p><h2 id="the_options_flags_field"><span>2.5. </span>The Options Flags Field</h2>
+
+<p>Flags consist of zero or more characters that immediately follow the
+"%" that introduces the substitution. The various flags and their meanings
+are as follows:
+
+</p><center>
+<table border="1" cellpadding="10" width="80%">
+<tr>
+<th>Flag
+</th><th>Meaning
+</th></tr><tr>
+<td><b>-</b>
+</td><td>Left-justify the value in the output. The default is to right-justify.
+If the width is zero or is otherwise less than the length of the value being
+substituted, then there is no padding and the "-" flag is a no-op.
+</td></tr><tr>
+<td><b>+</b>
+</td><td>For signed numeric substitutions, include a "+" sign before positive numbers.
+A "-" sign always appears before negative numbers regardless of flag settings.
+</td></tr><tr>
+<td><i>(space)</i>
+</td><td>For signed numeric substitutions, prepend a single space before positive
+numbers.
+</td></tr><tr>
+<td><b>0</b>
+</td><td>(The zero-padding option)
+Prepend as many "0" characters to numeric substitutions as necessary to
+expand the value out to the specified width. If the width field is omitted,
+then this flag is a no-op.
+Infinity and NaN (Not-A-Number) floating point values are normally rendered
+as "Inf" and "NaN", respectively, but with the zero-padding option enabled
+they are rendered as "9.0e+999" and "null". In other words, with the zero-padding
+option, floating-point Infinity and NaN are rendered as valid SQL and JSON literals.
+</td></tr><tr>
+<td><b>#</b>
+</td><td>This is the "alternate-form-1" flag.
+For %g and %G substitutions, this causes trailing zeros to be removed.
+This flag forces a decimal point to appear for all floating-point substitutions.
+For %o, %x, and %X substitutions, the alternate-form-1 flag cause the value
+to be prepended with "0", "0x", or "0X", respectively.
+</td></tr><tr>
+<a name="comma"></a>
+
+<td><b>,</b>
+</td><td>The comma option causes comma separators to be added to the output of numeric
+substitutions (%d, %f, and similar) before every 3rd digits to the left of
+the decimal point. No commas are added for digits to the right of the decimal point.
+This can help humans to more easily discern the magnitude of large integer values.
+For example,
+the value 2147483647 would be rendered as "2147483647" using "%d" but would
+appear as "2,147,483,647" with "%,d". This flag is a non-standard extension.
+</td></tr><tr>
+<td><b>!</b>
+</td><td>This is the "alternate-form-2 flag.
+For string substitutions, this flag causes the width and precision to be understand
+in terms of characters rather than bytes.
+For floating point substitutions, the alternate-form-2 flag increases the
+maximum number of significant digits displayed from 16 to 26,
+forces the display of the decimal point and causes at least one digit
+to appear after the decimal point.<br><br>
+The alternate-form-2 flag is a non-standard extension that appears in no
+other printf() implementations, as far as we know.
+</td></tr></table>
+</center>
+
+<h1 id="implementation_and_history"><span>3. </span>Implementation And History</h1>
+
+<p>
+The core string formatting routine is the sqlite3VXPrintf() function found in the
+<a href="https://sqlite.org/src/file/src/printf.c">printf.c</a> source file. All the
+various interfaces invoke (sometimes indirectly) this one core function.
+The sqlite3VXPrintf() function began as code written by the first author
+of SQLite (<a href="crew.html">Hipp</a>) when he was a graduate student at Duke University in the
+late 1980s. Hipp kept this printf() implementation in his personal toolbox until
+he started working on SQLite in 2000. The code was incorporated into the
+SQLite source tree on <a href="https://sqlite.org/src/timeline?c=f9372072a6">2000-10-08</a>
+for SQLite version 1.0.9.
+
+</p><p>
+The <a href="https://www.fossil-scm.org/">Fossil Version Control System</a> uses its own
+printf() implementation that is derived from an early version of the SQLite
+printf() implementation, but those two implementations have since diverged.
+
+</p><p>
+The <a href="c3ref/mprintf.html">sqlite3_snprintf()</a> function has its buffer pointer and buffer size
+arguments reversed from what is found in the standard C library snprintf()
+routine. This is because there was no snprintf() routine in the
+standard C library
+when Hipp was first implementing his version, and he chose a different order
+than the designers of the standard C library.
+</p><p align="center"><small><i>This page last modified on <a href="https://sqlite.org/docsrc/honeypot" id="mtimelink" data-href="https://sqlite.org/docsrc/finfo/pages/printf.in?m=4880d4e1ee">2023-06-29 23:18:37</a> UTC </small></i></p>
+