inweb-bootstrap/docs/foundation-module/2-str.html

1065 lines
221 KiB
HTML
Raw Normal View History

2019-02-04 22:26:45 +00:00
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
2020-04-08 22:41:00 +00:00
<title>Streams</title>
2020-04-23 22:23:44 +00:00
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
<meta name="viewport" content="width=device-width initial-scale=1">
2019-02-04 22:26:45 +00:00
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
2020-04-20 22:26:08 +00:00
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
<script>
function togglePopup(material_id) {
var popup = document.getElementById(material_id);
popup.classList.toggle("show");
}
</script>
<link href="../docs-assets/Popups.css" rel="stylesheet" rev="stylesheet" type="text/css">
2020-04-21 16:55:17 +00:00
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
2020-04-23 22:23:44 +00:00
2019-02-04 22:26:45 +00:00
</head>
<body>
<nav role="navigation">
2020-04-13 16:06:45 +00:00
<h1><a href="../index.html">
2020-04-20 22:26:08 +00:00
<img src="../docs-assets/Octagram.png" width=72 height=72">
2020-04-13 16:06:45 +00:00
</a></h1>
<ul><li><a href="../inweb/index.html">inweb</a></li>
</ul><h2>Foundation Module</h2><ul>
<li><a href="index.html"><span class="selectedlink">foundation</span></a></li>
<li><a href="../foundation-test/index.html">foundation-test</a></li>
2020-04-13 16:06:45 +00:00
</ul><h2>Example Webs</h2><ul>
2020-04-12 16:24:23 +00:00
<li><a href="../goldbach/index.html">goldbach</a></li>
<li><a href="../twinprimes/twinprimes.html">twinprimes</a></li>
2020-04-15 22:45:08 +00:00
<li><a href="../eastertide/index.html">eastertide</a></li>
2020-04-14 17:36:42 +00:00
</ul><h2>Repository</h2><ul>
2020-04-20 22:34:44 +00:00
<li><a href="https://github.com/ganelson/inweb"><img src="../docs-assets/github.png" height=18> github</a></li>
2020-04-14 17:36:42 +00:00
</ul><h2>Related Projects</h2><ul>
<li><a href="../../../inform/docs/index.html">inform</a></li>
<li><a href="../../../intest/docs/index.html">intest</a></li>
2020-04-13 16:06:45 +00:00
</ul>
</nav>
<main role="main">
2020-04-23 22:23:44 +00:00
<!--Weave of 'Streams' generated by Inweb-->
2020-04-13 16:06:45 +00:00
<ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="index.html">foundation</a></li><li><a href="index.html#2">Chapter 2: Memory, Streams and Collections</a></li><li><b>Streams</b></li></ul><p class="purpose">Support for writing structured textual output, perhaps to the screen, to a file, or to a flexible-sized wide string.</p>
2019-02-04 22:26:45 +00:00
2020-04-15 22:45:08 +00:00
<ul class="toc"><li><a href="2-str.html#SP1">&#167;1. About streams</a></li><li><a href="2-str.html#SP19">&#167;19. Initialising the stream structure</a></li><li><a href="2-str.html#SP21">&#167;21. Logging</a></li><li><a href="2-str.html#SP22">&#167;22. Standard I/O wrappers</a></li><li><a href="2-str.html#SP24">&#167;24. Creating file streams</a></li><li><a href="2-str.html#SP26">&#167;26. Creating memory streams</a></li><li><a href="2-str.html#SP28">&#167;28. Converting from C strings</a></li><li><a href="2-str.html#SP29">&#167;29. Converting to C strings</a></li><li><a href="2-str.html#SP32">&#167;32. Locale versions</a></li><li><a href="2-str.html#SP33">&#167;33. Flush and close</a></li><li><a href="2-str.html#SP35">&#167;35. Writing</a></li><li><a href="2-str.html#SP39">&#167;39. Memory-stream-only functions</a></li><li><a href="2-str.html#SP43">&#167;43. Writer</a></li></ul><hr class="tocbar">
2019-02-04 22:26:45 +00:00
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP1"></a><b>&#167;1. About streams. </b>The Inform tools produce textual output in many formats (HTML, EPS, plain
2019-02-04 22:26:45 +00:00
text, Inform 6 code, XML, and so on), writing to a variety of files, and
often need to juggle and rearrange partially written segments. These
texts tend to be structured with running indentation, and may eventually
need to be written to a disc file with either ISO Latin-1 or UTF-8
encodings, perhaps escaped for XML.
</p>
2020-04-24 23:06:02 +00:00
<p class="commentary">"Streams" are an abstraction to make it easy to handle all of this. The
2019-02-04 22:26:45 +00:00
writer to a stream never needs to know where the text will come out, or how
it should be indented or encoded.
</p>
2020-04-24 23:06:02 +00:00
<p class="commentary">Moreover, streams unify text files and strings, and can hold arbitrary
2019-02-04 22:26:45 +00:00
Unicode text. This text is encoded internally as a sequence of 32-bit Unicode
code points, in a form we might call semi-composed, in that all possible
compositions of ISO Latin-1 characters are made: e.g., E plus acute accent
is composed to a single code point as E-acute.
</p>
2020-04-24 23:06:02 +00:00
<p class="commentary">We give just one character value a non-Unicode meaning:
2019-02-04 22:26:45 +00:00
</p>
2020-04-24 23:06:02 +00:00
<pre class="definitions"><span class="definition-keyword">define</span> <span class="constant-syntax">NEWLINE_IN_STRING</span><span class="plain-syntax"> ((</span><span class="reserved-syntax">char</span><span class="plain-syntax">) </span><span class="constant-syntax">0x7f</span><span class="plain-syntax">) </span><span class="comment-syntax"> Within quoted text, all newlines are converted to this</span>
2019-02-04 22:26:45 +00:00
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP2"></a><b>&#167;2. </b>The <span class="extract"><span class="extract-syntax">text_stream</span></span> type began as a generalisation of the standard C library's
2020-04-22 22:57:09 +00:00
<span class="extract"><span class="extract-syntax">FILE</span></span>, and it is used in mostly similar ways. The user &mdash; the whole
program outside of this section &mdash; deals only with <span class="extract"><span class="extract-syntax">text_stream *</span></span> pointers to
2019-02-04 22:26:45 +00:00
represent streams in use.
</p>
2020-04-24 23:06:02 +00:00
<p class="commentary">All stream handling is defined via macros. While many operations could be
2020-04-22 22:57:09 +00:00
handled by ordinary functions, others cannot. <span class="extract"><span class="extract-syntax">text_stream</span></span> cannot have exactly
the semantics of <span class="extract"><span class="extract-syntax">FILE</span></span> since we cannot rely on the host operating system
to allocate and deallocate the structures behind <span class="extract"><span class="extract-syntax">text_stream *</span></span> pointers; and
2019-02-04 22:26:45 +00:00
we cannot use our own memory system, either, since we need stream handling
to work both before the memory allocator starts and after it has finished.
Our macros allow us to hide all this. Besides that, a macro approach makes it
easier to retrofit new implementations as necessary. (The present
implementation is the second stab at it.)
</p>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP3"></a><b>&#167;3. </b>We'll define a few variadic macros here, because there are awkward issues
2019-02-04 22:26:45 +00:00
with code ordering if we leave them until later. They are written in the
old-fashioned way, for compatibility with old copies of GCC, and avoid the
need for comma deletion around empty tokens, as that is a point of
2020-04-22 22:57:09 +00:00
incompatibility between implementations of the C preprocessor <span class="extract"><span class="extract-syntax">cpp</span></span>. All the
2019-02-04 22:26:45 +00:00
same, if you're porting this code, you may need to rewrite the macro with
2020-04-22 22:57:09 +00:00
<span class="extract"><span class="extract-syntax">...</span></span> in place of <span class="extract"><span class="extract-syntax">args...</span></span> in the header, and then <span class="extract"><span class="extract-syntax">__VA_ARGS__</span></span> in place
of <span class="extract"><span class="extract-syntax">args</span></span> in the definition: that being the modern way, apparently.
2019-02-04 22:26:45 +00:00
</p>
2020-04-24 23:06:02 +00:00
<p class="commentary"><span class="extract"><span class="extract-syntax">WRITE</span></span> is essentially <span class="extract"><span class="extract-syntax">sprintf</span></span> and <span class="extract"><span class="extract-syntax">fprintf</span></span> combined, since it prints
2019-02-04 22:26:45 +00:00
formatted text to the current stream, which could be either a string or a
2020-04-22 22:57:09 +00:00
file. <span class="extract"><span class="extract-syntax">PRINT</span></span> does the same but to <span class="extract"><span class="extract-syntax">STDOUT</span></span>, and is thus essentially <span class="extract"><span class="extract-syntax">printf</span></span>.
2019-02-04 22:26:45 +00:00
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
2020-04-21 23:52:25 +00:00
<span class="plain-syntax">#</span><span class="identifier-syntax">define</span><span class="plain-syntax"> </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="identifier-syntax">args</span><span class="plain-syntax">...) </span><a href="2-wal.html#SP6" class="function-link"><span class="function-syntax">Writers::printf</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="identifier-syntax">args</span><span class="plain-syntax">)</span>
2019-02-04 22:26:45 +00:00
2020-04-21 23:52:25 +00:00
<span class="plain-syntax">#</span><span class="identifier-syntax">define</span><span class="plain-syntax"> </span><span class="identifier-syntax">PRINT</span><span class="plain-syntax">(</span><span class="identifier-syntax">args</span><span class="plain-syntax">...) </span><a href="2-wal.html#SP6" class="function-link"><span class="function-syntax">Writers::printf</span></a><span class="plain-syntax">(</span><span class="constant-syntax">STDOUT</span><span class="plain-syntax">, </span><span class="identifier-syntax">args</span><span class="plain-syntax">)</span>
2019-02-04 22:26:45 +00:00
2020-04-21 23:52:25 +00:00
<span class="plain-syntax">#</span><span class="identifier-syntax">define</span><span class="plain-syntax"> </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="identifier-syntax">args</span><span class="plain-syntax">...) </span><a href="2-wal.html#SP6" class="function-link"><span class="function-syntax">Writers::printf</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="identifier-syntax">args</span><span class="plain-syntax">)</span>
2019-02-04 22:26:45 +00:00
2020-04-21 23:52:25 +00:00
<span class="plain-syntax">#</span><span class="identifier-syntax">define</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="identifier-syntax">args</span><span class="plain-syntax">...) </span><a href="2-wal.html#SP6" class="function-link"><span class="function-syntax">Writers::printf</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">DL</span><span class="plain-syntax">, </span><span class="identifier-syntax">args</span><span class="plain-syntax">)</span>
2019-02-04 22:26:45 +00:00
2020-04-21 16:55:17 +00:00
<span class="plain-syntax">#</span><span class="identifier-syntax">define</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOGIF</span><span class="plain-syntax">(</span><span class="identifier-syntax">aspect</span><span class="plain-syntax">, </span><span class="identifier-syntax">args</span><span class="plain-syntax">...) { \</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-dl.html#SP7" class="function-link"><span class="function-syntax">Log::aspect_switched_on</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">aspect</span><span class="plain-syntax">##</span><span class="identifier-syntax">_DA</span><span class="plain-syntax">)) </span><a href="2-wal.html#SP6" class="function-link"><span class="function-syntax">Writers::printf</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">DL</span><span class="plain-syntax">, </span><span class="identifier-syntax">args</span><span class="plain-syntax">); \</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax">}</span>
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP4"></a><b>&#167;4. </b>The main purpose of many functions is to write textual material to some
2019-02-04 22:26:45 +00:00
file. Such functions almost always have a special argument in their
2020-04-22 22:57:09 +00:00
prototypes: <span class="extract"><span class="extract-syntax">OUTPUT_STREAM</span></span>. This tells them where to pipe their output, which
is always to a "current stream" called <span class="extract"><span class="extract-syntax">OUT</span></span>. What this leads to, and who will
2019-02-04 22:26:45 +00:00
see that it's properly opened and closed, are not their concern.
</p>
2020-04-24 23:06:02 +00:00
<pre class="definitions"><span class="definition-keyword">define</span> <span class="constant-syntax">OUTPUT_STREAM</span><span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">OUT</span><span class="plain-syntax"> </span><span class="comment-syntax"> used only as a function prototype argument</span>
2019-02-04 22:26:45 +00:00
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP5"></a><b>&#167;5. </b>Three output streams are always open. One is <span class="extract"><span class="extract-syntax">NULL</span></span>, that is, its value
2020-04-22 22:57:09 +00:00
as a <span class="extract"><span class="extract-syntax">text_stream *</span></span> pointer is <span class="extract"><span class="extract-syntax">NULL</span></span>, the generic C null pointer. This represents
an oubliette: it is entirely valid to use it, but output sent to <span class="extract"><span class="extract-syntax">NULL</span></span> will
2019-02-04 22:26:45 +00:00
never be seen again.
</p>
2020-04-24 23:06:02 +00:00
<p class="commentary">The others are <span class="extract"><span class="extract-syntax">STDOUT</span></span> and <span class="extract"><span class="extract-syntax">STDERR</span></span>. As the names suggest these are wrappers
2020-04-22 22:57:09 +00:00
for <span class="extract"><span class="extract-syntax">stdout</span></span> and <span class="extract"><span class="extract-syntax">stderr</span></span>, the standard console output and error messages
2019-02-04 22:26:45 +00:00
"files" provided by the C library.
</p>
2020-04-24 23:06:02 +00:00
<p class="commentary">We should always use <span class="extract"><span class="extract-syntax">PRINT(...)</span></span> instead of <span class="extract"><span class="extract-syntax">printf(...)</span></span> for console output,
2020-04-22 22:57:09 +00:00
so that there are no uses of <span class="extract"><span class="extract-syntax">printf</span></span> anywhere in the program.
2019-02-04 22:26:45 +00:00
</p>
<pre class="definitions"><span class="definition-keyword">define</span> <span class="constant-syntax">STDOUT</span><span class="plain-syntax"> </span><a href="2-str.html#SP22" class="function-link"><span class="function-syntax">Streams::get_stdout</span></a><span class="plain-syntax">()</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">STDERR</span><span class="plain-syntax"> </span><a href="2-str.html#SP23" class="function-link"><span class="function-syntax">Streams::get_stderr</span></a><span class="plain-syntax">()</span>
2019-02-04 22:26:45 +00:00
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP6"></a><b>&#167;6. </b><span class="extract"><span class="extract-syntax">PUT</span></span> and <span class="extract"><span class="extract-syntax">PUT_TO</span></span> similarly print single characters, which are
2020-04-22 22:57:09 +00:00
specified as unsigned integer values. In practice, <span class="extract"><span class="extract-syntax">WRITE_TO</span></span> and
<span class="extract"><span class="extract-syntax">PUT_TO</span></span> are seldom needed because there is almost always only one
stream of interest at a time &mdash; <span class="extract"><span class="extract-syntax">OUT</span></span>, the current stream.
2019-02-04 22:26:45 +00:00
</p>
<pre class="definitions"><span class="definition-keyword">define</span> <span class="identifier-syntax">PUT</span><span class="plain-syntax">(</span><span class="identifier-syntax">c</span><span class="plain-syntax">) </span><a href="2-str.html#SP35" class="function-link"><span class="function-syntax">Streams::putc</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">c</span><span class="plain-syntax">, </span><span class="identifier-syntax">OUT</span><span class="plain-syntax">)</span>
<span class="definition-keyword">define</span> <span class="identifier-syntax">PUT_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="identifier-syntax">c</span><span class="plain-syntax">) </span><a href="2-str.html#SP35" class="function-link"><span class="function-syntax">Streams::putc</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">c</span><span class="plain-syntax">, </span><span class="identifier-syntax">stream</span><span class="plain-syntax">)</span>
2019-02-04 22:26:45 +00:00
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP7"></a><b>&#167;7. </b>Each stream has a current indentation level, initially 0. Lines of text
2019-02-04 22:26:45 +00:00
will be indented by one tab stop for each level; it's an error for the level
to become negative.
</p>
<pre class="definitions"><span class="definition-keyword">define</span> <span class="constant-syntax">INDENT</span><span class="plain-syntax"> </span><a href="2-str.html#SP37" class="function-link"><span class="function-syntax">Streams::indent</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">);</span>
<span class="definition-keyword">define</span> <span class="identifier-syntax">STREAM_INDENT</span><span class="plain-syntax">(</span><span class="identifier-syntax">x</span><span class="plain-syntax">) </span><a href="2-str.html#SP37" class="function-link"><span class="function-syntax">Streams::indent</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">x</span><span class="plain-syntax">);</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">OUTDENT</span><span class="plain-syntax"> </span><a href="2-str.html#SP37" class="function-link"><span class="function-syntax">Streams::outdent</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">);</span>
<span class="definition-keyword">define</span> <span class="identifier-syntax">STREAM_OUTDENT</span><span class="plain-syntax">(</span><span class="identifier-syntax">x</span><span class="plain-syntax">) </span><a href="2-str.html#SP37" class="function-link"><span class="function-syntax">Streams::outdent</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">x</span><span class="plain-syntax">);</span>
<span class="definition-keyword">define</span> <span class="identifier-syntax">SET_INDENT</span><span class="plain-syntax">(</span><span class="identifier-syntax">N</span><span class="plain-syntax">) </span><a href="2-str.html#SP37" class="function-link"><span class="function-syntax">Streams::set_indentation</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="identifier-syntax">N</span><span class="plain-syntax">);</span>
2019-02-04 22:26:45 +00:00
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP8"></a><b>&#167;8. </b>Other streams only exist when explicitly created, or "opened". A function
2019-02-04 22:26:45 +00:00
is only allowed to open a new stream if it can be proved that this stream will
always subsequently be "closed". (Except for the possibility of the tool
2020-04-22 22:57:09 +00:00
halting with an internal error, and therefore an <span class="extract"><span class="extract-syntax">exit(1)</span></span>, while the stream
2019-02-04 22:26:45 +00:00
is still open.) A stream can be opened and closed only once, and outside that
time its state is undefined: it must not be used at all.
</p>
2020-04-24 23:06:02 +00:00
<p class="commentary">The simplest way is to make a temporary stream, which can be used as a sort
2019-02-04 22:26:45 +00:00
of clipboard. For instance, suppose we have to compile X before Y, but have to
ensure Y comes before X in the eventual output. We create a temporary stream,
2020-04-22 22:57:09 +00:00
compile X into it, then compile Y to <span class="extract"><span class="extract-syntax">OUT</span></span>, then copy the temporary stream
into <span class="extract"><span class="extract-syntax">OUT</span></span> and dispose of it.
2019-02-04 22:26:45 +00:00
</p>
2020-04-24 23:06:02 +00:00
<p class="commentary">Temporary streams are always created in memory, held in C's local stack frame
2020-04-22 22:57:09 +00:00
rather than allocated and freed via <span class="extract"><span class="extract-syntax">malloc</span></span> and <span class="extract"><span class="extract-syntax">free</span></span>. It must always be
possible to prove that execution passes from <span class="extract"><span class="extract-syntax">TEMPORARY_TEXT</span></span> to
<span class="extract"><span class="extract-syntax">DISCARD_TEXT</span></span>, unless the program makes a fatal exit in between. The stream,
let's call it <span class="extract"><span class="extract-syntax">TEMP</span></span>, exists only between those macros. We can legitimately
2019-02-04 22:26:45 +00:00
create a temporary stream many times in one function (for instance inside a
2020-04-22 22:57:09 +00:00
loop body) because each time <span class="extract"><span class="extract-syntax">TEMP</span></span> is created as a new stream, overwriting the
old one. <span class="extract"><span class="extract-syntax">TEMP</span></span> is a different stream each time it is created, so it does
2019-02-04 22:26:45 +00:00
not violate the rule that every stream is opened and closed once only.
</p>
<pre class="definitions"><span class="definition-keyword">define</span> <span class="identifier-syntax">TEMPORARY_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">T</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">T</span><span class="plain-syntax">##</span><span class="identifier-syntax">_dest</span><span class="plain-syntax">[2048];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> </span><span class="identifier-syntax">T</span><span class="plain-syntax">##</span><span class="identifier-syntax">_stream_structure</span><span class="plain-syntax"> = </span><a href="2-str.html#SP27" class="function-link"><span class="function-syntax">Streams::new_buffer</span></a><span class="plain-syntax">(2048, </span><span class="identifier-syntax">T</span><span class="plain-syntax">##</span><span class="identifier-syntax">_dest</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">T</span><span class="plain-syntax"> = &amp;</span><span class="identifier-syntax">T</span><span class="plain-syntax">##</span><span class="identifier-syntax">_stream_structure</span><span class="plain-syntax">;</span>
<span class="definition-keyword">define</span> <span class="identifier-syntax">DISCARD_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">T</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">STREAM_CLOSE</span><span class="plain-syntax">(</span><span class="identifier-syntax">T</span><span class="plain-syntax">);</span>
2019-02-04 22:26:45 +00:00
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP9"></a><b>&#167;9. </b>Otherwise we can create new globally existing streams, provided we take on
2019-02-04 22:26:45 +00:00
the responsibility for seeing that they are properly closed. There are two
2020-04-22 22:57:09 +00:00
choices: a stream in memory, allocated via <span class="extract"><span class="extract-syntax">malloc</span></span> and freed by <span class="extract"><span class="extract-syntax">free</span></span> when
the stream is closed; or a file written to disc, opened via <span class="extract"><span class="extract-syntax">fopen</span></span> and
later closed by <span class="extract"><span class="extract-syntax">fclose</span></span>. Files are always written in text mode, that is,
<span class="extract"><span class="extract-syntax">"w"</span></span> not <span class="extract"><span class="extract-syntax">"wb"</span></span>, for those platforms where this makes a difference.
2019-02-04 22:26:45 +00:00
</p>
2020-04-24 23:06:02 +00:00
<p class="commentary">We use streams to handle all of our text file output, so there should be no
2020-04-22 22:57:09 +00:00
calls to <span class="extract"><span class="extract-syntax">fprintf</span></span> anywhere in the program except for binary files.
2019-02-04 22:26:45 +00:00
</p>
<pre class="definitions"><span class="definition-keyword">define</span> <span class="identifier-syntax">STREAM_OPEN_TO_FILE</span><span class="plain-syntax">(</span><span class="identifier-syntax">new</span><span class="plain-syntax">, </span><span class="identifier-syntax">fn</span><span class="plain-syntax">, </span><span class="identifier-syntax">enc</span><span class="plain-syntax">) </span><a href="2-str.html#SP24" class="function-link"><span class="function-syntax">Streams::open_to_file</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">new</span><span class="plain-syntax">, </span><span class="identifier-syntax">fn</span><span class="plain-syntax">, </span><span class="identifier-syntax">enc</span><span class="plain-syntax">)</span>
<span class="definition-keyword">define</span> <span class="identifier-syntax">STREAM_OPEN_TO_FILE_APPEND</span><span class="plain-syntax">(</span><span class="identifier-syntax">new</span><span class="plain-syntax">, </span><span class="identifier-syntax">fn</span><span class="plain-syntax">, </span><span class="identifier-syntax">enc</span><span class="plain-syntax">) </span><a href="2-str.html#SP25" class="function-link"><span class="function-syntax">Streams::open_to_file_append</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">new</span><span class="plain-syntax">, </span><span class="identifier-syntax">fn</span><span class="plain-syntax">, </span><span class="identifier-syntax">enc</span><span class="plain-syntax">)</span>
<span class="definition-keyword">define</span> <span class="identifier-syntax">STREAM_OPEN_IN_MEMORY</span><span class="plain-syntax">(</span><span class="identifier-syntax">new</span><span class="plain-syntax">) </span><a href="2-str.html#SP26" class="function-link"><span class="function-syntax">Streams::open_to_memory</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">new</span><span class="plain-syntax">, </span><span class="constant-syntax">20480</span><span class="plain-syntax">)</span>
<span class="definition-keyword">define</span> <span class="identifier-syntax">STREAM_CLOSE</span><span class="plain-syntax">(</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) </span><a href="2-str.html#SP34" class="function-link"><span class="function-syntax">Streams::close</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">stream</span><span class="plain-syntax">)</span>
2019-02-04 22:26:45 +00:00
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP10"></a><b>&#167;10. </b>The following operation is equivalent to <span class="extract"><span class="extract-syntax">fflush</span></span> and makes it more likely
2019-02-04 22:26:45 +00:00
(I put it no higher) that the text written to a stream has all actually been
copied onto the disc, rather than sitting in some operating system buffer.
This helps ensure that any debugging log is up to the minute, in case of
a crash, but its absence wouldn't hurt our normal function. Flushing
a memory stream is legal but does nothing.
</p>
<pre class="definitions"><span class="definition-keyword">define</span> <span class="identifier-syntax">STREAM_FLUSH</span><span class="plain-syntax">(</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) </span><a href="2-str.html#SP33" class="function-link"><span class="function-syntax">Streams::flush</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">stream</span><span class="plain-syntax">)</span>
2019-02-04 22:26:45 +00:00
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP11"></a><b>&#167;11. </b>A piece of information we can read for any stream is the number of characters
2019-02-04 22:26:45 +00:00
written to it: its "extent". In fact, UTF-8 multi-byte encoding schemes,
2020-04-22 22:57:09 +00:00
together with differing platform interpretations of C's <span class="extract"><span class="extract-syntax">'\n'</span></span>, mean that this
2019-02-04 22:26:45 +00:00
extent is not necessarily either the final file size in bytes or the final
number of human-readable characters. We will only actually use it to detect
whether text has, or has not, been written to a stream between two points in
time, by seeing whether or not it has increased.
</p>
<pre class="definitions"><span class="definition-keyword">define</span> <span class="identifier-syntax">STREAM_EXTENT</span><span class="plain-syntax">(</span><span class="identifier-syntax">x</span><span class="plain-syntax">) </span><a href="2-str.html#SP38" class="function-link"><span class="function-syntax">Streams::get_position</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">x</span><span class="plain-syntax">)</span>
2019-02-04 22:26:45 +00:00
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP12"></a><b>&#167;12. </b>The remaining operations are available only for streams in memory (well, and
2020-04-22 22:57:09 +00:00
for <span class="extract"><span class="extract-syntax">NULL</span></span>, but of course they do nothing when applied to that). While they
2019-02-04 22:26:45 +00:00
could be provided for file streams, this would be so inefficient that we will
pretend it is impossible. Any function which might need to use one
of these operations should open with the following sentinel macro:
</p>
<pre class="definitions"><span class="definition-keyword">define</span> <span class="identifier-syntax">STREAM_MUST_BE_IN_MEMORY</span><span class="plain-syntax">(</span><span class="identifier-syntax">x</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">x</span><span class="plain-syntax"> != </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">x</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_memory</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"text_stream not in memory"</span><span class="plain-syntax">);</span>
2019-02-04 22:26:45 +00:00
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP13"></a><b>&#167;13. </b>First, we can erase one or more recently written characters:
2019-02-04 22:26:45 +00:00
</p>
<pre class="definitions"><span class="definition-keyword">define</span> <span class="identifier-syntax">STREAM_BACKSPACE</span><span class="plain-syntax">(</span><span class="identifier-syntax">x</span><span class="plain-syntax">) </span><a href="2-str.html#SP41" class="function-link"><span class="function-syntax">Streams::set_position</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">x</span><span class="plain-syntax">, </span><a href="2-str.html#SP38" class="function-link"><span class="function-syntax">Streams::get_position</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">x</span><span class="plain-syntax">) - </span><span class="constant-syntax">1</span><span class="plain-syntax">)</span>
<span class="definition-keyword">define</span> <span class="identifier-syntax">STREAM_ERASE_BACK_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">start_position</span><span class="plain-syntax">) </span><a href="2-str.html#SP41" class="function-link"><span class="function-syntax">Streams::set_position</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="identifier-syntax">start_position</span><span class="plain-syntax">)</span>
2019-02-04 22:26:45 +00:00
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP14"></a><b>&#167;14. </b>Second, we can look at the text written. The minimal form is to look at
2019-02-04 22:26:45 +00:00
just the most recent character, but we can also copy one entire memory
stream into another stream (where the target can be either a memory or file
stream).
</p>
<pre class="definitions"><span class="definition-keyword">define</span> <span class="identifier-syntax">STREAM_MOST_RECENT_CHAR</span><span class="plain-syntax">(</span><span class="identifier-syntax">x</span><span class="plain-syntax">) </span><a href="2-str.html#SP39" class="function-link"><span class="function-syntax">Streams::latest</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">x</span><span class="plain-syntax">)</span>
<span class="definition-keyword">define</span> <span class="identifier-syntax">STREAM_COPY</span><span class="plain-syntax">(</span><span class="identifier-syntax">to</span><span class="plain-syntax">, </span><span class="identifier-syntax">from</span><span class="plain-syntax">) </span><a href="2-str.html#SP42" class="function-link"><span class="function-syntax">Streams::copy</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">to</span><span class="plain-syntax">, </span><span class="identifier-syntax">from</span><span class="plain-syntax">)</span>
2019-02-04 22:26:45 +00:00
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP15"></a><b>&#167;15. </b>So much for the definition; now the implementation. Here is the <span class="extract"><span class="extract-syntax">text_stream</span></span>
2019-02-04 22:26:45 +00:00
structure. Open memory streams are represented by structures where
2020-04-22 22:57:09 +00:00
<span class="extract"><span class="extract-syntax">write_to_memory</span></span> is valid, open file streams by those where <span class="extract"><span class="extract-syntax">write_to_file</span></span>
is valid. That counts every open stream except <span class="extract"><span class="extract-syntax">NULL</span></span>, which of course
doesn't point to a <span class="extract"><span class="extract-syntax">text_stream</span></span> structure at all.
2019-02-04 22:26:45 +00:00
</p>
2020-04-24 23:06:02 +00:00
<p class="commentary">Any stream can have <span class="extract"><span class="extract-syntax">USES_XML_ESCAPES_STRF</span></span> set or cleared. When this is set, the
2020-04-22 22:57:09 +00:00
XML (and HTML) escapes of <span class="extract"><span class="extract-syntax">&amp;amp;</span></span> for ampersand, and <span class="extract"><span class="extract-syntax">&amp;lt;</span></span> and <span class="extract"><span class="extract-syntax">&amp;gt;</span></span> for
2019-02-04 22:26:45 +00:00
angle brackets, will be used automatically on writing. By default this flag
is clear, that is, no conversion is made.
</p>
2020-04-24 23:06:02 +00:00
<pre class="definitions"><span class="definition-keyword">define</span> <span class="constant-syntax">MALLOCED_STRF</span><span class="plain-syntax"> </span><span class="constant-syntax">0x00000001</span><span class="plain-syntax"> </span><span class="comment-syntax"> was the </span><span class="extract"><span class="extract-syntax">write_to_memory</span></span><span class="comment-syntax"> pointer claimed by </span><span class="extract"><span class="extract-syntax">malloc</span></span><span class="comment-syntax">?</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">USES_XML_ESCAPES_STRF</span><span class="plain-syntax"> </span><span class="constant-syntax">0x00000002</span><span class="plain-syntax"> </span><span class="comment-syntax"> see above</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">USES_LOG_ESCAPES_STRF</span><span class="plain-syntax"> </span><span class="constant-syntax">0x00000004</span><span class="plain-syntax"> </span><span class="comment-syntax"> </span><span class="extract"><span class="extract-syntax">WRITE</span></span><span class="comment-syntax"> to this stream supports </span><span class="extract"><span class="extract-syntax">$</span></span><span class="comment-syntax"> escapes</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">INDENT_PENDING_STRF</span><span class="plain-syntax"> </span><span class="constant-syntax">0x00000008</span><span class="plain-syntax"> </span><span class="comment-syntax"> we have just ended a line, so further text should indent</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">FILE_ENCODING_ISO_STRF</span><span class="plain-syntax"> </span><span class="constant-syntax">0x00000010</span><span class="plain-syntax"> </span><span class="comment-syntax"> relevant only for file streams</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">FILE_ENCODING_UTF8_STRF</span><span class="plain-syntax"> </span><span class="constant-syntax">0x00000020</span><span class="plain-syntax"> </span><span class="comment-syntax"> relevant only for file streams</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">FOR_RE_STRF</span><span class="plain-syntax"> </span><span class="constant-syntax">0x00000100</span><span class="plain-syntax"> </span><span class="comment-syntax"> for debugging only</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">FOR_TT_STRF</span><span class="plain-syntax"> </span><span class="constant-syntax">0x00000200</span><span class="plain-syntax"> </span><span class="comment-syntax"> for debugging only</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">FOR_CO_STRF</span><span class="plain-syntax"> </span><span class="constant-syntax">0x00000400</span><span class="plain-syntax"> </span><span class="comment-syntax"> for debugging only</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">FOR_FI_STRF</span><span class="plain-syntax"> </span><span class="constant-syntax">0x00000800</span><span class="plain-syntax"> </span><span class="comment-syntax"> for debugging only</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">FOR_OM_STRF</span><span class="plain-syntax"> </span><span class="constant-syntax">0x00001000</span><span class="plain-syntax"> </span><span class="comment-syntax"> for debugging only</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">USES_I6_ESCAPES_STRF</span><span class="plain-syntax"> </span><span class="constant-syntax">0x00002000</span><span class="plain-syntax"> </span><span class="comment-syntax"> as if an Inform 6 string</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">READ_ONLY_STRF</span><span class="plain-syntax"> </span><span class="constant-syntax">0x00008000</span>
2020-04-24 23:06:02 +00:00
<span class="definition-keyword">define</span> <span class="constant-syntax">INDENTATION_BASE_STRF</span><span class="plain-syntax"> </span><span class="constant-syntax">0x00010000</span><span class="plain-syntax"> </span><span class="comment-syntax"> number of tab stops in from the left margin</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">INDENTATION_MASK_STRF</span><span class="plain-syntax"> </span><span class="constant-syntax">0x0FFF0000</span><span class="plain-syntax"> </span><span class="comment-syntax"> (held in these bits)</span>
2019-02-04 22:26:45 +00:00
</pre>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> {</span>
2020-04-24 23:06:02 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">stream_flags</span><span class="plain-syntax">; </span><span class="comment-syntax"> bitmap of the </span><span class="extract"><span class="extract-syntax">*_STRF</span></span><span class="comment-syntax"> values above</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">FILE</span><span class="plain-syntax"> *</span><span class="identifier-syntax">write_to_file</span><span class="plain-syntax">; </span><span class="comment-syntax"> for an open stream, exactly one of these is </span><span class="extract"><span class="extract-syntax">NULL</span></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">HTML_file_state</span><span class="plain-syntax"> *</span><span class="identifier-syntax">as_HTML</span><span class="plain-syntax">; </span><span class="comment-syntax"> relevant only to the </span><span class="extract"><span class="extract-syntax">HTML::</span></span><span class="comment-syntax"> section</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> *</span><span class="identifier-syntax">write_to_memory</span><span class="plain-syntax">;</span>
2020-04-24 23:06:02 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">filename</span><span class="plain-syntax"> *</span><span class="identifier-syntax">file_written</span><span class="plain-syntax">; </span><span class="comment-syntax"> ditto</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">chars_written</span><span class="plain-syntax">; </span><span class="comment-syntax"> number of characters sent, counting </span><span class="extract"><span class="extract-syntax">\n</span></span><span class="comment-syntax"> as 1</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">chars_capacity</span><span class="plain-syntax">; </span><span class="comment-syntax"> maximum number the stream can accept without claiming more resources</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream_continues</span><span class="plain-syntax">; </span><span class="comment-syntax"> if one memory stream is extended by another</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax">} </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>The structure text_stream is accessed in 2/wal, 4/pm and here.</li></ul>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP16"></a><b>&#167;16. </b>A theological question: what is the text encoding for the null stream?
2019-02-04 22:26:45 +00:00
</p>
<pre class="definitions"><span class="definition-keyword">define</span> <span class="identifier-syntax">STREAM_USES_UTF8</span><span class="plain-syntax">(</span><span class="identifier-syntax">x</span><span class="plain-syntax">) ((</span><span class="identifier-syntax">x</span><span class="plain-syntax">)?((</span><span class="identifier-syntax">x</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax">) &amp; </span><span class="constant-syntax">FILE_ENCODING_UTF8_STRF</span><span class="plain-syntax">):</span><span class="constant-syntax">FALSE</span><span class="plain-syntax">)</span>
2019-02-04 22:26:45 +00:00
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP17"></a><b>&#167;17. </b>When text is stored at <span class="extract"><span class="extract-syntax">write_to_memory</span></span>, it is kept as a zero-terminated C
2019-02-04 22:26:45 +00:00
wide string, with one word per Unicode code point. It turns out to be
efficient to preserve a small margin of clear space at the end of the space,
2020-04-22 22:57:09 +00:00
so out of the <span class="extract"><span class="extract-syntax">chars_capacity</span></span> space, the following amount will be kept clear:
2019-02-04 22:26:45 +00:00
</p>
<pre class="definitions"><span class="definition-keyword">define</span> <span class="constant-syntax">SPACE_AT_END_OF_STREAM</span><span class="plain-syntax"> </span><span class="constant-syntax">6</span>
2019-02-04 22:26:45 +00:00
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP18"></a><b>&#167;18. </b>A statistic we keep, since it costs little:
2019-02-04 22:26:45 +00:00
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">total_file_writes</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="comment-syntax"> number of text files opened for writing during the run</span>
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP19"></a><b>&#167;19. Initialising the stream structure. </b>Note that the following fills in sensible defaults for every field, but the
2019-02-04 22:26:45 +00:00
result is not a valid open stream; it's a blank form ready to be filled in.
</p>
2020-04-24 23:06:02 +00:00
<p class="commentary">By default the upper limit on file size is 2 GB. It's very hard to see this
2019-02-04 22:26:45 +00:00
ever being approached for any tool associated with the Inform project, where
text files have a size which is proportionate to the result of human writing.
The only output file with a sorceror's-apprentice-like ability to grow and
grow is the debugging file, and if it should reach 2 GB then it deserves to be
truncated and we will shed no tears.
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::initialise</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <b>Streams::initialise</b>:<br><a href="2-str.html#SP22">&#167;22</a>, <a href="2-str.html#SP23">&#167;23</a>, <a href="2-str.html#SP24">&#167;24</a>, <a href="2-str.html#SP25">&#167;25</a>, <a href="2-str.html#SP26">&#167;26</a>, <a href="2-str.html#SP27">&#167;27</a>, <a href="2-str.html#SP35_3">&#167;35.3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">from</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"tried to initialise NULL stream"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_file</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_memory</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_written</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_capacity</span><span class="plain-syntax"> = </span><span class="constant-syntax">2147483647</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_continues</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">as_HTML</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">file_written</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP20"></a><b>&#167;20. </b>Any stream can have the following flag set or cleared. When this is set, the
2020-04-22 22:57:09 +00:00
XML (and HTML) escapes of <span class="extract"><span class="extract-syntax">&amp;amp;</span></span> for ampersand, and <span class="extract"><span class="extract-syntax">&amp;lt;</span></span> and <span class="extract"><span class="extract-syntax">&amp;gt;</span></span> for
2019-02-04 22:26:45 +00:00
angle brackets, will be used automatically on writing. By default this flag
is clear, that is, no conversion is made.
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::enable_XML_escapes</span><button class="popup" onclick="togglePopup('usagePopup2')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup2">Usage of <b>Streams::enable_XML_escapes</b>:<br>none</span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> |= </span><span class="constant-syntax">USES_XML_ESCAPES_STRF</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::disable_XML_escapes</span><button class="popup" onclick="togglePopup('usagePopup3')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup3">Usage of <b>Streams::disable_XML_escapes</b>:<br>none</span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> &amp; </span><span class="constant-syntax">USES_XML_ESCAPES_STRF</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> -= </span><span class="constant-syntax">USES_XML_ESCAPES_STRF</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">I6_escapes_globally_enabled</span><span class="plain-syntax"> = </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">;</span>
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::enable_I6_escapes</span><button class="popup" onclick="togglePopup('usagePopup4')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup4">Usage of <b>Streams::enable_I6_escapes</b>:<br>none</span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> |= </span><span class="constant-syntax">USES_I6_ESCAPES_STRF</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">I6_escapes_globally_enabled</span><span class="plain-syntax"> = </span><span class="constant-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::disable_I6_escapes</span><button class="popup" onclick="togglePopup('usagePopup5')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup5">Usage of <b>Streams::disable_I6_escapes</b>:<br>none</span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> &amp; </span><span class="constant-syntax">USES_I6_ESCAPES_STRF</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> -= </span><span class="constant-syntax">USES_I6_ESCAPES_STRF</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">I6_escapes_globally_enabled</span><span class="plain-syntax"> = </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::I6_escapes_enabled</span><button class="popup" onclick="togglePopup('usagePopup6')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup6">Usage of <b>Streams::I6_escapes_enabled</b>:<br>none</span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">I6_escapes_globally_enabled</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::enable_debugging</span><button class="popup" onclick="togglePopup('usagePopup7')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup7">Usage of <b>Streams::enable_debugging</b>:<br>Debugging Log - <a href="2-dl.html#SP5">&#167;5</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> |= </span><span class="constant-syntax">USES_LOG_ESCAPES_STRF</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::disable_debugging</span><button class="popup" onclick="togglePopup('usagePopup8')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup8">Usage of <b>Streams::disable_debugging</b>:<br>none</span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> &amp; </span><span class="constant-syntax">USES_LOG_ESCAPES_STRF</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> -= </span><span class="constant-syntax">USES_LOG_ESCAPES_STRF</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::mark_as_read_only</span><button class="popup" onclick="togglePopup('usagePopup9')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup9">Usage of <b>Streams::mark_as_read_only</b>:<br>String Manipulation - <a href="4-sm.html#SP27_1">&#167;27.1</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> |= </span><span class="constant-syntax">READ_ONLY_STRF</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::declare_as_HTML</span><button class="popup" onclick="togglePopup('usagePopup10')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup10">Usage of <b>Streams::declare_as_HTML</b>:<br>HTML - <a href="5-htm.html#SP2">&#167;2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="reserved-syntax">HTML_file_state</span><span class="plain-syntax"> *</span><span class="identifier-syntax">hs</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">as_HTML</span><span class="plain-syntax"> = </span><span class="identifier-syntax">hs</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">HTML_file_state</span><span class="plain-syntax"> *</span><span class="function-syntax">Streams::get_HTML_file_state</span><button class="popup" onclick="togglePopup('usagePopup11')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup11">Usage of <b>Streams::get_HTML_file_state</b>:<br>HTML - <a href="5-htm.html#SP3">&#167;3</a>, <a href="5-htm.html#SP4">&#167;4</a>, <a href="5-htm.html#SP5">&#167;5</a>, <a href="5-htm.html#SP7">&#167;7</a>, <a href="5-htm.html#SP8">&#167;8</a>, <a href="5-htm.html#SP10">&#167;10</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">as_HTML</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP21"></a><b>&#167;21. Logging. </b></p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::log</span><button class="popup" onclick="togglePopup('usagePopup12')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup12">Usage of <b>Streams::log</b>:<br>Foundation Module - <a href="1-fm.html#SP8_3">&#167;8.3</a></span></button><span class="plain-syntax">(</span><span class="constant-syntax">OUTPUT_STREAM</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> *</span><span class="identifier-syntax">vS</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax"> = (</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *) </span><span class="identifier-syntax">vS</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"NULL"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_file</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"F'%f'(%d)"</span><span class="plain-syntax">, </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">file_written</span><span class="plain-syntax">, </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_written</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"S%x("</span><span class="plain-syntax">, (</span><span class="reserved-syntax">long</span><span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax">) </span><span class="identifier-syntax">stream</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"%d/%d"</span><span class="plain-syntax">, </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_written</span><span class="plain-syntax">, </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_capacity</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_continues</span><span class="plain-syntax">) </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"+"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax"> = </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_continues</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">")"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax">}</span>
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP22"></a><b>&#167;22. Standard I/O wrappers. </b>The first call to <span class="extract"><span class="extract-syntax">Streams::get_stdout()</span></span> creates a suitable wrapper for <span class="extract"><span class="extract-syntax">stdout</span></span>
2020-04-22 22:57:09 +00:00
and returns a <span class="extract"><span class="extract-syntax">text_stream *</span></span> pointer to it; subsequent calls just return this wrapper.
2019-02-04 22:26:45 +00:00
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
<span class="reserved-syntax">text_stream</span><span class="plain-syntax"> </span><span class="identifier-syntax">STDOUT_struct</span><span class="plain-syntax">; </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">stdout_wrapper_initialised</span><span class="plain-syntax"> = </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">;</span>
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="function-syntax">Streams::get_stdout</span><button class="popup" onclick="togglePopup('usagePopup13')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup13">Usage of <b>Streams::get_stdout</b>:<br><a href="2-str.html#SP5">&#167;5</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stdout_wrapper_initialised</span><span class="plain-syntax"> == </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">) {</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><a href="2-str.html#SP19" class="function-link"><span class="function-syntax">Streams::initialise</span></a><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">STDOUT_struct</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">); </span><span class="identifier-syntax">STDOUT_struct</span><span class="plain-syntax">.</span><span class="element-syntax">write_to_file</span><span class="plain-syntax"> = </span><span class="identifier-syntax">stdout</span><span class="plain-syntax">;</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="identifier-syntax">stdout_wrapper_initialised</span><span class="plain-syntax"> = </span><span class="constant-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="constant-syntax">LOCALE_IS_ISO</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">STDOUT_struct</span><span class="plain-syntax">.</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> |= </span><span class="constant-syntax">FILE_ENCODING_ISO_STRF</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOCALE_IS_UTF8</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">STDOUT_struct</span><span class="plain-syntax">.</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> |= </span><span class="constant-syntax">FILE_ENCODING_UTF8_STRF</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> &amp;</span><span class="identifier-syntax">STDOUT_struct</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP23"></a><b>&#167;23. </b>And similarly for the standard error file.
2019-02-04 22:26:45 +00:00
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
<span class="reserved-syntax">text_stream</span><span class="plain-syntax"> </span><span class="identifier-syntax">STDERR_struct</span><span class="plain-syntax">; </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">stderr_wrapper_initialised</span><span class="plain-syntax"> = </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">;</span>
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="function-syntax">Streams::get_stderr</span><button class="popup" onclick="togglePopup('usagePopup14')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup14">Usage of <b>Streams::get_stderr</b>:<br><a href="2-str.html#SP5">&#167;5</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stderr_wrapper_initialised</span><span class="plain-syntax"> == </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">) {</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><a href="2-str.html#SP19" class="function-link"><span class="function-syntax">Streams::initialise</span></a><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">STDERR_struct</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">); </span><span class="identifier-syntax">STDERR_struct</span><span class="plain-syntax">.</span><span class="element-syntax">write_to_file</span><span class="plain-syntax"> = </span><span class="identifier-syntax">stderr</span><span class="plain-syntax">;</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="identifier-syntax">stderr_wrapper_initialised</span><span class="plain-syntax"> = </span><span class="constant-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="constant-syntax">LOCALE_IS_ISO</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">STDERR_struct</span><span class="plain-syntax">.</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> |= </span><span class="constant-syntax">FILE_ENCODING_ISO_STRF</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOCALE_IS_UTF8</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">STDERR_struct</span><span class="plain-syntax">.</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> |= </span><span class="constant-syntax">FILE_ENCODING_UTF8_STRF</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> &amp;</span><span class="identifier-syntax">STDERR_struct</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP24"></a><b>&#167;24. Creating file streams. </b>Note that this can fail, if the host filing system refuses to open the file,
2020-04-22 22:57:09 +00:00
so we return <span class="extract"><span class="extract-syntax">TRUE</span></span> if and only if successful.
2019-02-04 22:26:45 +00:00
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::open_to_file</span><button class="popup" onclick="togglePopup('usagePopup15')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup15">Usage of <b>Streams::open_to_file</b>:<br><a href="2-str.html#SP9">&#167;9</a>, Build Files - <a href="8-bf.html#SP4">&#167;4</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="reserved-syntax">filename</span><span class="plain-syntax"> *</span><span class="identifier-syntax">name</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">encoding</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"tried to open NULL stream"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">name</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"stream_open_to_file on null filename"</span><span class="plain-syntax">);</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><a href="2-str.html#SP19" class="function-link"><span class="function-syntax">Streams::initialise</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="constant-syntax">FOR_FI_STRF</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax">(</span><span class="identifier-syntax">encoding</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">UTF8_ENC:</span><span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> |= </span><span class="constant-syntax">FILE_ENCODING_UTF8_STRF</span><span class="plain-syntax">; </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">ISO_ENC:</span><span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> |= </span><span class="constant-syntax">FILE_ENCODING_ISO_STRF</span><span class="plain-syntax">; </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">default:</span><span class="plain-syntax"> </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"stream has unknown text encoding"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_file</span><span class="plain-syntax"> = </span><a href="3-fln.html#SP10" class="function-link"><span class="function-syntax">Filenames::fopen</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">name</span><span class="plain-syntax">, </span><span class="string-syntax">"w"</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_file</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">file_written</span><span class="plain-syntax"> = </span><span class="identifier-syntax">name</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">total_file_writes</span><span class="plain-syntax">++;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP25"></a><b>&#167;25. </b>Similarly for appending:
2019-02-04 22:26:45 +00:00
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::open_to_file_append</span><button class="popup" onclick="togglePopup('usagePopup16')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup16">Usage of <b>Streams::open_to_file_append</b>:<br><a href="2-str.html#SP9">&#167;9</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="reserved-syntax">filename</span><span class="plain-syntax"> *</span><span class="identifier-syntax">name</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">encoding</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"tried to open NULL stream"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">name</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"stream_open_to_file on null filename"</span><span class="plain-syntax">);</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><a href="2-str.html#SP19" class="function-link"><span class="function-syntax">Streams::initialise</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="constant-syntax">FOR_FI_STRF</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax">(</span><span class="identifier-syntax">encoding</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">UTF8_ENC:</span><span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> |= </span><span class="constant-syntax">FILE_ENCODING_UTF8_STRF</span><span class="plain-syntax">; </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">ISO_ENC:</span><span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> |= </span><span class="constant-syntax">FILE_ENCODING_ISO_STRF</span><span class="plain-syntax">; </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">default:</span><span class="plain-syntax"> </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"stream has unknown text encoding"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_file</span><span class="plain-syntax"> = </span><a href="3-fln.html#SP10" class="function-link"><span class="function-syntax">Filenames::fopen</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">name</span><span class="plain-syntax">, </span><span class="string-syntax">"a"</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_file</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">total_file_writes</span><span class="plain-syntax">++;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP26"></a><b>&#167;26. Creating memory streams. </b>Here we have a choice. One option is to use <span class="extract"><span class="extract-syntax">malloc</span></span> to allocate memory to hold
2019-02-04 22:26:45 +00:00
the text of the stream; this too can fail for host platform reasons, so again
we return a success code.
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::open_to_memory</span><button class="popup" onclick="togglePopup('usagePopup17')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup17">Usage of <b>Streams::open_to_memory</b>:<br><a href="2-str.html#SP9">&#167;9</a>, <a href="2-str.html#SP28_3">&#167;28.3</a>, String Manipulation - <a href="4-sm.html#SP2">&#167;2</a>, <a href="4-sm.html#SP3">&#167;3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">capacity</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="identifier-syntax">CREATE_MUTEX</span><span class="plain-syntax">(</span><span class="identifier-syntax">mutex</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOCK_MUTEX</span><span class="plain-syntax">(</span><span class="identifier-syntax">mutex</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"tried to open NULL stream"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">capacity</span><span class="plain-syntax"> += </span><span class="constant-syntax">SPACE_AT_END_OF_STREAM</span><span class="plain-syntax">;</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><a href="2-str.html#SP19" class="function-link"><span class="function-syntax">Streams::initialise</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="constant-syntax">FOR_OM_STRF</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_memory</span><span class="plain-syntax"> = </span><a href="2-mmr.html#SP25" class="function-link"><span class="function-syntax">Memory::calloc</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">capacity</span><span class="plain-syntax">, </span><span class="reserved-syntax">sizeof</span><span class="plain-syntax">(</span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax">), </span><span class="constant-syntax">STREAM_MREASON</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_memory</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_memory</span><span class="plain-syntax">)[0] = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> |= </span><span class="constant-syntax">MALLOCED_STRF</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_capacity</span><span class="plain-syntax"> = </span><span class="identifier-syntax">capacity</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">UNLOCK_MUTEX</span><span class="plain-syntax">(</span><span class="identifier-syntax">mutex</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP27"></a><b>&#167;27. </b>The other option avoids <span class="extract"><span class="extract-syntax">malloc</span></span> by using specific storage already available.
2019-02-04 22:26:45 +00:00
If called validly, this cannot fail.
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">text_stream</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::new_buffer</span><button class="popup" onclick="togglePopup('usagePopup18')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup18">Usage of <b>Streams::new_buffer</b>:<br><a href="2-str.html#SP8">&#167;8</a>, Pattern Matching - <a href="4-pm.html#SP10">&#167;10</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">capacity</span><span class="plain-syntax">, </span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> *</span><span class="identifier-syntax">at</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">at</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"tried to make stream wrapper for NULL string"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">capacity</span><span class="plain-syntax"> &lt; </span><span class="constant-syntax">SPACE_AT_END_OF_STREAM</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"memory stream too small"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">;</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><a href="2-str.html#SP19" class="function-link"><span class="function-syntax">Streams::initialise</span></a><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="constant-syntax">FOR_TT_STRF</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">.</span><span class="identifier-syntax">write_to_memory</span><span class="plain-syntax"> = </span><span class="identifier-syntax">at</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">.</span><span class="element-syntax">write_to_memory</span><span class="plain-syntax">)[0] = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">.</span><span class="identifier-syntax">chars_capacity</span><span class="plain-syntax"> = </span><span class="identifier-syntax">capacity</span><span class="plain-syntax"> - </span><span class="constant-syntax">SPACE_AT_END_OF_STREAM</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP28"></a><b>&#167;28. Converting from C strings. </b>We then have three ways to open a stream whose initial contents are given
2019-02-04 22:26:45 +00:00
by a C string. First, a wide string (a sequence of 32-bit Unicode code
points, null terminated):
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::open_from_wide_string</span><button class="popup" onclick="togglePopup('usagePopup19')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup19">Usage of <b>Streams::open_from_wide_string</b>:<br>String Manipulation - <a href="4-sm.html#SP4">&#167;4</a>, <a href="4-sm.html#SP5">&#167;5</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> *</span><span class="identifier-syntax">c_string</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"tried to open NULL stream"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">capacity</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">c_string</span><span class="plain-syntax">)?((</span><span class="reserved-syntax">int</span><span class="plain-syntax">) </span><span class="identifier-syntax">wcslen</span><span class="plain-syntax">(</span><span class="identifier-syntax">c_string</span><span class="plain-syntax">)):0;</span>
2020-04-24 23:06:02 +00:00
<span class="plain-syntax"> </span><span class="named-paragraph-container"><a href="2-str.html#SP28_3" class="named-paragraph-link"><span class="named-paragraph">Ensure a capacity large enough to hold the initial string in one frame</span><span class="named-paragraph-number">28.3</span></span></a><span class="plain-syntax">;</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">c_string</span><span class="plain-syntax">) </span><a href="2-str.html#SP28" class="function-link"><span class="function-syntax">Streams::write_wide_string</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="identifier-syntax">c_string</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::write_wide_string</span><button class="popup" onclick="togglePopup('usagePopup20')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup20">Usage of <b>Streams::write_wide_string</b>:<br>String Manipulation - <a href="4-sm.html#SP18">&#167;18</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> *</span><span class="identifier-syntax">c_string</span><span class="plain-syntax">) {</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">c_string</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">]; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++) </span><a href="2-str.html#SP35" class="function-link"><span class="function-syntax">Streams::putc</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">c_string</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">], </span><span class="identifier-syntax">stream</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax">}</span>
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP28_1"></a><b>&#167;28.1. </b>Similarly, an ISO string (a sequence of 8-bit code points in the first
2019-02-04 22:26:45 +00:00
page of the Unicode set, null terminated):
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::open_from_ISO_string</span><button class="popup" onclick="togglePopup('usagePopup21')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup21">Usage of <b>Streams::open_from_ISO_string</b>:<br><a href="2-str.html#SP32">&#167;32</a>, String Manipulation - <a href="4-sm.html#SP4">&#167;4</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">c_string</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"tried to open NULL stream"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">capacity</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">c_string</span><span class="plain-syntax">)?((</span><span class="reserved-syntax">int</span><span class="plain-syntax">) </span><span class="identifier-syntax">strlen</span><span class="plain-syntax">(</span><span class="identifier-syntax">c_string</span><span class="plain-syntax">)):0;</span>
2020-04-24 23:06:02 +00:00
<span class="plain-syntax"> </span><span class="named-paragraph-container"><a href="2-str.html#SP28_3" class="named-paragraph-link"><span class="named-paragraph">Ensure a capacity large enough to hold the initial string in one frame</span><span class="named-paragraph-number">28.3</span></span></a><span class="plain-syntax">;</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">c_string</span><span class="plain-syntax">) </span><a href="2-str.html#SP28_1" class="function-link"><span class="function-syntax">Streams::write_ISO_string</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="identifier-syntax">c_string</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::write_ISO_string</span><button class="popup" onclick="togglePopup('usagePopup22')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup22">Usage of <b>Streams::write_ISO_string</b>:<br><a href="2-str.html#SP32">&#167;32</a>, String Manipulation - <a href="4-sm.html#SP18">&#167;18</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">c_string</span><span class="plain-syntax">) {</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">c_string</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">]; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++) </span><a href="2-str.html#SP35" class="function-link"><span class="function-syntax">Streams::putc</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">c_string</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">], </span><span class="identifier-syntax">stream</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax">}</span>
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP28_2"></a><b>&#167;28.2. </b>Finally, a UTF-8 encoded C string:
2019-02-04 22:26:45 +00:00
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::open_from_UTF8_string</span><button class="popup" onclick="togglePopup('usagePopup23')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup23">Usage of <b>Streams::open_from_UTF8_string</b>:<br><a href="2-str.html#SP32">&#167;32</a>, String Manipulation - <a href="4-sm.html#SP4">&#167;4</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">c_string</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"tried to open NULL stream"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">capacity</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">c_string</span><span class="plain-syntax">)?((</span><span class="reserved-syntax">int</span><span class="plain-syntax">) </span><span class="identifier-syntax">strlen</span><span class="plain-syntax">(</span><span class="identifier-syntax">c_string</span><span class="plain-syntax">)):0;</span>
2020-04-24 23:06:02 +00:00
<span class="plain-syntax"> </span><span class="named-paragraph-container"><a href="2-str.html#SP28_3" class="named-paragraph-link"><span class="named-paragraph">Ensure a capacity large enough to hold the initial string in one frame</span><span class="named-paragraph-number">28.3</span></span></a><span class="plain-syntax">;</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">c_string</span><span class="plain-syntax">) </span><a href="2-str.html#SP28_2" class="function-link"><span class="function-syntax">Streams::write_UTF8_string</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="identifier-syntax">c_string</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::write_UTF8_string</span><button class="popup" onclick="togglePopup('usagePopup24')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup24">Usage of <b>Streams::write_UTF8_string</b>:<br><a href="2-str.html#SP32">&#167;32</a>, String Manipulation - <a href="4-sm.html#SP18">&#167;18</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">c_string</span><span class="plain-syntax">) {</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">unicode_file_buffer</span><span class="plain-syntax"> </span><span class="identifier-syntax">ufb</span><span class="plain-syntax"> = </span><a href="4-tf.html#SP8" class="function-link"><span class="function-syntax">TextFiles::create_ufb</span></a><span class="plain-syntax">();</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">c</span><span class="plain-syntax">;</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">c</span><span class="plain-syntax"> = </span><a href="4-tf.html#SP8" class="function-link"><span class="function-syntax">TextFiles::utf8_fgetc</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, &amp;</span><span class="identifier-syntax">c_string</span><span class="plain-syntax">, </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">, &amp;</span><span class="identifier-syntax">ufb</span><span class="plain-syntax">)) != </span><span class="constant-syntax">0</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><a href="2-str.html#SP35" class="function-link"><span class="function-syntax">Streams::putc</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">c</span><span class="plain-syntax">, </span><span class="identifier-syntax">stream</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax">}</span>
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP28_3"></a><b>&#167;28.3. </b>...all of which use:
2019-02-04 22:26:45 +00:00
</p>
2020-04-24 23:06:02 +00:00
<p class="commentary"><span class="named-paragraph-container"><span class="named-paragraph-defn">Ensure a capacity large enough to hold the initial string in one frame</span><span class="named-paragraph-number">28.3</span></span><span class="comment-syntax"> =</span>
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">capacity</span><span class="plain-syntax"> &lt; </span><span class="constant-syntax">8</span><span class="plain-syntax">) </span><span class="identifier-syntax">capacity</span><span class="plain-syntax"> = </span><span class="constant-syntax">8</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">capacity</span><span class="plain-syntax"> += </span><span class="constant-syntax">1</span><span class="plain-syntax">+</span><span class="constant-syntax">SPACE_AT_END_OF_STREAM</span><span class="plain-syntax">;</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">rv</span><span class="plain-syntax"> = </span><a href="2-str.html#SP26" class="function-link"><span class="function-syntax">Streams::open_to_memory</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="identifier-syntax">capacity</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">rv</span><span class="plain-syntax"> == </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-str.html#SP28">&#167;28</a>, <a href="2-str.html#SP28_1">&#167;28.1</a>, <a href="2-str.html#SP28_2">&#167;28.2</a>.</li></ul>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP29"></a><b>&#167;29. Converting to C strings. </b>Now for the converse problem.
2019-02-04 22:26:45 +00:00
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::write_as_wide_string</span><button class="popup" onclick="togglePopup('usagePopup25')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup25">Usage of <b>Streams::write_as_wide_string</b>:<br>String Manipulation - <a href="4-sm.html#SP6">&#167;6</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> *</span><span class="identifier-syntax">C_string</span><span class="plain-syntax">, </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">buffer_size</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">buffer_size</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) { </span><span class="identifier-syntax">C_string</span><span class="plain-syntax">[0] = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="reserved-syntax">return</span><span class="plain-syntax">; }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_file</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"stream_get_text on file stream"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">j</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">j</span><span class="plain-syntax">&lt;</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_written</span><span class="plain-syntax">; </span><span class="identifier-syntax">j</span><span class="plain-syntax">++) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">i</span><span class="plain-syntax"> &gt;= </span><span class="identifier-syntax">buffer_size</span><span class="plain-syntax">-1) </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">C_string</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">++] = </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_memory</span><span class="plain-syntax">[</span><span class="identifier-syntax">j</span><span class="plain-syntax">];</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax"> = </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_continues</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">C_string</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">] = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP30"></a><b>&#167;30. </b>Unicode code points outside the first page are flattened to <span class="extract"><span class="extract-syntax">'?'</span></span> in an
2019-02-04 22:26:45 +00:00
ISO string:
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::write_as_ISO_string</span><button class="popup" onclick="togglePopup('usagePopup26')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup26">Usage of <b>Streams::write_as_ISO_string</b>:<br><a href="2-str.html#SP32">&#167;32</a>, String Manipulation - <a href="4-sm.html#SP6">&#167;6</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">C_string</span><span class="plain-syntax">, </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">buffer_size</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">buffer_size</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) { </span><span class="identifier-syntax">C_string</span><span class="plain-syntax">[0] = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="reserved-syntax">return</span><span class="plain-syntax">; }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_file</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"stream_get_text on file stream"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">j</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">j</span><span class="plain-syntax">&lt;</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_written</span><span class="plain-syntax">; </span><span class="identifier-syntax">j</span><span class="plain-syntax">++) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">i</span><span class="plain-syntax"> &gt;= </span><span class="identifier-syntax">buffer_size</span><span class="plain-syntax">-1) </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">c</span><span class="plain-syntax"> = </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_memory</span><span class="plain-syntax">[</span><span class="identifier-syntax">j</span><span class="plain-syntax">];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">c</span><span class="plain-syntax"> &lt; </span><span class="constant-syntax">256</span><span class="plain-syntax">) </span><span class="identifier-syntax">C_string</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">++] = (</span><span class="reserved-syntax">char</span><span class="plain-syntax">) </span><span class="identifier-syntax">c</span><span class="plain-syntax">; </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">C_string</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">++] = </span><span class="character-syntax">'?'</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax"> = </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_continues</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">C_string</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">] = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP31"></a><b>&#167;31. </b></p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::write_as_UTF8_string</span><button class="popup" onclick="togglePopup('usagePopup27')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup27">Usage of <b>Streams::write_as_UTF8_string</b>:<br><a href="2-str.html#SP32">&#167;32</a>, String Manipulation - <a href="4-sm.html#SP6">&#167;6</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">C_string</span><span class="plain-syntax">, </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">buffer_size</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">buffer_size</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) { </span><span class="identifier-syntax">C_string</span><span class="plain-syntax">[0] = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="reserved-syntax">return</span><span class="plain-syntax">; }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_file</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"stream_get_text on file stream"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">unsigned</span><span class="plain-syntax"> </span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">to</span><span class="plain-syntax"> = (</span><span class="reserved-syntax">unsigned</span><span class="plain-syntax"> </span><span class="reserved-syntax">char</span><span class="plain-syntax"> *) </span><span class="identifier-syntax">C_string</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">j</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">j</span><span class="plain-syntax">&lt;</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_written</span><span class="plain-syntax">; </span><span class="identifier-syntax">j</span><span class="plain-syntax">++) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">unsigned</span><span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">c</span><span class="plain-syntax"> = (</span><span class="reserved-syntax">unsigned</span><span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax">) </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_memory</span><span class="plain-syntax">[</span><span class="identifier-syntax">j</span><span class="plain-syntax">];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">c</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">0x800</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">i</span><span class="plain-syntax"> &gt;= </span><span class="identifier-syntax">buffer_size</span><span class="plain-syntax">-3) </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">to</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">++] = </span><span class="constant-syntax">0xE0</span><span class="plain-syntax"> + (</span><span class="reserved-syntax">unsigned</span><span class="plain-syntax"> </span><span class="reserved-syntax">char</span><span class="plain-syntax">) (</span><span class="identifier-syntax">c</span><span class="plain-syntax"> &gt;&gt; </span><span class="constant-syntax">12</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">to</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">++] = </span><span class="constant-syntax">0x80</span><span class="plain-syntax"> + (</span><span class="reserved-syntax">unsigned</span><span class="plain-syntax"> </span><span class="reserved-syntax">char</span><span class="plain-syntax">) ((</span><span class="identifier-syntax">c</span><span class="plain-syntax"> &gt;&gt; </span><span class="constant-syntax">6</span><span class="plain-syntax">) &amp; </span><span class="constant-syntax">0x3f</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">to</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">++] = </span><span class="constant-syntax">0x80</span><span class="plain-syntax"> + (</span><span class="reserved-syntax">unsigned</span><span class="plain-syntax"> </span><span class="reserved-syntax">char</span><span class="plain-syntax">) (</span><span class="identifier-syntax">c</span><span class="plain-syntax"> &amp; </span><span class="constant-syntax">0x3f</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">c</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">0x80</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">i</span><span class="plain-syntax"> &gt;= </span><span class="identifier-syntax">buffer_size</span><span class="plain-syntax">-2) </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">to</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">++] = </span><span class="constant-syntax">0xC0</span><span class="plain-syntax"> + (</span><span class="reserved-syntax">unsigned</span><span class="plain-syntax"> </span><span class="reserved-syntax">char</span><span class="plain-syntax">) (</span><span class="identifier-syntax">c</span><span class="plain-syntax"> &gt;&gt; </span><span class="constant-syntax">6</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">to</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">++] = </span><span class="constant-syntax">0x80</span><span class="plain-syntax"> + (</span><span class="reserved-syntax">unsigned</span><span class="plain-syntax"> </span><span class="reserved-syntax">char</span><span class="plain-syntax">) (</span><span class="identifier-syntax">c</span><span class="plain-syntax"> &amp; </span><span class="constant-syntax">0x3f</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">i</span><span class="plain-syntax"> &gt;= </span><span class="identifier-syntax">buffer_size</span><span class="plain-syntax">-1) </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">to</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">++] = (</span><span class="reserved-syntax">unsigned</span><span class="plain-syntax"> </span><span class="reserved-syntax">char</span><span class="plain-syntax">) </span><span class="identifier-syntax">c</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax"> = </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_continues</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">to</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">] = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP32"></a><b>&#167;32. Locale versions. </b></p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::open_from_locale_string</span><button class="popup" onclick="togglePopup('usagePopup28')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup28">Usage of <b>Streams::open_from_locale_string</b>:<br>String Manipulation - <a href="4-sm.html#SP4">&#167;4</a>, <a href="4-sm.html#SP5">&#167;5</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">C_string</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOCALE_IS_UTF8</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><a href="2-str.html#SP28_2" class="function-link"><span class="function-syntax">Streams::open_from_UTF8_string</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="identifier-syntax">C_string</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="constant-syntax">LOCALE_IS_ISO</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><a href="2-str.html#SP28_1" class="function-link"><span class="function-syntax">Streams::open_from_ISO_string</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="identifier-syntax">C_string</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax">}</span>
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::write_as_locale_string</span><button class="popup" onclick="togglePopup('usagePopup29')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup29">Usage of <b>Streams::write_as_locale_string</b>:<br>Shell - <a href="3-shl.html#SP5">&#167;5</a>&lt;br&gt;String Manipulation - <a href="4-sm.html#SP6">&#167;6</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">C_string</span><span class="plain-syntax">, </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">buffer_size</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOCALE_IS_UTF8</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><a href="2-str.html#SP31" class="function-link"><span class="function-syntax">Streams::write_as_UTF8_string</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">C_string</span><span class="plain-syntax">, </span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="identifier-syntax">buffer_size</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="constant-syntax">LOCALE_IS_ISO</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><a href="2-str.html#SP30" class="function-link"><span class="function-syntax">Streams::write_as_ISO_string</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">C_string</span><span class="plain-syntax">, </span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="identifier-syntax">buffer_size</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax">}</span>
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::write_locale_string</span><button class="popup" onclick="togglePopup('usagePopup30')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup30">Usage of <b>Streams::write_locale_string</b>:<br>Command Line Arguments - <a href="3-cla.html#SP8">&#167;8</a>&lt;br&gt;Directories - <a href="3-drc.html#SP2">&#167;2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">C_string</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOCALE_IS_UTF8</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><a href="2-str.html#SP28_2" class="function-link"><span class="function-syntax">Streams::write_UTF8_string</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="identifier-syntax">C_string</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="constant-syntax">LOCALE_IS_ISO</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><a href="2-str.html#SP28_1" class="function-link"><span class="function-syntax">Streams::write_ISO_string</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="identifier-syntax">C_string</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax">}</span>
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP33"></a><b>&#167;33. Flush and close. </b>Note that flush is an operation which can be performed on any stream, including
2020-04-22 22:57:09 +00:00
<span class="extract"><span class="extract-syntax">NULL</span></span>:
2019-02-04 22:26:45 +00:00
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::flush</span><button class="popup" onclick="togglePopup('usagePopup31')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup31">Usage of <b>Streams::flush</b>:<br><a href="2-str.html#SP10">&#167;10</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_file</span><span class="plain-syntax">) </span><span class="identifier-syntax">fflush</span><span class="plain-syntax">(</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_file</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP34"></a><b>&#167;34. </b>But closing is not allowed for <span class="extract"><span class="extract-syntax">NULL</span></span> or the standard I/O wrappers:
2019-02-04 22:26:45 +00:00
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::close</span><button class="popup" onclick="togglePopup('usagePopup32')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup32">Usage of <b>Streams::close</b>:<br><a href="2-str.html#SP9">&#167;9</a>, <a href="2-str.html#SP40">&#167;40</a>, <a href="2-str.html#SP41">&#167;41</a>, Build Files - <a href="8-bf.html#SP4">&#167;4</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"tried to close NULL stream"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax"> == &amp;</span><span class="identifier-syntax">STDOUT_struct</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"tried to close STDOUT stream"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax"> == &amp;</span><span class="identifier-syntax">STDERR_struct</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"tried to close STDERR stream"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_capacity</span><span class="plain-syntax"> == -1) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"stream closed twice"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_continues</span><span class="plain-syntax">) {</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><a href="2-str.html#SP34" class="function-link"><span class="function-syntax">Streams::close</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_continues</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_continues</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
2020-04-24 23:06:02 +00:00
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_capacity</span><span class="plain-syntax"> = -1; </span><span class="comment-syntax"> mark as closed</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_file</span><span class="plain-syntax">) </span><span class="named-paragraph-container"><a href="2-str.html#SP34_1" class="named-paragraph-link"><span class="named-paragraph">Take suitable action to close the file stream</span><span class="named-paragraph-number">34.1</span></span></a><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_memory</span><span class="plain-syntax">) </span><span class="named-paragraph-container"><a href="2-str.html#SP34_2" class="named-paragraph-link"><span class="named-paragraph">Take suitable action to close the memory stream</span><span class="named-paragraph-number">34.2</span></span></a><span class="plain-syntax">;</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax">}</span>
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP34_1"></a><b>&#167;34.1. </b>Note that we need do nothing to close a memory stream when the storage
2019-02-04 22:26:45 +00:00
was supplied by our client; it only needs freeing if we were the ones who
allocated it.
</p>
2020-04-24 23:06:02 +00:00
<p class="commentary">Inscrutably, <span class="extract"><span class="extract-syntax">fclose</span></span> returns <span class="extract"><span class="extract-syntax">EOF</span></span> to report any failure.
2019-02-04 22:26:45 +00:00
</p>
2020-04-24 23:06:02 +00:00
<p class="commentary"><span class="named-paragraph-container"><span class="named-paragraph-defn">Take suitable action to close the file stream</span><span class="named-paragraph-number">34.1</span></span><span class="comment-syntax"> =</span>
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">ferror</span><span class="plain-syntax">(</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_file</span><span class="plain-syntax">)) || (</span><span class="identifier-syntax">fclose</span><span class="plain-syntax">(</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_file</span><span class="plain-syntax">) == </span><span class="identifier-syntax">EOF</span><span class="plain-syntax">))</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><a href="3-em.html#SP2" class="function-link"><span class="function-syntax">Errors::fatal</span></a><span class="plain-syntax">(</span><span class="string-syntax">"The host computer reported an error trying to write a text file"</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax"> != </span><span class="identifier-syntax">DL</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOGIF</span><span class="plain-syntax">(</span><span class="identifier-syntax">TEXT_FILES</span><span class="plain-syntax">, </span><span class="string-syntax">"Text file '%f' (%s): %d characters written\n"</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">file_written</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> &amp; </span><span class="constant-syntax">FILE_ENCODING_UTF8_STRF</span><span class="plain-syntax">)?</span><span class="string-syntax">"UTF8"</span><span class="plain-syntax">:</span><span class="string-syntax">"ISO"</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_written</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_file</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-str.html#SP34">&#167;34</a>.</li></ul>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP34_2"></a><b>&#167;34.2. </b>Note that we need do nothing to close a memory stream when the storage
2019-02-04 22:26:45 +00:00
was supplied by our client; it only needs freeing if we were the ones who
2020-04-22 22:57:09 +00:00
allocated it. <span class="extract"><span class="extract-syntax">free</span></span> is a void function; in theory it cannot fail, if
2019-02-04 22:26:45 +00:00
supplied a valid argument.
</p>
2020-04-24 23:06:02 +00:00
<p class="commentary">We have to be very careful once we have called <span class="extract"><span class="extract-syntax">free</span></span>, because that memory
2020-04-22 22:57:09 +00:00
may well contain the <span class="extract"><span class="extract-syntax">text_stream</span></span> structure to which <span class="extract"><span class="extract-syntax">stream</span></span> points &mdash; see
2019-02-04 22:26:45 +00:00
how continuations are made, below.
</p>
2020-04-24 23:06:02 +00:00
<p class="commentary"><span class="named-paragraph-container"><span class="named-paragraph-defn">Take suitable action to close the memory stream</span><span class="named-paragraph-number">34.2</span></span><span class="comment-syntax"> =</span>
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax">) &amp; </span><span class="constant-syntax">MALLOCED_STRF</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> *</span><span class="identifier-syntax">mem</span><span class="plain-syntax"> = </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_memory</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_memory</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><a href="2-mmr.html#SP27" class="function-link"><span class="function-syntax">Memory::I7_free</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">mem</span><span class="plain-syntax">, </span><span class="constant-syntax">STREAM_MREASON</span><span class="plain-syntax">, </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_capacity</span><span class="plain-syntax">*((</span><span class="reserved-syntax">int</span><span class="plain-syntax">) </span><span class="reserved-syntax">sizeof</span><span class="plain-syntax">(</span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax">)));</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-str.html#SP34">&#167;34</a>.</li></ul>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP35"></a><b>&#167;35. Writing. </b>Our equivalent of <span class="extract"><span class="extract-syntax">fputc</span></span> reads:
2019-02-04 22:26:45 +00:00
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::putc</span><button class="popup" onclick="togglePopup('usagePopup33')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup33">Usage of <b>Streams::putc</b>:<br><a href="2-str.html#SP6">&#167;6</a>, <a href="2-str.html#SP28">&#167;28</a>, <a href="2-str.html#SP28_1">&#167;28.1</a>, <a href="2-str.html#SP28_2">&#167;28.2</a>, <a href="2-str.html#SP35_2">&#167;35.2</a>, <a href="2-str.html#SP36">&#167;36</a>, <a href="2-str.html#SP42">&#167;42</a>, Writers and Loggers - <a href="2-wal.html#SP6">&#167;6</a>, <a href="2-wal.html#SP6_1_1">&#167;6.1.1</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">c_int</span><span class="plain-syntax">, </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">unsigned</span><span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">c</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">c_int</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">c</span><span class="plain-syntax"> = (</span><span class="reserved-syntax">unsigned</span><span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax">) </span><span class="identifier-syntax">c_int</span><span class="plain-syntax">; </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">c</span><span class="plain-syntax"> = (</span><span class="reserved-syntax">unsigned</span><span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax">) (</span><span class="identifier-syntax">c_int</span><span class="plain-syntax"> + </span><span class="constant-syntax">256</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">first_stream</span><span class="plain-syntax"> = </span><span class="identifier-syntax">stream</span><span class="plain-syntax">;</span>
2020-04-24 23:06:02 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">c</span><span class="plain-syntax"> != </span><span class="character-syntax">'\n'</span><span class="plain-syntax">) </span><span class="named-paragraph-container"><a href="2-str.html#SP35_2" class="named-paragraph-link"><span class="named-paragraph">Insert indentation if this is pending</span><span class="named-paragraph-number">35.2</span></span></a><span class="plain-syntax">;</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> &amp; </span><span class="constant-syntax">READ_ONLY_STRF</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"modifying read-only stream"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax">) &amp; </span><span class="constant-syntax">USES_XML_ESCAPES_STRF</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax">(</span><span class="identifier-syntax">c</span><span class="plain-syntax">) {</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">NEWLINE_IN_STRING:</span><span class="plain-syntax"> </span><a href="2-str.html#SP36" class="function-link"><span class="function-syntax">Streams::literal</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="string-syntax">"&lt;br&gt;"</span><span class="plain-syntax">); </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="character-syntax">'&amp;'</span><span class="plain-syntax">: </span><a href="2-str.html#SP36" class="function-link"><span class="function-syntax">Streams::literal</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="string-syntax">"&amp;amp;"</span><span class="plain-syntax">); </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="character-syntax">'&lt;'</span><span class="plain-syntax">: </span><a href="2-str.html#SP36" class="function-link"><span class="function-syntax">Streams::literal</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="string-syntax">"&amp;lt;"</span><span class="plain-syntax">); </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="character-syntax">'&gt;'</span><span class="plain-syntax">: </span><a href="2-str.html#SP36" class="function-link"><span class="function-syntax">Streams::literal</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="string-syntax">"&amp;gt;"</span><span class="plain-syntax">); </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_continues</span><span class="plain-syntax">) </span><span class="identifier-syntax">stream</span><span class="plain-syntax"> = </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_continues</span><span class="plain-syntax">;</span>
2020-04-24 23:06:02 +00:00
<span class="plain-syntax"> </span><span class="named-paragraph-container"><a href="2-str.html#SP35_3" class="named-paragraph-link"><span class="named-paragraph">Ensure there is room to expand the escape sequence into</span><span class="named-paragraph-number">35.3</span></span></a><span class="plain-syntax">;</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_file</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> &amp; </span><span class="constant-syntax">FILE_ENCODING_UTF8_STRF</span><span class="plain-syntax">)</span>
2020-04-24 23:06:02 +00:00
<span class="plain-syntax"> </span><span class="named-paragraph-container"><a href="2-str.html#SP35_1" class="named-paragraph-link"><span class="named-paragraph">Put a UTF8-encoded character into the underlying file</span><span class="named-paragraph-number">35.1</span></span></a>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> &amp; </span><span class="constant-syntax">FILE_ENCODING_ISO_STRF</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">c</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">0x100</span><span class="plain-syntax">) </span><span class="identifier-syntax">c</span><span class="plain-syntax"> = </span><span class="character-syntax">'?'</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">fputc</span><span class="plain-syntax">((</span><span class="reserved-syntax">int</span><span class="plain-syntax">) </span><span class="identifier-syntax">c</span><span class="plain-syntax">, </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_file</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"stream has unknown text encoding"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_memory</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">c</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">0x0300</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">c</span><span class="plain-syntax"> &lt;= </span><span class="constant-syntax">0x036F</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_written</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">)) {</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><span class="identifier-syntax">c</span><span class="plain-syntax"> = (</span><span class="reserved-syntax">unsigned</span><span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax">) </span><a href="4-chr.html#SP4" class="function-link"><span class="function-syntax">Characters::combine_accent</span></a><span class="plain-syntax">(</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax">) </span><span class="identifier-syntax">c</span><span class="plain-syntax">, (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_memory</span><span class="plain-syntax">)[</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_written</span><span class="plain-syntax"> - </span><span class="constant-syntax">1</span><span class="plain-syntax">]);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_written</span><span class="plain-syntax">--;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_memory</span><span class="plain-syntax">)[</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_written</span><span class="plain-syntax">] = (</span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax">) </span><span class="identifier-syntax">c</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">c</span><span class="plain-syntax"> == </span><span class="character-syntax">'\n'</span><span class="plain-syntax">) </span><span class="identifier-syntax">first_stream</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">stream_flags</span><span class="plain-syntax"> |= </span><span class="constant-syntax">INDENT_PENDING_STRF</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_written</span><span class="plain-syntax">++;</span>
<span class="plain-syntax">}</span>
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP35_1"></a><b>&#167;35.1. </b>Where we pack large character values, up to 65535, as follows.
2019-02-04 22:26:45 +00:00
</p>
2020-04-24 23:06:02 +00:00
<p class="commentary"><span class="named-paragraph-container"><span class="named-paragraph-defn">Put a UTF8-encoded character into the underlying file</span><span class="named-paragraph-number">35.1</span></span><span class="comment-syntax"> =</span>
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">c</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">0x800</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">fputc</span><span class="plain-syntax">(</span><span class="constant-syntax">0xE0</span><span class="plain-syntax"> + (</span><span class="identifier-syntax">c</span><span class="plain-syntax"> &gt;&gt; </span><span class="constant-syntax">12</span><span class="plain-syntax">), </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_file</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">fputc</span><span class="plain-syntax">(</span><span class="constant-syntax">0x80</span><span class="plain-syntax"> + ((</span><span class="identifier-syntax">c</span><span class="plain-syntax"> &gt;&gt; </span><span class="constant-syntax">6</span><span class="plain-syntax">) &amp; </span><span class="constant-syntax">0x3f</span><span class="plain-syntax">), </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_file</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">fputc</span><span class="plain-syntax">(</span><span class="constant-syntax">0x80</span><span class="plain-syntax"> + (</span><span class="identifier-syntax">c</span><span class="plain-syntax"> &amp; </span><span class="constant-syntax">0x3f</span><span class="plain-syntax">), </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_file</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">c</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">0x80</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">fputc</span><span class="plain-syntax">(</span><span class="constant-syntax">0xC0</span><span class="plain-syntax"> + (</span><span class="identifier-syntax">c</span><span class="plain-syntax"> &gt;&gt; </span><span class="constant-syntax">6</span><span class="plain-syntax">), </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_file</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">fputc</span><span class="plain-syntax">(</span><span class="constant-syntax">0x80</span><span class="plain-syntax"> + (</span><span class="identifier-syntax">c</span><span class="plain-syntax"> &amp; </span><span class="constant-syntax">0x3f</span><span class="plain-syntax">), </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_file</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">fputc</span><span class="plain-syntax">((</span><span class="reserved-syntax">int</span><span class="plain-syntax">) </span><span class="identifier-syntax">c</span><span class="plain-syntax">, </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_file</span><span class="plain-syntax">);</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-str.html#SP35">&#167;35</a>.</li></ul>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP35_2"></a><b>&#167;35.2. </b><span class="named-paragraph-container"><span class="named-paragraph-defn">Insert indentation if this is pending</span><span class="named-paragraph-number">35.2</span></span><span class="comment-syntax"> =</span>
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">first_stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> &amp; </span><span class="constant-syntax">INDENT_PENDING_STRF</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">first_stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> -= </span><span class="constant-syntax">INDENT_PENDING_STRF</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">L</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">first_stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> &amp; </span><span class="constant-syntax">INDENTATION_MASK_STRF</span><span class="plain-syntax">)/</span><span class="constant-syntax">INDENTATION_BASE_STRF</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">i</span><span class="plain-syntax">&lt;</span><span class="identifier-syntax">L</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++) {</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><a href="2-str.html#SP35" class="function-link"><span class="function-syntax">Streams::putc</span></a><span class="plain-syntax">(</span><span class="character-syntax">' '</span><span class="plain-syntax">, </span><span class="identifier-syntax">first_stream</span><span class="plain-syntax">); </span><a href="2-str.html#SP35" class="function-link"><span class="function-syntax">Streams::putc</span></a><span class="plain-syntax">(</span><span class="character-syntax">' '</span><span class="plain-syntax">, </span><span class="identifier-syntax">first_stream</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="2-str.html#SP35" class="function-link"><span class="function-syntax">Streams::putc</span></a><span class="plain-syntax">(</span><span class="character-syntax">' '</span><span class="plain-syntax">, </span><span class="identifier-syntax">first_stream</span><span class="plain-syntax">); </span><a href="2-str.html#SP35" class="function-link"><span class="function-syntax">Streams::putc</span></a><span class="plain-syntax">(</span><span class="character-syntax">' '</span><span class="plain-syntax">, </span><span class="identifier-syntax">first_stream</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-str.html#SP35">&#167;35</a>.</li></ul>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP35_3"></a><b>&#167;35.3. </b>The following is checked before any numerical <span class="extract"><span class="extract-syntax">printf</span></span>-style escape is expanded
2019-02-04 22:26:45 +00:00
into the stream, or before any single character is written. Thus we cannot
overrun our buffers unless the expansion of a numerical escape exceeds
2020-04-22 22:57:09 +00:00
<span class="extract"><span class="extract-syntax">SPACE_AT_END_OF_STREAM</span></span> plus 1 in size. Since no outside influence gets to
choose what formatting escapes we use (so that <span class="extract"><span class="extract-syntax">%3000d</span></span>, say, can't occur),
2019-02-04 22:26:45 +00:00
we can be pretty confident.
</p>
2020-04-24 23:06:02 +00:00
<p class="commentary">The interesting case occurs when we run out of memory in a memory stream.
2020-04-22 22:57:09 +00:00
We make a continuation to a fresh <span class="extract"><span class="extract-syntax">text_stream</span></span> structure, which points to twice
as much memory as the original, allocated via <span class="extract"><span class="extract-syntax">malloc</span></span>. (We will actually need
2019-02-04 22:26:45 +00:00
a little more memory than that because we also have to make room for the
2020-04-22 22:57:09 +00:00
<span class="extract"><span class="extract-syntax">text_stream</span></span> structure itself.) We then set <span class="extract"><span class="extract-syntax">stream</span></span> to the <span class="extract"><span class="extract-syntax">continuation</span></span>. Given
that <span class="extract"><span class="extract-syntax">malloc</span></span> was successful &mdash; and it must have been or we would have stopped
2019-02-04 22:26:45 +00:00
with a fatal error &mdash; the continuation is guaranteed to be large enough,
since it's twice the size of the original, which itself was large enough to
hold any escape sequence when opened.
</p>
2020-04-24 23:06:02 +00:00
<p class="commentary"><span class="named-paragraph-container"><span class="named-paragraph-defn">Ensure there is room to expand the escape sequence into</span><span class="named-paragraph-number">35.3</span></span><span class="comment-syntax"> =</span>
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_written</span><span class="plain-syntax"> + </span><span class="constant-syntax">SPACE_AT_END_OF_STREAM</span><span class="plain-syntax"> &gt;= </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_capacity</span><span class="plain-syntax">) {</span>
2020-04-24 23:06:02 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_file</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax">; </span><span class="comment-syntax"> write nothing further</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_memory</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">offset</span><span class="plain-syntax"> = (32 + </span><span class="constant-syntax">2</span><span class="plain-syntax">*(</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_capacity</span><span class="plain-syntax">))*((</span><span class="reserved-syntax">int</span><span class="plain-syntax">) </span><span class="reserved-syntax">sizeof</span><span class="plain-syntax">(</span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">needed</span><span class="plain-syntax"> = </span><span class="identifier-syntax">offset</span><span class="plain-syntax"> + ((</span><span class="reserved-syntax">int</span><span class="plain-syntax">) </span><span class="reserved-syntax">sizeof</span><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax">)) + </span><span class="constant-syntax">32</span><span class="plain-syntax">;</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">void</span><span class="plain-syntax"> *</span><span class="identifier-syntax">further_allocation</span><span class="plain-syntax"> = </span><a href="2-mmr.html#SP25" class="function-link"><span class="function-syntax">Memory::malloc</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">needed</span><span class="plain-syntax">, </span><span class="constant-syntax">STREAM_MREASON</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">further_allocation</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><a href="3-em.html#SP2" class="function-link"><span class="function-syntax">Errors::fatal</span></a><span class="plain-syntax">(</span><span class="string-syntax">"Out of memory"</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">continuation</span><span class="plain-syntax"> = (</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *) (</span><span class="identifier-syntax">further_allocation</span><span class="plain-syntax"> + </span><span class="identifier-syntax">offset</span><span class="plain-syntax">);</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><a href="2-str.html#SP19" class="function-link"><span class="function-syntax">Streams::initialise</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">continuation</span><span class="plain-syntax">, </span><span class="constant-syntax">FOR_CO_STRF</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="identifier-syntax">continuation</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_memory</span><span class="plain-syntax"> = </span><span class="identifier-syntax">further_allocation</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">continuation</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_capacity</span><span class="plain-syntax"> = </span><span class="constant-syntax">2</span><span class="plain-syntax">*</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_capacity</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> (</span><span class="identifier-syntax">continuation</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_memory</span><span class="plain-syntax">)[0] = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_continues</span><span class="plain-syntax"> = </span><span class="identifier-syntax">continuation</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax"> = </span><span class="identifier-syntax">continuation</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-str.html#SP35">&#167;35</a>.</li></ul>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP36"></a><b>&#167;36. </b>Literal printing is just printing with XML escapes switched off:
2019-02-04 22:26:45 +00:00
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::literal</span><button class="popup" onclick="togglePopup('usagePopup34')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup34">Usage of <b>Streams::literal</b>:<br><a href="2-str.html#SP35">&#167;35</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">p</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">, </span><span class="identifier-syntax">x</span><span class="plain-syntax"> = ((</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax">) &amp; </span><span class="constant-syntax">USES_XML_ESCAPES_STRF</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">x</span><span class="plain-syntax">) </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> -= </span><span class="constant-syntax">USES_XML_ESCAPES_STRF</span><span class="plain-syntax">;</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">]; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++) </span><a href="2-str.html#SP35" class="function-link"><span class="function-syntax">Streams::putc</span></a><span class="plain-syntax">((</span><span class="reserved-syntax">int</span><span class="plain-syntax">) </span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">], </span><span class="identifier-syntax">stream</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">x</span><span class="plain-syntax">) </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> += </span><span class="constant-syntax">USES_XML_ESCAPES_STRF</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP37"></a><b>&#167;37. </b>Shifting indentation. For every indent there must be an equal and opposite
2019-02-04 22:26:45 +00:00
outdent, but error conditions can cause some compilation routines to issue
problem messages and then leave what they're doing incomplete, so we will
be a little cautious about assuming that a mismatch means an error.
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::indent</span><button class="popup" onclick="togglePopup('usagePopup35')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup35">Usage of <b>Streams::indent</b>:<br><a href="2-str.html#SP7">&#167;7</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> += </span><span class="constant-syntax">INDENTATION_BASE_STRF</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::outdent</span><button class="popup" onclick="togglePopup('usagePopup36')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup36">Usage of <b>Streams::outdent</b>:<br><a href="2-str.html#SP7">&#167;7</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> &amp; </span><span class="constant-syntax">INDENTATION_MASK_STRF</span><span class="plain-syntax">) == </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="3-em.html#SP1" class="function-link"><span class="function-syntax">Errors::have_occurred</span></a><span class="plain-syntax">() == </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"stream indentation negative"</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> -= </span><span class="constant-syntax">INDENTATION_BASE_STRF</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::set_indentation</span><button class="popup" onclick="togglePopup('usagePopup37')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup37">Usage of <b>Streams::set_indentation</b>:<br><a href="2-str.html#SP7">&#167;7</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">N</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">B</span><span class="plain-syntax"> = </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> &amp; </span><span class="constant-syntax">INDENTATION_MASK_STRF</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> -= </span><span class="identifier-syntax">B</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> += </span><span class="identifier-syntax">N</span><span class="plain-syntax">*</span><span class="constant-syntax">INDENTATION_BASE_STRF</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP38"></a><b>&#167;38. </b>We can read the position for any stream, including <span class="extract"><span class="extract-syntax">NULL</span></span>, but no matter
2020-04-22 22:57:09 +00:00
how much is written to <span class="extract"><span class="extract-syntax">NULL</span></span> this position never budges.
2019-02-04 22:26:45 +00:00
</p>
2020-04-24 23:06:02 +00:00
<p class="commentary">Because of continuations, this is not as simple as returning the <span class="extract"><span class="extract-syntax">chars_written</span></span>
2019-02-04 22:26:45 +00:00
field.
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::get_position</span><button class="popup" onclick="togglePopup('usagePopup38')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup38">Usage of <b>Streams::get_position</b>:<br><a href="2-str.html#SP11">&#167;11</a>, <a href="2-str.html#SP13">&#167;13</a>, String Manipulation - <a href="4-sm.html#SP8">&#167;8</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">t</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">t</span><span class="plain-syntax"> += </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_written</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax"> = </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_continues</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">t</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP39"></a><b>&#167;39. Memory-stream-only functions. </b>While it would be easy enough to implement this for file streams too, there's
2019-02-04 22:26:45 +00:00
no point, since it is used only in concert with backspacing.
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::latest</span><button class="popup" onclick="togglePopup('usagePopup39')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup39">Usage of <b>Streams::latest</b>:<br><a href="2-str.html#SP14">&#167;14</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_file</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"stream_latest on file stream"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_continues</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_continues</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_written</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax"> = </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_continues</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_memory</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_written</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax">) ((</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_memory</span><span class="plain-syntax">)[</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_written</span><span class="plain-syntax"> - </span><span class="constant-syntax">1</span><span class="plain-syntax">]);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP40"></a><b>&#167;40. </b>Accessing characters by index. Note that the stream terminates at the first
2019-02-04 22:26:45 +00:00
zero byte found, so that putting a zero truncates it.
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
2020-04-24 23:06:02 +00:00
<span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::get_char_at_index</span><button class="popup" onclick="togglePopup('usagePopup40')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup40">Usage of <b>Streams::get_char_at_index</b>:<br>String Manipulation - <a href="4-sm.html#SP13">&#167;13</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">position</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"examining null stream"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_file</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"examining file stream"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">position</span><span class="plain-syntax"> &gt;= </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_written</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">position</span><span class="plain-syntax"> = </span><span class="identifier-syntax">position</span><span class="plain-syntax"> - </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_written</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax"> = </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_continues</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_memory</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_memory</span><span class="plain-syntax">)[</span><span class="identifier-syntax">position</span><span class="plain-syntax">];</span>
<span class="plain-syntax">}</span>
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::put_char_at_index</span><button class="popup" onclick="togglePopup('usagePopup41')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup41">Usage of <b>Streams::put_char_at_index</b>:<br>String Manipulation - <a href="4-sm.html#SP14">&#167;14</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">position</span><span class="plain-syntax">, </span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">C</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"modifying null stream"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_file</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"modifying file stream"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> &amp; </span><span class="constant-syntax">READ_ONLY_STRF</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"modifying read-only stream"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">position</span><span class="plain-syntax"> &gt;= </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_written</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">position</span><span class="plain-syntax"> = </span><span class="identifier-syntax">position</span><span class="plain-syntax"> - </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_written</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax"> = </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_continues</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"overrun memory stream"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_memory</span><span class="plain-syntax">)[</span><span class="identifier-syntax">position</span><span class="plain-syntax">] = </span><span class="identifier-syntax">C</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">C</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_written</span><span class="plain-syntax"> = </span><span class="identifier-syntax">position</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_continues</span><span class="plain-syntax">) {</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><a href="2-str.html#SP34" class="function-link"><span class="function-syntax">Streams::close</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_continues</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_continues</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax">}</span>
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP41"></a><b>&#167;41. </b>Now for what is the trickiest function, because the position may be moved back
2019-02-04 22:26:45 +00:00
so that later continuations fall away. This will very rarely happen, so we
won't worry about the inefficiency of freeing up the memory saved by closing
such continuation blocks (which would be inefficient if we immediately had
to open similar ones again).
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::set_position</span><button class="popup" onclick="togglePopup('usagePopup42')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup42">Usage of <b>Streams::set_position</b>:<br><a href="2-str.html#SP13">&#167;13</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stream</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">position</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
2020-04-24 23:06:02 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">position</span><span class="plain-syntax"> &lt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">position</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="comment-syntax"> to simplify the implementation of backspacing</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_file</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"stream_set_position on file stream"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> &amp; </span><span class="constant-syntax">READ_ONLY_STRF</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"modifying read-only stream"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_memory</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">position</span><span class="plain-syntax"> &gt; </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_written</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">position</span><span class="plain-syntax"> = </span><span class="identifier-syntax">position</span><span class="plain-syntax"> - </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_written</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax"> = </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_continues</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"can't set position forwards"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_written</span><span class="plain-syntax"> = </span><span class="identifier-syntax">position</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_memory</span><span class="plain-syntax">)[</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_written</span><span class="plain-syntax">] = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_continues</span><span class="plain-syntax">) {</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><a href="2-str.html#SP34" class="function-link"><span class="function-syntax">Streams::close</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_continues</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_continues</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax">}</span>
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP42"></a><b>&#167;42. </b>Lastly, our copying function, where <span class="extract"><span class="extract-syntax">from</span></span> has to be a memory stream (or
2020-04-22 22:57:09 +00:00
<span class="extract"><span class="extract-syntax">NULL</span></span>) but <span class="extract"><span class="extract-syntax">to</span></span> can be anything (including <span class="extract"><span class="extract-syntax">NULL</span></span>).
2019-02-04 22:26:45 +00:00
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::copy</span><button class="popup" onclick="togglePopup('usagePopup43')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup43">Usage of <b>Streams::copy</b>:<br><a href="2-str.html#SP14">&#167;14</a>, <a href="2-str.html#SP43">&#167;43</a>, String Manipulation - <a href="4-sm.html#SP3">&#167;3</a>, <a href="4-sm.html#SP17">&#167;17</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">to</span><span class="plain-syntax">, </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">from</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">from</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">to</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">from</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_file</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"stream_copy from file stream"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">from</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_memory</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">i</span><span class="plain-syntax">&lt;</span><span class="identifier-syntax">from</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">chars_written</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">c</span><span class="plain-syntax"> = (</span><span class="reserved-syntax">int</span><span class="plain-syntax">) ((</span><span class="identifier-syntax">from</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">write_to_memory</span><span class="plain-syntax">)[</span><span class="identifier-syntax">i</span><span class="plain-syntax">]);</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><a href="2-str.html#SP35" class="function-link"><span class="function-syntax">Streams::putc</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">c</span><span class="plain-syntax">, </span><span class="identifier-syntax">to</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> }</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">from</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_continues</span><span class="plain-syntax">) </span><a href="2-str.html#SP42" class="function-link"><span class="function-syntax">Streams::copy</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">to</span><span class="plain-syntax">, </span><span class="identifier-syntax">from</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stream_continues</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> }</span>
<span class="plain-syntax">}</span>
</pre>
2020-04-24 23:06:02 +00:00
<p class="commentary firstcommentary"><a id="SP43"></a><b>&#167;43. Writer. </b>This writes one stream into another one, which implements <span class="extract"><span class="extract-syntax">%S</span></span>.
2019-02-04 22:26:45 +00:00
</p>
2020-04-21 16:55:17 +00:00
<pre class="displayed-code all-displayed-code">
2020-04-24 23:06:02 +00:00
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::writer</span><button class="popup" onclick="togglePopup('usagePopup44')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup44">Usage of <b>Streams::writer</b>:<br>Foundation Module - <a href="1-fm.html#SP8_1">&#167;8.1</a></span></button><span class="plain-syntax">(</span><span class="constant-syntax">OUTPUT_STREAM</span><span class="plain-syntax">, </span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">format_string</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> *</span><span class="identifier-syntax">vS</span><span class="plain-syntax">) {</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">S</span><span class="plain-syntax"> = (</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *) </span><span class="identifier-syntax">vS</span><span class="plain-syntax">;</span>
2020-04-21 23:52:25 +00:00
<span class="plain-syntax"> </span><a href="2-str.html#SP42" class="function-link"><span class="function-syntax">Streams::copy</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="identifier-syntax">S</span><span class="plain-syntax">);</span>
2020-04-21 16:55:17 +00:00
<span class="plain-syntax">}</span>
</pre>
<hr class="tocbar">
2019-03-12 23:32:12 +00:00
<ul class="toc"><li><a href="2-mmr.html">Back to 'Memory'</a></li><li><a href="2-wal.html">Continue with 'Writers and Loggers'</a></li></ul><hr class="tocbar">
<!--End of weave-->
2020-04-23 22:23:44 +00:00
</main>
2019-02-04 22:26:45 +00:00
</body>
</html>