1070 lines
224 KiB
HTML
1070 lines
224 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html>
|
|
<head>
|
|
<title>Streams</title>
|
|
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
<meta name="viewport" content="width=device-width initial-scale=1">
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
<meta http-equiv="Content-Language" content="en-gb">
|
|
|
|
<link href="../docs-assets/Contents.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
<link href="../docs-assets/Progress.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
<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">
|
|
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
|
|
</head>
|
|
<body class="commentary-font">
|
|
<nav role="navigation">
|
|
<h1><a href="../index.html">
|
|
<img src="../docs-assets/Octagram.png" width=72 height=72">
|
|
</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>
|
|
</ul><h2>Example Webs</h2><ul>
|
|
<li><a href="../goldbach/index.html">goldbach</a></li>
|
|
<li><a href="../twinprimes/twinprimes.html">twinprimes</a></li>
|
|
<li><a href="../eastertide/index.html">eastertide</a></li>
|
|
</ul><h2>Repository</h2><ul>
|
|
<li><a href="https://github.com/ganelson/inweb"><img src="../docs-assets/github.png" height=18> github</a></li>
|
|
</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>
|
|
|
|
</ul>
|
|
</nav>
|
|
<main role="main">
|
|
<!--Weave of 'Streams' generated by Inweb-->
|
|
<div class="breadcrumbs">
|
|
<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></div>
|
|
<p class="purpose">Support for writing structured textual output, perhaps to the screen, to a file, or to a flexible-sized wide string.</p>
|
|
|
|
<ul class="toc"><li><a href="2-str.html#SP1">§1. About streams</a></li><li><a href="2-str.html#SP19">§19. Initialising the stream structure</a></li><li><a href="2-str.html#SP21">§21. Logging</a></li><li><a href="2-str.html#SP22">§22. Standard I/O wrappers</a></li><li><a href="2-str.html#SP24">§24. Creating file streams</a></li><li><a href="2-str.html#SP26">§26. Creating memory streams</a></li><li><a href="2-str.html#SP28">§28. Converting from C strings</a></li><li><a href="2-str.html#SP29">§29. Converting to C strings</a></li><li><a href="2-str.html#SP32">§32. Locale versions</a></li><li><a href="2-str.html#SP33">§33. Flush and close</a></li><li><a href="2-str.html#SP35">§35. Writing</a></li><li><a href="2-str.html#SP39">§39. Memory-stream-only functions</a></li><li><a href="2-str.html#SP43">§43. Writer</a></li></ul><hr class="tocbar">
|
|
|
|
<p class="commentary firstcommentary"><a id="SP1"></a><b>§1. About streams. </b>The Inform tools produce textual output in many formats (HTML, EPS, plain
|
|
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>
|
|
|
|
<p class="commentary">"Streams" are an abstraction to make it easy to handle all of this. The
|
|
writer to a stream never needs to know where the text will come out, or how
|
|
it should be indented or encoded.
|
|
</p>
|
|
|
|
<p class="commentary">Moreover, streams unify text files and strings, and can hold arbitrary
|
|
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>
|
|
|
|
<p class="commentary">We give just one character value a non-Unicode meaning:
|
|
</p>
|
|
|
|
<pre class="definitions code-font"><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>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP2"></a><b>§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
|
|
<span class="extract"><span class="extract-syntax">FILE</span></span>, and it is used in mostly similar ways. The user — the whole
|
|
program outside of this section — deals only with <span class="extract"><span class="extract-syntax">text_stream *</span></span> pointers to
|
|
represent streams in use.
|
|
</p>
|
|
|
|
<p class="commentary">All stream handling is defined via macros. While many operations could be
|
|
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
|
|
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>
|
|
|
|
<p class="commentary firstcommentary"><a id="SP3"></a><b>§3. </b>We'll define a few variadic macros here, because there are awkward issues
|
|
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
|
|
incompatibility between implementations of the C preprocessor <span class="extract"><span class="extract-syntax">cpp</span></span>. All the
|
|
same, if you're porting this code, you may need to rewrite the macro with
|
|
<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.
|
|
</p>
|
|
|
|
<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
|
|
formatted text to the current stream, which could be either a string or a
|
|
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>.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<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>
|
|
|
|
<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>
|
|
|
|
<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>
|
|
|
|
<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>
|
|
|
|
<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>
|
|
<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>
|
|
<span class="plain-syntax">}</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP4"></a><b>§4. </b>The main purpose of many functions is to write textual material to some
|
|
file. Such functions almost always have a special argument in their
|
|
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
|
|
see that it's properly opened and closed, are not their concern.
|
|
</p>
|
|
|
|
<pre class="definitions code-font"><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>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP5"></a><b>§5. </b>Three output streams are always open. One is <span class="extract"><span class="extract-syntax">NULL</span></span>, that is, its value
|
|
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
|
|
never be seen again.
|
|
</p>
|
|
|
|
<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
|
|
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
|
|
"files" provided by the C library.
|
|
</p>
|
|
|
|
<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,
|
|
so that there are no uses of <span class="extract"><span class="extract-syntax">printf</span></span> anywhere in the program.
|
|
</p>
|
|
|
|
<pre class="definitions code-font"><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>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP6"></a><b>§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
|
|
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 — <span class="extract"><span class="extract-syntax">OUT</span></span>, the current stream.
|
|
</p>
|
|
|
|
<pre class="definitions code-font"><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>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP7"></a><b>§7. </b>Each stream has a current indentation level, initially 0. Lines of text
|
|
will be indented by one tab stop for each level; it's an error for the level
|
|
to become negative.
|
|
</p>
|
|
|
|
<pre class="definitions code-font"><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>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP8"></a><b>§8. </b>Other streams only exist when explicitly created, or "opened". A function
|
|
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
|
|
halting with an internal error, and therefore an <span class="extract"><span class="extract-syntax">exit(1)</span></span>, while the stream
|
|
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>
|
|
|
|
<p class="commentary">The simplest way is to make a temporary stream, which can be used as a sort
|
|
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,
|
|
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.
|
|
</p>
|
|
|
|
<p class="commentary">Temporary streams are always created in memory, held in C's local stack frame
|
|
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
|
|
create a temporary stream many times in one function (for instance inside a
|
|
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
|
|
not violate the rule that every stream is opened and closed once only.
|
|
</p>
|
|
|
|
<pre class="definitions code-font"><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"> = &</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>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP9"></a><b>§9. </b>Otherwise we can create new globally existing streams, provided we take on
|
|
the responsibility for seeing that they are properly closed. There are two
|
|
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.
|
|
</p>
|
|
|
|
<p class="commentary">We use streams to handle all of our text file output, so there should be no
|
|
calls to <span class="extract"><span class="extract-syntax">fprintf</span></span> anywhere in the program except for binary files.
|
|
</p>
|
|
|
|
<pre class="definitions code-font"><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>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP10"></a><b>§10. </b>The following operation is equivalent to <span class="extract"><span class="extract-syntax">fflush</span></span> and makes it more likely
|
|
(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 code-font"><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>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP11"></a><b>§11. </b>A piece of information we can read for any stream is the number of characters
|
|
written to it: its "extent". In fact, UTF-8 multi-byte encoding schemes,
|
|
together with differing platform interpretations of C's <span class="extract"><span class="extract-syntax">'\n'</span></span>, mean that this
|
|
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 code-font"><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>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP12"></a><b>§12. </b>The remaining operations are available only for streams in memory (well, and
|
|
for <span class="extract"><span class="extract-syntax">NULL</span></span>, but of course they do nothing when applied to that). While they
|
|
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 code-font"><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">) && (</span><span class="identifier-syntax">x</span><span class="plain-syntax">-></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>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP13"></a><b>§13. </b>First, we can erase one or more recently written characters:
|
|
</p>
|
|
|
|
<pre class="definitions code-font"><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>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP14"></a><b>§14. </b>Second, we can look at the text written. The minimal form is to look at
|
|
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 code-font"><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>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP15"></a><b>§15. </b>So much for the definition; now the implementation. Here is the <span class="extract"><span class="extract-syntax">text_stream</span></span>
|
|
structure. Open memory streams are represented by structures where
|
|
<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.
|
|
</p>
|
|
|
|
<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
|
|
XML (and HTML) escapes of <span class="extract"><span class="extract-syntax">&amp;</span></span> for ampersand, and <span class="extract"><span class="extract-syntax">&lt;</span></span> and <span class="extract"><span class="extract-syntax">&gt;</span></span> for
|
|
angle brackets, will be used automatically on writing. By default this flag
|
|
is clear, that is, no conversion is made.
|
|
</p>
|
|
|
|
<pre class="definitions code-font"><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>
|
|
<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>
|
|
</pre>
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<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>
|
|
<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>
|
|
<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>
|
|
<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>
|
|
<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>
|
|
<p class="commentary firstcommentary"><a id="SP16"></a><b>§16. </b>A theological question: what is the text encoding for the null stream?
|
|
</p>
|
|
|
|
<pre class="definitions code-font"><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">-></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="constant-syntax">FALSE</span><span class="plain-syntax">)</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP17"></a><b>§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
|
|
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,
|
|
so out of the <span class="extract"><span class="extract-syntax">chars_capacity</span></span> space, the following amount will be kept clear:
|
|
</p>
|
|
|
|
<pre class="definitions code-font"><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>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP18"></a><b>§18. </b>A statistic we keep, since it costs little:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<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>
|
|
<p class="commentary firstcommentary"><a id="SP19"></a><b>§19. Initialising the stream structure. </b>Note that the following fills in sensible defaults for every field, but the
|
|
result is not a valid open stream; it's a blank form ready to be filled in.
|
|
</p>
|
|
|
|
<p class="commentary">By default the upper limit on file size is 2 GB. It's very hard to see this
|
|
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>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<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 <span class="code-font"><span class="function-syntax">Streams::initialise</span></span>:<br/><a href="2-str.html#SP22">§22</a>, <a href="2-str.html#SP23">§23</a>, <a href="2-str.html#SP24">§24</a>, <a href="2-str.html#SP25">§25</a>, <a href="2-str.html#SP26">§26</a>, <a href="2-str.html#SP27">§27</a>, <a href="2-str.html#SP35_3">§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>
|
|
<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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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>
|
|
<p class="commentary firstcommentary"><a id="SP20"></a><b>§20. </b>Any stream can have the following flag set or cleared. When this is set, the
|
|
XML (and HTML) escapes of <span class="extract"><span class="extract-syntax">&amp;</span></span> for ampersand, and <span class="extract"><span class="extract-syntax">&lt;</span></span> and <span class="extract"><span class="extract-syntax">&gt;</span></span> for
|
|
angle brackets, will be used automatically on writing. By default this flag
|
|
is clear, that is, no conversion is made.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::enable_XML_escapes</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="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">-></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">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::disable_XML_escapes</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="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">-></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="identifier-syntax">stream</span><span class="plain-syntax">-></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>
|
|
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::enable_I6_escapes</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="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">-></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>
|
|
|
|
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::disable_I6_escapes</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="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">-></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">stream</span><span class="plain-syntax">-></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>
|
|
|
|
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::I6_escapes_enabled</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="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>
|
|
|
|
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::enable_debugging</span><button class="popup" onclick="togglePopup('usagePopup2')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup2">Usage of <span class="code-font"><span class="function-syntax">Streams::enable_debugging</span></span>:<br/>Debugging Log - <a href="2-dl.html#SP5">§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="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">-></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>
|
|
|
|
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::disable_debugging</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="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">-></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><span class="identifier-syntax">stream</span><span class="plain-syntax">-></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>
|
|
|
|
<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('usagePopup3')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup3">Usage of <span class="code-font"><span class="function-syntax">Streams::mark_as_read_only</span></span>:<br/>String Manipulation - <a href="4-sm.html#SP27_1">§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>
|
|
<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">-></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>
|
|
|
|
<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('usagePopup4')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup4">Usage of <span class="code-font"><span class="function-syntax">Streams::declare_as_HTML</span></span>:<br/>HTML - <a href="5-htm.html#SP3">§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">HTML_file_state</span><span class="plain-syntax"> *</span><span class="identifier-syntax">hs</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">stream</span><span class="plain-syntax">-></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>
|
|
|
|
<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('usagePopup5')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup5">Usage of <span class="code-font"><span class="function-syntax">Streams::get_HTML_file_state</span></span>:<br/>HTML - <a href="5-htm.html#SP4">§4</a>, <a href="5-htm.html#SP5">§5</a>, <a href="5-htm.html#SP6">§6</a>, <a href="5-htm.html#SP8">§8</a>, <a href="5-htm.html#SP9">§9</a>, <a href="5-htm.html#SP11">§11</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="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="element-syntax">as_HTML</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">}</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP21"></a><b>§21. Logging. </b></p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::log</span><button class="popup" onclick="togglePopup('usagePopup6')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup6">Usage of <span class="code-font"><span class="function-syntax">Streams::log</span></span>:<br/>Foundation Module - <a href="1-fm.html#SP8_3">§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>
|
|
<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">-></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">-></span><span class="element-syntax">file_written</span><span class="plain-syntax">, </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-></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">-></span><span class="element-syntax">chars_written</span><span class="plain-syntax">, </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-></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">-></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">-></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>
|
|
<p class="commentary firstcommentary"><a id="SP22"></a><b>§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>
|
|
and returns a <span class="extract"><span class="extract-syntax">text_stream *</span></span> pointer to it; subsequent calls just return this wrapper.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<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>
|
|
<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('usagePopup7')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup7">Usage of <span class="code-font"><span class="function-syntax">Streams::get_stdout</span></span>:<br/><a href="2-str.html#SP5">§5</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</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">stdout_wrapper_initialised</span><span class="plain-syntax"> == </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">) {</span>
|
|
<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">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>
|
|
<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"> &</span><span class="identifier-syntax">STDOUT_struct</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">}</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP23"></a><b>§23. </b>And similarly for the standard error file.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<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>
|
|
<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('usagePopup8')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup8">Usage of <span class="code-font"><span class="function-syntax">Streams::get_stderr</span></span>:<br/><a href="2-str.html#SP5">§5</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</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">stderr_wrapper_initialised</span><span class="plain-syntax"> == </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">) {</span>
|
|
<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">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>
|
|
<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"> &</span><span class="identifier-syntax">STDERR_struct</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">}</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP24"></a><b>§24. Creating file streams. </b>Note that this can fail, if the host filing system refuses to open the file,
|
|
so we return <span class="extract"><span class="extract-syntax">TRUE</span></span> if and only if successful.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<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('usagePopup9')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup9">Usage of <span class="code-font"><span class="function-syntax">Streams::open_to_file</span></span>:<br/><a href="2-str.html#SP9">§9</a><br/>Build Files - <a href="8-bf.html#SP4">§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>
|
|
<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>
|
|
<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>
|
|
<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">-></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">-></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>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-></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>
|
|
<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="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">-></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>
|
|
<p class="commentary firstcommentary"><a id="SP25"></a><b>§25. </b>Similarly for appending:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<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('usagePopup10')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup10">Usage of <span class="code-font"><span class="function-syntax">Streams::open_to_file_append</span></span>:<br/><a href="2-str.html#SP9">§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>
|
|
<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>
|
|
<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>
|
|
<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">-></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">-></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>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-></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>
|
|
<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="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>
|
|
<p class="commentary firstcommentary"><a id="SP26"></a><b>§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
|
|
the text of the stream; this too can fail for host platform reasons, so again
|
|
we return a success code.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<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('usagePopup11')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup11">Usage of <span class="code-font"><span class="function-syntax">Streams::open_to_memory</span></span>:<br/><a href="2-str.html#SP9">§9</a>, <a href="2-str.html#SP28_3">§28.3</a><br/>String Manipulation - <a href="4-sm.html#SP2">§2</a>, <a href="4-sm.html#SP3">§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>
|
|
<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>
|
|
<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">-></span><span class="element-syntax">write_to_memory</span><span class="plain-syntax"> = </span><a href="2-mmr.html#SP24" 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>
|
|
<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="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">-></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="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">-></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>
|
|
<p class="commentary firstcommentary"><a id="SP27"></a><b>§27. </b>The other option avoids <span class="extract"><span class="extract-syntax">malloc</span></span> by using specific storage already available.
|
|
If called validly, this cannot fail.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<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('usagePopup12')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup12">Usage of <span class="code-font"><span class="function-syntax">Streams::new_buffer</span></span>:<br/><a href="2-str.html#SP8">§8</a><br/>Pattern Matching - <a href="4-pm.html#SP10">§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>
|
|
<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"> < </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>
|
|
<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_TT_STRF</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">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>
|
|
<p class="commentary firstcommentary"><a id="SP28"></a><b>§28. Converting from C strings. </b>We then have three ways to open a stream whose initial contents are given
|
|
by a C string. First, a wide string (a sequence of 32-bit Unicode code
|
|
points, null terminated):
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<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('usagePopup13')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup13">Usage of <span class="code-font"><span class="function-syntax">Streams::open_from_wide_string</span></span>:<br/>String Manipulation - <a href="4-sm.html#SP4">§4</a>, <a href="4-sm.html#SP5">§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>
|
|
<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>
|
|
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><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></a></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_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>
|
|
<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>
|
|
|
|
<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('usagePopup14')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup14">Usage of <span class="code-font"><span class="function-syntax">Streams::write_wide_string</span></span>:<br/>String Manipulation - <a href="4-sm.html#SP18">§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>
|
|
<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>
|
|
<span class="plain-syntax">}</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP28_1"></a><b>§28.1. </b>Similarly, an ISO string (a sequence of 8-bit code points in the first
|
|
page of the Unicode set, null terminated):
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<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('usagePopup15')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup15">Usage of <span class="code-font"><span class="function-syntax">Streams::open_from_ISO_string</span></span>:<br/><a href="2-str.html#SP32">§32</a><br/>String Manipulation - <a href="4-sm.html#SP4">§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>
|
|
<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>
|
|
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><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></a></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_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>
|
|
<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>
|
|
|
|
<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('usagePopup16')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup16">Usage of <span class="code-font"><span class="function-syntax">Streams::write_ISO_string</span></span>:<br/><a href="2-str.html#SP32">§32</a><br/>String Manipulation - <a href="4-sm.html#SP18">§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>
|
|
<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>
|
|
<span class="plain-syntax">}</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP28_2"></a><b>§28.2. </b>Finally, a UTF-8 encoded C string:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<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('usagePopup17')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup17">Usage of <span class="code-font"><span class="function-syntax">Streams::open_from_UTF8_string</span></span>:<br/><a href="2-str.html#SP32">§32</a><br/>String Manipulation - <a href="4-sm.html#SP4">§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>
|
|
<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>
|
|
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><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></a></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_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>
|
|
<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>
|
|
|
|
<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('usagePopup18')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup18">Usage of <span class="code-font"><span class="function-syntax">Streams::write_UTF8_string</span></span>:<br/><a href="2-str.html#SP32">§32</a><br/>String Manipulation - <a href="4-sm.html#SP18">§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>
|
|
<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>
|
|
<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">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">, &</span><span class="identifier-syntax">c_string</span><span class="plain-syntax">, </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">, &</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>
|
|
<span class="plain-syntax">}</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP28_3"></a><b>§28.3. </b>...all of which use:
|
|
</p>
|
|
|
|
<p class="commentary"><span class="named-paragraph-container code-font"><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>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<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"> < </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>
|
|
<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>
|
|
<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">§28</a>, <a href="2-str.html#SP28_1">§28.1</a>, <a href="2-str.html#SP28_2">§28.2</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP29"></a><b>§29. Converting to C strings. </b>Now for the converse problem.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<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('usagePopup19')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup19">Usage of <span class="code-font"><span class="function-syntax">Streams::write_as_wide_string</span></span>:<br/>String Manipulation - <a href="4-sm.html#SP6">§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>
|
|
<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">-></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="function-syntax"><stream-></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"> >= </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">-></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">-></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>
|
|
<p class="commentary firstcommentary"><a id="SP30"></a><b>§30. </b>Unicode code points outside the first page are flattened to <span class="extract"><span class="extract-syntax">'?'</span></span> in an
|
|
ISO string:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<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('usagePopup20')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup20">Usage of <span class="code-font"><span class="function-syntax">Streams::write_as_ISO_string</span></span>:<br/><a href="2-str.html#SP32">§32</a><br/>String Manipulation - <a href="4-sm.html#SP6">§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>
|
|
<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">-></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="function-syntax"><stream-></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"> >= </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">-></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"> < </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">-></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>
|
|
<p class="commentary firstcommentary"><a id="SP31"></a><b>§31. </b></p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<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('usagePopup21')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup21">Usage of <span class="code-font"><span class="function-syntax">Streams::write_as_UTF8_string</span></span>:<br/><a href="2-str.html#SP32">§32</a><br/>String Manipulation - <a href="4-sm.html#SP6">§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>
|
|
<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">-></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="function-syntax"><stream-></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">-></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"> >= </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"> >= </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"> >> </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"> >> </span><span class="constant-syntax">6</span><span class="plain-syntax">) & </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"> & </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"> >= </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"> >= </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"> >> </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"> & </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"> >= </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">-></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>
|
|
<p class="commentary firstcommentary"><a id="SP32"></a><b>§32. Locale versions. </b></p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<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('usagePopup22')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup22">Usage of <span class="code-font"><span class="function-syntax">Streams::open_from_locale_string</span></span>:<br/>String Manipulation - <a href="4-sm.html#SP4">§4</a>, <a href="4-sm.html#SP5">§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>
|
|
<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="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>
|
|
<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>
|
|
<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>
|
|
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
|
|
<span class="plain-syntax">}</span>
|
|
|
|
<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('usagePopup23')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup23">Usage of <span class="code-font"><span class="function-syntax">Streams::write_as_locale_string</span></span>:<br/>Shell - <a href="3-shl.html#SP5">§5</a><br/>String Manipulation - <a href="4-sm.html#SP6">§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>
|
|
<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><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>
|
|
<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>
|
|
<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>
|
|
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
|
|
<span class="plain-syntax">}</span>
|
|
|
|
<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('usagePopup24')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup24">Usage of <span class="code-font"><span class="function-syntax">Streams::write_locale_string</span></span>:<br/>Command Line Arguments - <a href="3-cla.html#SP8">§8</a><br/>Directories - <a href="3-drc.html#SP2">§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>
|
|
<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><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>
|
|
<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>
|
|
<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>
|
|
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
|
|
<span class="plain-syntax">}</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP33"></a><b>§33. Flush and close. </b>Note that flush is an operation which can be performed on any stream, including
|
|
<span class="extract"><span class="extract-syntax">NULL</span></span>:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::flush</span><button class="popup" onclick="togglePopup('usagePopup25')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup25">Usage of <span class="code-font"><span class="function-syntax">Streams::flush</span></span>:<br/><a href="2-str.html#SP10">§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>
|
|
<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">-></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">-></span><span class="element-syntax">write_to_file</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax">}</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP34"></a><b>§34. </b>But closing is not allowed for <span class="extract"><span class="extract-syntax">NULL</span></span> or the standard I/O wrappers:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::close</span><button class="popup" onclick="togglePopup('usagePopup26')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup26">Usage of <span class="code-font"><span class="function-syntax">Streams::close</span></span>:<br/><a href="2-str.html#SP9">§9</a>, <a href="2-str.html#SP40">§40</a>, <a href="2-str.html#SP41">§41</a><br/>Build Files - <a href="8-bf.html#SP4">§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="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"> == &</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"> == &</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">-></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">-></span><span class="element-syntax">stream_continues</span><span class="plain-syntax">) {</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><span class="element-syntax">stream_continues</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">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="identifier-syntax">stream</span><span class="plain-syntax">-></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">-></span><span class="element-syntax">write_to_file</span><span class="plain-syntax">) </span><span class="named-paragraph-container code-font"><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></a></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="element-syntax">write_to_memory</span><span class="plain-syntax">) </span><span class="named-paragraph-container code-font"><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></a></span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">}</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP34_1"></a><b>§34.1. </b>Note that we need do nothing to close a memory stream when the storage
|
|
was supplied by our client; it only needs freeing if we were the ones who
|
|
allocated it.
|
|
</p>
|
|
|
|
<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.
|
|
</p>
|
|
|
|
<p class="commentary"><span class="named-paragraph-container code-font"><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>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<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">-></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">-></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>
|
|
<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>
|
|
<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">-></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">-></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="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">-></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="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">§34</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP34_2"></a><b>§34.2. </b>Note that we need do nothing to close a memory stream when the storage
|
|
was supplied by our client; it only needs freeing if we were the ones who
|
|
allocated it. <span class="extract"><span class="extract-syntax">free</span></span> is a void function; in theory it cannot fail, if
|
|
supplied a valid argument.
|
|
</p>
|
|
|
|
<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
|
|
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 — see
|
|
how continuations are made, below.
|
|
</p>
|
|
|
|
<p class="commentary"><span class="named-paragraph-container code-font"><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>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<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="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">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">-></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">-></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><a href="2-mmr.html#SP26" 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">-></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="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">§34</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP35"></a><b>§35. Writing. </b>Our equivalent of <span class="extract"><span class="extract-syntax">fputc</span></span> reads:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::putc</span><button class="popup" onclick="togglePopup('usagePopup27')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup27">Usage of <span class="code-font"><span class="function-syntax">Streams::putc</span></span>:<br/><a href="2-str.html#SP6">§6</a>, <a href="2-str.html#SP28">§28</a>, <a href="2-str.html#SP28_1">§28.1</a>, <a href="2-str.html#SP28_2">§28.2</a>, <a href="2-str.html#SP35_2">§35.2</a>, <a href="2-str.html#SP36">§36</a>, <a href="2-str.html#SP42">§42</a><br/>Writers and Loggers - <a href="2-wal.html#SP6">§6</a>, <a href="2-wal.html#SP6_1_1">§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>
|
|
<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"> >= </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>
|
|
<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 code-font"><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></a></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="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="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">-></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">switch</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">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">"<br>"</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">'&'</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;"</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">'<'</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;"</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">'>'</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">"&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="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="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">-></span><span class="element-syntax">stream_continues</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><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></a></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="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">-></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="named-paragraph-container code-font"><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></a></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">-></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="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">c</span><span class="plain-syntax"> >= </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">-></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">-></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"> >= </span><span class="constant-syntax">0x0300</span><span class="plain-syntax">) && (</span><span class="identifier-syntax">c</span><span class="plain-syntax"> <= </span><span class="constant-syntax">0x036F</span><span class="plain-syntax">) && (</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-></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">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>
|
|
<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">-></span><span class="element-syntax">write_to_memory</span><span class="plain-syntax">)[</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-></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">-></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">-></span><span class="element-syntax">write_to_memory</span><span class="plain-syntax">)[</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-></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">-></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">-></span><span class="element-syntax">chars_written</span><span class="plain-syntax">++;</span>
|
|
<span class="plain-syntax">}</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP35_1"></a><b>§35.1. </b>Where we pack large character values, up to 65535, as follows.
|
|
</p>
|
|
|
|
<p class="commentary"><span class="named-paragraph-container code-font"><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>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<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">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"> >> </span><span class="constant-syntax">12</span><span class="plain-syntax">), </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-></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"> >> </span><span class="constant-syntax">6</span><span class="plain-syntax">) & </span><span class="constant-syntax">0x3f</span><span class="plain-syntax">), </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-></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"> & </span><span class="constant-syntax">0x3f</span><span class="plain-syntax">), </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-></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"> >= </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"> >> </span><span class="constant-syntax">6</span><span class="plain-syntax">), </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-></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"> & </span><span class="constant-syntax">0x3f</span><span class="plain-syntax">), </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-></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">-></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">§35</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP35_2"></a><b>§35.2. </b><span class="named-paragraph-container code-font"><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>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<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">-></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="identifier-syntax">first_stream</span><span class="plain-syntax">-></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">-></span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> & </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"><</span><span class="identifier-syntax">L</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</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>
|
|
<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>
|
|
<span class="plain-syntax"> }</span>
|
|
</pre>
|
|
<ul class="endnotetexts"><li>This code is used in <a href="2-str.html#SP35">§35</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP35_3"></a><b>§35.3. </b>The following is checked before any numerical <span class="extract"><span class="extract-syntax">printf</span></span>-style escape is expanded
|
|
into the stream, or before any single character is written. Thus we cannot
|
|
overrun our buffers unless the expansion of a numerical escape exceeds
|
|
<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),
|
|
we can be pretty confident.
|
|
</p>
|
|
|
|
<p class="commentary">The interesting case occurs when we run out of memory in a memory stream.
|
|
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
|
|
a little more memory than that because we also have to make room for the
|
|
<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 — and it must have been or we would have stopped
|
|
with a fatal error — 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>
|
|
|
|
<p class="commentary"><span class="named-paragraph-container code-font"><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>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<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="element-syntax">chars_written</span><span class="plain-syntax"> + </span><span class="constant-syntax">SPACE_AT_END_OF_STREAM</span><span class="plain-syntax"> >= </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-></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">-></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>
|
|
<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="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">-></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>
|
|
<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#SP24" 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>
|
|
<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>
|
|
<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>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">continuation</span><span class="plain-syntax">-></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">-></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">-></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">-></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="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">§35</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP36"></a><b>§36. </b>Literal printing is just printing with XML escapes switched off:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::literal</span><button class="popup" onclick="togglePopup('usagePopup28')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup28">Usage of <span class="code-font"><span class="function-syntax">Streams::literal</span></span>:<br/><a href="2-str.html#SP35">§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>
|
|
<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">-></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">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">-></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">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>
|
|
<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">-></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>
|
|
<p class="commentary firstcommentary"><a id="SP37"></a><b>§37. </b>Shifting indentation. For every indent there must be an equal and opposite
|
|
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>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::indent</span><button class="popup" onclick="togglePopup('usagePopup29')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup29">Usage of <span class="code-font"><span class="function-syntax">Streams::indent</span></span>:<br/><a href="2-str.html#SP7">§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="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">-></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>
|
|
|
|
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::outdent</span><button class="popup" onclick="togglePopup('usagePopup30')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup30">Usage of <span class="code-font"><span class="function-syntax">Streams::outdent</span></span>:<br/><a href="2-str.html#SP7">§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="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">-></span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> & </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>
|
|
<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>
|
|
<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">-></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>
|
|
|
|
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::set_indentation</span><button class="popup" onclick="togglePopup('usagePopup31')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup31">Usage of <span class="code-font"><span class="function-syntax">Streams::set_indentation</span></span>:<br/><a href="2-str.html#SP7">§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>
|
|
<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">-></span><span class="element-syntax">stream_flags</span><span class="plain-syntax"> & </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">-></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">-></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>
|
|
<p class="commentary firstcommentary"><a id="SP38"></a><b>§38. </b>We can read the position for any stream, including <span class="extract"><span class="extract-syntax">NULL</span></span>, but no matter
|
|
how much is written to <span class="extract"><span class="extract-syntax">NULL</span></span> this position never budges.
|
|
</p>
|
|
|
|
<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>
|
|
field.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::get_position</span><button class="popup" onclick="togglePopup('usagePopup32')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup32">Usage of <span class="code-font"><span class="function-syntax">Streams::get_position</span></span>:<br/><a href="2-str.html#SP11">§11</a>, <a href="2-str.html#SP13">§13</a><br/>String Manipulation - <a href="4-sm.html#SP8">§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>
|
|
<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">-></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">-></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>
|
|
<p class="commentary firstcommentary"><a id="SP39"></a><b>§39. Memory-stream-only functions. </b>While it would be easy enough to implement this for file streams too, there's
|
|
no point, since it is used only in concert with backspacing.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::latest</span><button class="popup" onclick="togglePopup('usagePopup33')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup33">Usage of <span class="code-font"><span class="function-syntax">Streams::latest</span></span>:<br/><a href="2-str.html#SP14">§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="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">-></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">-></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="element-syntax">stream_continues</span><span class="plain-syntax">-></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"> = </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-></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="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">-></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">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">-></span><span class="element-syntax">write_to_memory</span><span class="plain-syntax">)[</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-></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>
|
|
<p class="commentary firstcommentary"><a id="SP40"></a><b>§40. </b>Accessing characters by index. Note that the stream terminates at the first
|
|
zero byte found, so that putting a zero truncates it.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<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('usagePopup34')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup34">Usage of <span class="code-font"><span class="function-syntax">Streams::get_char_at_index</span></span>:<br/>String Manipulation - <a href="4-sm.html#SP13">§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>
|
|
<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">-></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"> >= </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-></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">-></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">-></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">-></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">-></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>
|
|
|
|
<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('usagePopup35')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup35">Usage of <span class="code-font"><span class="function-syntax">Streams::put_char_at_index</span></span>:<br/>String Manipulation - <a href="4-sm.html#SP14">§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>
|
|
<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">-></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">-></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="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"> >= </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-></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">-></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">-></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">-></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">-></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">-></span><span class="element-syntax">stream_continues</span><span class="plain-syntax">) {</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><span class="element-syntax">stream_continues</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">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>
|
|
<p class="commentary firstcommentary"><a id="SP41"></a><b>§41. </b>Now for what is the trickiest function, because the position may be moved back
|
|
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>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::set_position</span><button class="popup" onclick="togglePopup('usagePopup36')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup36">Usage of <span class="code-font"><span class="function-syntax">Streams::set_position</span></span>:<br/><a href="2-str.html#SP13">§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>
|
|
<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">position</span><span class="plain-syntax"> < </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>
|
|
<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="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">-></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="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">-></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"> > </span><span class="identifier-syntax">stream</span><span class="plain-syntax">-></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">-></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">-></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">-></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">-></span><span class="element-syntax">write_to_memory</span><span class="plain-syntax">)[</span><span class="identifier-syntax">stream</span><span class="plain-syntax">-></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">-></span><span class="element-syntax">stream_continues</span><span class="plain-syntax">) {</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><span class="element-syntax">stream_continues</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">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>
|
|
<p class="commentary firstcommentary"><a id="SP42"></a><b>§42. </b>Lastly, our copying function, where <span class="extract"><span class="extract-syntax">from</span></span> has to be a memory stream (or
|
|
<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>).
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::copy</span><button class="popup" onclick="togglePopup('usagePopup37')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup37">Usage of <span class="code-font"><span class="function-syntax">Streams::copy</span></span>:<br/><a href="2-str.html#SP14">§14</a>, <a href="2-str.html#SP43">§43</a><br/>String Manipulation - <a href="4-sm.html#SP3">§3</a>, <a href="4-sm.html#SP17">§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>
|
|
<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">-></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">-></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="function-syntax"><from-></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">-></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>
|
|
<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>
|
|
<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">-></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">-></span><span class="element-syntax">stream_continues</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax">}</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP43"></a><b>§43. Writer. </b>This writes one stream into another one, which implements <span class="extract"><span class="extract-syntax">%S</span></span>.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Streams::writer</span><button class="popup" onclick="togglePopup('usagePopup38')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup38">Usage of <span class="code-font"><span class="function-syntax">Streams::writer</span></span>:<br/>Foundation Module - <a href="1-fm.html#SP8_1">§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>
|
|
<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>
|
|
<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>
|
|
<span class="plain-syntax">}</span>
|
|
</pre>
|
|
<nav role="progress"><div class="progresscontainer">
|
|
<ul class="progressbar"><li class="progressprev"><a href="2-fc.html">❮</a></li><li class="progresschapter"><a href="P-abgtf.html">P</a></li><li class="progresschapter"><a href="1-fm.html">1</a></li><li class="progresscurrentchapter">2</li><li class="progresssection"><a href="2-dl.html">dl</a></li><li class="progresssection"><a href="2-mmr.html">mmr</a></li><li class="progresssection"><a href="2-fc.html">fc</a></li><li class="progresscurrent">str</li><li class="progresssection"><a href="2-wal.html">wal</a></li><li class="progresssection"><a href="2-mth.html">mth</a></li><li class="progresssection"><a href="2-llas.html">llas</a></li><li class="progresssection"><a href="2-dct.html">dct</a></li><li class="progresssection"><a href="2-trs.html">trs</a></li><li class="progresschapter"><a href="3-em.html">3</a></li><li class="progresschapter"><a href="4-chr.html">4</a></li><li class="progresschapter"><a href="5-htm.html">5</a></li><li class="progresschapter"><a href="6-bf.html">6</a></li><li class="progresschapter"><a href="7-vn.html">7</a></li><li class="progresschapter"><a href="8-ws.html">8</a></li><li class="progressnext"><a href="2-wal.html">❯</a></li></ul></div>
|
|
</nav><!--End of weave-->
|
|
|
|
</main>
|
|
</body>
|
|
</html>
|
|
|