884 lines
120 KiB
HTML
884 lines
120 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html>
|
|
<head>
|
|
<title>4/ws</title>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
<meta http-equiv="Content-Language" content="en-gb">
|
|
<link href="inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
</head>
|
|
<body>
|
|
|
|
<!--Weave of '4/sm' generated by 7-->
|
|
<ul class="crumbs"><li><a href="../webs.html">★</a></li><li><a href="index.html">foundation</a></li><li><a href="index.html#4">Chapter 4: Text Handling</a></li><li><b>String Manipulation</b></li></ul><p class="purpose">Convenient routines for manipulating strings of text.</p>
|
|
|
|
<ul class="toc"><li><a href="#SP1">§1. Strings are streams</a></li><li><a href="#SP2">§2. New strings</a></li><li><a href="#SP4">§4. Converting from C strings</a></li><li><a href="#SP6">§6. Converting to C strings</a></li><li><a href="#SP7">§7. Converting to integers</a></li><li><a href="#SP8">§8. Length</a></li><li><a href="#SP9">§9. Position markers</a></li><li><a href="#SP13">§13. Character operations</a></li><li><a href="#SP15">§15. Truncation</a></li><li><a href="#SP16">§16. Copying</a></li><li><a href="#SP18">§18. Comparisons</a></li><li><a href="#SP22">§22. White space</a></li><li><a href="#SP24">§24. Deleting characters</a></li><li><a href="#SP25">§25. Substrings</a></li><li><a href="#SP26">§26. Shim for literal storage</a></li></ul><hr class="tocbar">
|
|
|
|
<p class="inwebparagraph"><a id="SP1"></a><b>§1. Strings are streams. </b>Although Foundation provides limited facilities for handling standard or
|
|
wide C-style strings — that is, null-terminated arrays of <code class="display"><span class="extract">char</span></code> or
|
|
<code class="display"><span class="extract">wchar_t</span></code> — these are not encouraged.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Instead, a standard string for a program using Foundation is nothing more than
|
|
a text stream (see Chapter 2). These are unbounded in size, with memory
|
|
allocation being automatic; they are encoded as an array of Unicode code
|
|
points (not as UTF-8, -16 or -32); and they do not use a null or indeed any
|
|
terminator. This has the advantage that finding the length of a string, and
|
|
appending characters to it, run in constant time regardless of the string's
|
|
length. It is is entirely feasible to write hundreds of megabytes of
|
|
output into a string, if that's useful, and no substantial slowing down
|
|
will occur in handling the result (except, of course, that printing it
|
|
out on screen would take a while). Strings are also very well protected
|
|
against buffer overruns.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The present section of code provides convenient routines for creating,
|
|
duplicating, modifying and examining such strings.
|
|
</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2"></a><b>§2. New strings. </b>Sometimes we want to make a new string in the sense of allocating more
|
|
memory to hold it. These objects won't automatically be destroyed, so we
|
|
shouldn't call these routines too casually. If we need a string just for
|
|
some space to play with for a short while, it's better to create one
|
|
with <code class="display"><span class="extract">TEMPORARY_TEXT</span></code> and then get rid of it with <code class="display"><span class="extract">DISCARD_TEXT</span></code>, macros
|
|
defined in Chapter 2.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The capacity of these strings is unlimited in principle, and the number
|
|
here is just the size of the initial memory block, which is fastest to
|
|
access.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="functiontext">Str::new</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Str::new_with_capacity</span><span class="plain">(32);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="functiontext">Str::new_with_capacity</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain">) {</span>
|
|
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Streams::open_to_memory</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">c</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">S</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Str::dispose_of</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">text</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">text</span><span class="plain">) </span><span class="identifier">STREAM_CLOSE</span><span class="plain">(</span><span class="identifier">text</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Str::new is used in <a href="#SP3">§3</a>, 2/dl (<a href="2-dl.html#SP4_1">§4.1</a>), 2/dct (<a href="2-dct.html#SP7_3_1">§7.3.1</a>), 3/cla (<a href="3-cla.html#SP5">§5</a>), 5/ee (<a href="5-ee.html#SP5">§5</a>).</p>
|
|
|
|
<p class="endnote">The function Str::new_with_capacity is used in 3/pth (<a href="3-pth.html#SP4">§4</a>), 3/fln (<a href="3-fln.html#SP2">§2</a>).</p>
|
|
|
|
<p class="endnote">The function Str::dispose_of is used in 2/dct (<a href="2-dct.html#SP7_3_2">§7.3.2</a>, <a href="2-dct.html#SP11">§11</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3"></a><b>§3. </b>Duplication of an existing string is complicated only by the issue that
|
|
we want the duplicate always to be writeable, so that <code class="display"><span class="extract">NULL</span></code> can't be
|
|
duplicated as <code class="display"><span class="extract">NULL</span></code>.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="functiontext">Str::duplicate</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">E</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">E</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Str::new</span><span class="plain">();</span>
|
|
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Streams::open_to_memory</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">E</span><span class="plain">)+4)) {</span>
|
|
<span class="functiontext">Streams::copy</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">E</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">S</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Str::duplicate is used in 2/dct (<a href="2-dct.html#SP7_3_1">§7.3.1</a>), 3/cla (<a href="3-cla.html#SP4_1">§4.1</a>), 5/ee (<a href="5-ee.html#SP5">§5</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP4"></a><b>§4. Converting from C strings. </b>Here we open text streams initially equal to the given C strings, and
|
|
with the capacity of the initial block large enough to hold the whole
|
|
thing plus a little extra, for efficiency's sake.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="functiontext">Str::new_from_wide_string</span><span class="plain">(</span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">C_string</span><span class="plain">) {</span>
|
|
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Streams::open_from_wide_string</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">C_string</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">S</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="functiontext">Str::new_from_ISO_string</span><span class="plain">(</span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">C_string</span><span class="plain">) {</span>
|
|
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Streams::open_from_ISO_string</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">C_string</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">S</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="functiontext">Str::new_from_UTF8_string</span><span class="plain">(</span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">C_string</span><span class="plain">) {</span>
|
|
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Streams::open_from_UTF8_string</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">C_string</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">S</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="functiontext">Str::new_from_locale_string</span><span class="plain">(</span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">C_string</span><span class="plain">) {</span>
|
|
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Streams::open_from_locale_string</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">C_string</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">S</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Str::new_from_wide_string is used in 3/cla (<a href="3-cla.html#SP4">§4</a>, <a href="3-cla.html#SP9">§9</a>), 3/pth (<a href="3-pth.html#SP3">§3</a>), 5/ee (<a href="5-ee.html#SP5">§5</a>).</p>
|
|
|
|
<p class="endnote">The function Str::new_from_ISO_string appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Str::new_from_UTF8_string appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Str::new_from_locale_string is used in 3/pth (<a href="3-pth.html#SP2">§2</a>, <a href="3-pth.html#SP3">§3</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5"></a><b>§5. </b>And sometimes we want to use an existing stream object:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="functiontext">Str::from_wide_string</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">c_string</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Streams::open_from_wide_string</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">c_string</span><span class="plain">) == </span><span class="constant">FALSE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">S</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="functiontext">Str::from_locale_string</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">c_string</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Streams::open_from_locale_string</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">c_string</span><span class="plain">) == </span><span class="constant">FALSE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">S</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Str::from_wide_string appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Str::from_locale_string appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6"></a><b>§6. Converting to C strings. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Str::copy_to_ISO_string</span><span class="plain">(</span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">C_string</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">buffer_size</span><span class="plain">) {</span>
|
|
<span class="functiontext">Streams::write_as_ISO_string</span><span class="plain">(</span><span class="identifier">C_string</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">buffer_size</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Str::copy_to_UTF8_string</span><span class="plain">(</span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">C_string</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">buffer_size</span><span class="plain">) {</span>
|
|
<span class="functiontext">Streams::write_as_UTF8_string</span><span class="plain">(</span><span class="identifier">C_string</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">buffer_size</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Str::copy_to_wide_string</span><span class="plain">(</span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">C_string</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">buffer_size</span><span class="plain">) {</span>
|
|
<span class="functiontext">Streams::write_as_wide_string</span><span class="plain">(</span><span class="identifier">C_string</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">buffer_size</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Str::copy_to_locale_string</span><span class="plain">(</span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">C_string</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">buffer_size</span><span class="plain">) {</span>
|
|
<span class="functiontext">Streams::write_as_locale_string</span><span class="plain">(</span><span class="identifier">C_string</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">buffer_size</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Str::copy_to_ISO_string appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Str::copy_to_UTF8_string appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Str::copy_to_wide_string appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Str::copy_to_locale_string is used in 3/pth (<a href="3-pth.html#SP8">§8</a>), 3/fln (<a href="3-fln.html#SP10">§10</a>), 3/drc (<a href="3-drc.html#SP2">§2</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP7"></a><b>§7. Converting to integers. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Str::atoi</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">index</span><span class="plain">) {</span>
|
|
<span class="reserved">char</span><span class="plain"> </span><span class="identifier">buffer</span><span class="plain">[32];</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">string_position</span><span class="plain"> </span><span class="identifier">P</span><span class="plain"> = </span><span class="functiontext">Str::at</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">index</span><span class="plain">);</span>
|
|
<span class="plain">((</span><span class="identifier">i</span><span class="plain"> < 31) && (</span><span class="identifier">P</span><span class="element">.index</span><span class="plain"> < </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">))); </span><span class="identifier">P</span><span class="plain"> = </span><span class="functiontext">Str::forward</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">))</span>
|
|
<span class="identifier">buffer</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">++] = (</span><span class="reserved">char</span><span class="plain">) </span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">);</span>
|
|
<span class="identifier">buffer</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = 0;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">atoi</span><span class="plain">(</span><span class="identifier">buffer</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Str::atoi is used in 3/cla (<a href="3-cla.html#SP7">§7</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8"></a><b>§8. Length. </b>A puritan would return a <code class="display"><span class="extract">size_t</span></code> here, but I am not a puritan.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">) {</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Streams::get_position</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Str::len is used in <a href="#SP3">§3</a>, <a href="#SP7">§7</a>, <a href="#SP10">§10</a>, <a href="#SP11">§11</a>, <a href="#SP12">§12</a>, <a href="#SP13">§13</a>, <a href="#SP14">§14</a>, <a href="#SP15">§15</a>, <a href="#SP16">§16</a>, <a href="#SP18">§18</a>, <a href="#SP19">§19</a>, <a href="#SP20">§20</a>, <a href="#SP21">§21</a>, <a href="#SP23">§23</a>, <a href="#SP24">§24</a>, <a href="#SP25">§25</a>, 2/dl (<a href="2-dl.html#SP9">§9</a>), 3/cla (<a href="3-cla.html#SP8">§8</a>, <a href="3-cla.html#SP9">§9</a>, <a href="3-cla.html#SP9_1">§9.1</a>), 3/pth (<a href="3-pth.html#SP4">§4</a>, <a href="3-pth.html#SP5">§5</a>, <a href="3-pth.html#SP7">§7</a>), 3/fln (<a href="3-fln.html#SP2">§2</a>, <a href="3-fln.html#SP3">§3</a>, <a href="3-fln.html#SP5">§5</a>, <a href="3-fln.html#SP9">§9</a>), 4/taa (<a href="4-taa.html#SP2_1">§2.1</a>), 4/pm (<a href="4-pm.html#SP3">§3</a>, <a href="4-pm.html#SP4">§4</a>, <a href="4-pm.html#SP11_3">§11.3</a>, <a href="4-pm.html#SP14">§14</a>), 5/htm (<a href="5-htm.html#SP7">§7</a>, <a href="5-htm.html#SP15">§15</a>), 5/ee (<a href="5-ee.html#SP7_1">§7.1</a>, <a href="5-ee.html#SP7_2_3">§7.2.3</a>, <a href="5-ee.html#SP7_2_4">§7.2.4</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP9"></a><b>§9. Position markers. </b>A position marker is a lightweight way to refer to a particular position
|
|
in a given string. Position 0 is before the first character; if, for
|
|
example, the string contains the word "gazpacho", then position 8 represents
|
|
the end of the string, after the "o". Negative positions are not allowed,
|
|
but positive ones well past the end of the string are legal. (Doing things
|
|
at those positions may well not be, of course.)
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">string_position</span><span class="plain"> {</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">index</span><span class="plain">;</span>
|
|
<span class="plain">} </span><span class="reserved">string_position</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The structure string_position is private to this section.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10"></a><b>§10. </b>You can then find a position in a given string thus:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">string_position</span><span class="plain"> </span><span class="functiontext">Str::start</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">) {</span>
|
|
<span class="reserved">string_position</span><span class="plain"> </span><span class="identifier">P</span><span class="plain">; </span><span class="identifier">P</span><span class="element">.S</span><span class="plain"> = </span><span class="identifier">S</span><span class="plain">; </span><span class="identifier">P</span><span class="element">.index</span><span class="plain"> = 0; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">P</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">string_position</span><span class="plain"> </span><span class="functiontext">Str::at</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain"> < 0) </span><span class="identifier">i</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain"> > </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">)) </span><span class="identifier">i</span><span class="plain"> = </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">);</span>
|
|
<span class="reserved">string_position</span><span class="plain"> </span><span class="identifier">P</span><span class="plain">; </span><span class="identifier">P</span><span class="element">.S</span><span class="plain"> = </span><span class="identifier">S</span><span class="plain">; </span><span class="identifier">P</span><span class="element">.index</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">P</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">string_position</span><span class="plain"> </span><span class="functiontext">Str::end</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">) {</span>
|
|
<span class="reserved">string_position</span><span class="plain"> </span><span class="identifier">P</span><span class="plain">; </span><span class="identifier">P</span><span class="element">.S</span><span class="plain"> = </span><span class="identifier">S</span><span class="plain">; </span><span class="identifier">P</span><span class="element">.index</span><span class="plain"> = </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">); </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">P</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Str::start is used in <a href="#SP12">§12</a>, <a href="#SP19">§19</a>, <a href="#SP23">§23</a>, 3/pth (<a href="3-pth.html#SP5">§5</a>).</p>
|
|
|
|
<p class="endnote">The function Str::at is used in <a href="#SP7">§7</a>, <a href="#SP13">§13</a>, <a href="#SP14">§14</a>, <a href="#SP15">§15</a>, <a href="#SP16">§16</a>, <a href="#SP24">§24</a>, 3/pth (<a href="3-pth.html#SP4">§4</a>, <a href="3-pth.html#SP5">§5</a>), 3/fln (<a href="3-fln.html#SP2">§2</a>, <a href="3-fln.html#SP3">§3</a>, <a href="3-fln.html#SP9">§9</a>).</p>
|
|
|
|
<p class="endnote">The function Str::end is used in <a href="#SP12">§12</a>, 3/fln (<a href="3-fln.html#SP9">§9</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11"></a><b>§11. </b>And you can step forwards or backwards:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">string_position</span><span class="plain"> </span><span class="functiontext">Str::back</span><span class="plain">(</span><span class="reserved">string_position</span><span class="plain"> </span><span class="identifier">P</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">P</span><span class="element">.index</span><span class="plain"> > 0) </span><span class="identifier">P</span><span class="element">.index</span><span class="plain">--; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">P</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">string_position</span><span class="plain"> </span><span class="functiontext">Str::forward</span><span class="plain">(</span><span class="reserved">string_position</span><span class="plain"> </span><span class="identifier">P</span><span class="plain">) {</span>
|
|
<span class="identifier">P</span><span class="element">.index</span><span class="plain">++; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">P</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">string_position</span><span class="plain"> </span><span class="functiontext">Str::plus</span><span class="plain">(</span><span class="reserved">string_position</span><span class="plain"> </span><span class="identifier">P</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">increment</span><span class="plain">) {</span>
|
|
<span class="identifier">P</span><span class="element">.index</span><span class="plain"> += </span><span class="identifier">increment</span><span class="plain">; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">P</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Str::width_between</span><span class="plain">(</span><span class="reserved">string_position</span><span class="plain"> </span><span class="identifier">P1</span><span class="plain">, </span><span class="reserved">string_position</span><span class="plain"> </span><span class="identifier">P2</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">P1</span><span class="element">.S</span><span class="plain"> != </span><span class="identifier">P2</span><span class="element">.S</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"positions are in different strings"</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">P2</span><span class="element">.index</span><span class="plain"> - </span><span class="identifier">P1</span><span class="element">.index</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Str::in_range</span><span class="plain">(</span><span class="reserved">string_position</span><span class="plain"> </span><span class="identifier">P</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">P</span><span class="element">.index</span><span class="plain"> < </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">P</span><span class="element">.S</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Str::index</span><span class="plain">(</span><span class="reserved">string_position</span><span class="plain"> </span><span class="identifier">P</span><span class="plain">) {</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">P</span><span class="element">.index</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Str::back is used in <a href="#SP12">§12</a>, 3/fln (<a href="3-fln.html#SP9">§9</a>).</p>
|
|
|
|
<p class="endnote">The function Str::forward is used in <a href="#SP7">§7</a>, <a href="#SP16">§16</a>, <a href="#SP19">§19</a>, <a href="#SP23">§23</a>, <a href="#SP24">§24</a>, 3/fln (<a href="3-fln.html#SP2">§2</a>).</p>
|
|
|
|
<p class="endnote">The function Str::plus appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Str::width_between appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Str::in_range appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Str::index appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP12"></a><b>§12. </b>This leads to the following convenient loop macros:
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="identifier">LOOP_THROUGH_TEXT</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">ST</span><span class="plain">)</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">string_position</span><span class="plain"> </span><span class="identifier">P</span><span class="plain"> = </span><span class="functiontext">Str::start</span><span class="plain">(</span><span class="identifier">ST</span><span class="plain">); </span><span class="identifier">P</span><span class="element">.index</span><span class="plain"> < </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">P</span><span class="element">.S</span><span class="plain">); </span><span class="identifier">P</span><span class="element">.index</span><span class="plain">++)</span>
|
|
<span class="definitionkeyword">define</span> <span class="identifier">LOOP_BACKWARDS_THROUGH_TEXT</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">ST</span><span class="plain">)</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">string_position</span><span class="plain"> </span><span class="identifier">P</span><span class="plain"> = </span><span class="functiontext">Str::back</span><span class="plain">(</span><span class="functiontext">Str::end</span><span class="plain">(</span><span class="identifier">ST</span><span class="plain">)); </span><span class="identifier">P</span><span class="element">.index</span><span class="plain"> >= 0; </span><span class="identifier">P</span><span class="element">.index</span><span class="plain">--)</span>
|
|
</pre>
|
|
<p class="inwebparagraph"><a id="SP13"></a><b>§13. Character operations. </b>How to get at individual characters, then, now that we can refer to positions:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="identifier">wchar_t</span><span class="plain"> </span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="reserved">string_position</span><span class="plain"> </span><span class="identifier">P</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">P</span><span class="element">.S</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">P</span><span class="element">.index</span><span class="plain"> < 0)) </span><span class="reserved">return</span><span class="plain"> 0;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Streams::get_char_at_index</span><span class="plain">(</span><span class="identifier">P</span><span class="element">.S</span><span class="plain">, </span><span class="identifier">P</span><span class="element">.index</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="identifier">wchar_t</span><span class="plain"> </span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">index</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">S</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">index</span><span class="plain"> < 0)) </span><span class="reserved">return</span><span class="plain"> 0;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Streams::get_char_at_index</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">index</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="identifier">wchar_t</span><span class="plain"> </span><span class="functiontext">Str::get_first_char</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">) {</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="functiontext">Str::at</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, 0));</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="identifier">wchar_t</span><span class="plain"> </span><span class="functiontext">Str::get_last_char</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">L</span><span class="plain"> = </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L</span><span class="plain"> == 0) </span><span class="reserved">return</span><span class="plain"> 0;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="functiontext">Str::at</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-1));</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Str::get is used in <a href="#SP7">§7</a>, <a href="#SP16">§16</a>, <a href="#SP19">§19</a>, <a href="#SP21">§21</a>, <a href="#SP22">§22</a>, <a href="#SP23">§23</a>, <a href="#SP24">§24</a>, <a href="#SP25">§25</a>, 2/dct (<a href="2-dct.html#SP4">§4</a>), 3/pth (<a href="3-pth.html#SP4">§4</a>, <a href="3-pth.html#SP5">§5</a>), 3/fln (<a href="3-fln.html#SP2">§2</a>, <a href="3-fln.html#SP3">§3</a>, <a href="3-fln.html#SP7">§7</a>, <a href="3-fln.html#SP8">§8</a>, <a href="3-fln.html#SP9">§9</a>), 3/shl (<a href="3-shl.html#SP1">§1</a>), 4/pm (<a href="4-pm.html#SP5">§5</a>), 5/ee (<a href="5-ee.html#SP5">§5</a>).</p>
|
|
|
|
<p class="endnote">The function Str::get_at is used in <a href="#SP20">§20</a>, <a href="#SP23">§23</a>, <a href="#SP25">§25</a>, 3/pth (<a href="3-pth.html#SP7">§7</a>), 3/fln (<a href="3-fln.html#SP5">§5</a>), 4/taa (<a href="4-taa.html#SP2">§2</a>), 4/pm (<a href="4-pm.html#SP3">§3</a>, <a href="4-pm.html#SP4">§4</a>, <a href="4-pm.html#SP11">§11</a>, <a href="4-pm.html#SP11_4">§11.4</a>, <a href="4-pm.html#SP11_6">§11.6</a>, <a href="4-pm.html#SP14">§14</a>, <a href="4-pm.html#SP14_1">§14.1</a>).</p>
|
|
|
|
<p class="endnote">The function Str::get_first_char appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Str::get_last_char appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP14"></a><b>§14. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Str::put</span><span class="plain">(</span><span class="reserved">string_position</span><span class="plain"> </span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">wchar_t</span><span class="plain"> </span><span class="identifier">C</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">P</span><span class="element">.index</span><span class="plain"> < 0) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"wrote before start of string"</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">P</span><span class="element">.S</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"wrote to null stream"</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">ext</span><span class="plain"> = </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">P</span><span class="element">.S</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">P</span><span class="element">.index</span><span class="plain"> > </span><span class="identifier">ext</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"wrote beyond end of string"</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">P</span><span class="element">.index</span><span class="plain"> == </span><span class="identifier">ext</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">C</span><span class="plain">) </span><span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">P</span><span class="element">.S</span><span class="plain">, (</span><span class="reserved">int</span><span class="plain">) </span><span class="identifier">C</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="functiontext">Streams::put_char_at_index</span><span class="plain">(</span><span class="identifier">P</span><span class="element">.S</span><span class="plain">, </span><span class="identifier">P</span><span class="element">.index</span><span class="plain">, </span><span class="identifier">C</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Str::put_at</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">index</span><span class="plain">, </span><span class="identifier">wchar_t</span><span class="plain"> </span><span class="identifier">C</span><span class="plain">) {</span>
|
|
<span class="functiontext">Str::put</span><span class="plain">(</span><span class="functiontext">Str::at</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">index</span><span class="plain">), </span><span class="identifier">C</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Str::put is used in <a href="#SP15">§15</a>, <a href="#SP23">§23</a>, <a href="#SP24">§24</a>, 5/ee (<a href="5-ee.html#SP5">§5</a>).</p>
|
|
|
|
<p class="endnote">The function Str::put_at is used in 4/tf (<a href="4-tf.html#SP5_3">§5.3</a>, <a href="4-tf.html#SP6">§6</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15"></a><b>§15. Truncation. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Str::clear</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">) {</span>
|
|
<span class="functiontext">Str::truncate</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, 0);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Str::truncate</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">len</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">len</span><span class="plain"> < 0) </span><span class="identifier">len</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">len</span><span class="plain"> < </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">)) </span><span class="functiontext">Str::put</span><span class="plain">(</span><span class="functiontext">Str::at</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">len</span><span class="plain">), 0);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Str::clear is used in <a href="#SP16">§16</a>, <a href="#SP17">§17</a>, <a href="#SP24">§24</a>, 3/drc (<a href="3-drc.html#SP2">§2</a>), 4/tf (<a href="4-tf.html#SP6">§6</a>), 4/pm (<a href="4-pm.html#SP11_6">§11.6</a>).</p>
|
|
|
|
<p class="endnote">The function Str::truncate is used in <a href="#SP23">§23</a>, <a href="#SP24">§24</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP16"></a><b>§16. Copying. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Str::concatenate</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S1</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S2</span><span class="plain">) {</span>
|
|
<span class="functiontext">Streams::copy</span><span class="plain">(</span><span class="identifier">S1</span><span class="plain">, </span><span class="identifier">S2</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Str::copy</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S1</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S2</span><span class="plain">) {</span>
|
|
<span class="functiontext">Str::clear</span><span class="plain">(</span><span class="identifier">S1</span><span class="plain">);</span>
|
|
<span class="functiontext">Streams::copy</span><span class="plain">(</span><span class="identifier">S1</span><span class="plain">, </span><span class="identifier">S2</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Str::copy_tail</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S1</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S2</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">from</span><span class="plain">) {</span>
|
|
<span class="functiontext">Str::clear</span><span class="plain">(</span><span class="identifier">S1</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">L</span><span class="plain"> = </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S2</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">from</span><span class="plain"> < </span><span class="identifier">L</span><span class="plain">)</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">string_position</span><span class="plain"> </span><span class="identifier">P</span><span class="plain"> = </span><span class="functiontext">Str::at</span><span class="plain">(</span><span class="identifier">S2</span><span class="plain">, </span><span class="identifier">from</span><span class="plain">); </span><span class="identifier">P</span><span class="element">.index</span><span class="plain"> < </span><span class="identifier">L</span><span class="plain">; </span><span class="identifier">P</span><span class="plain"> = </span><span class="functiontext">Str::forward</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">))</span>
|
|
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">S1</span><span class="plain">, </span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">));</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Str::concatenate appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Str::copy is used in 3/cla (<a href="3-cla.html#SP7">§7</a>), 4/pm (<a href="4-pm.html#SP14">§14</a>), 5/ee (<a href="5-ee.html#SP5">§5</a>, <a href="5-ee.html#SP7_1">§7.1</a>).</p>
|
|
|
|
<p class="endnote">The function Str::copy_tail appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP17"></a><b>§17. </b>A subtly different operation is to set a string equal to a given C string:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Str::copy_ISO_string</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">C_string</span><span class="plain">) {</span>
|
|
<span class="functiontext">Str::clear</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">);</span>
|
|
<span class="functiontext">Streams::write_ISO_string</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">C_string</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Str::copy_UTF8_string</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">C_string</span><span class="plain">) {</span>
|
|
<span class="functiontext">Str::clear</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">);</span>
|
|
<span class="functiontext">Streams::write_UTF8_string</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">C_string</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Str::copy_wide_string</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">C_string</span><span class="plain">) {</span>
|
|
<span class="functiontext">Str::clear</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">);</span>
|
|
<span class="functiontext">Streams::write_wide_string</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">C_string</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Str::copy_ISO_string appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Str::copy_UTF8_string appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Str::copy_wide_string appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP18"></a><b>§18. Comparisons. </b>We provide both case sensitive and insensitive versions.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Str::eq</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S1</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S2</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S1</span><span class="plain">) == </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S2</span><span class="plain">)) && (</span><span class="functiontext">Str::cmp</span><span class="plain">(</span><span class="identifier">S1</span><span class="plain">, </span><span class="identifier">S2</span><span class="plain">) == 0)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Str::eq_insensitive</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S1</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S2</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S1</span><span class="plain">) == </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S2</span><span class="plain">)) && (</span><span class="functiontext">Str::cmp_insensitive</span><span class="plain">(</span><span class="identifier">S1</span><span class="plain">, </span><span class="identifier">S2</span><span class="plain">) == 0)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Str::ne</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S1</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S2</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S1</span><span class="plain">) != </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S2</span><span class="plain">)) || (</span><span class="functiontext">Str::cmp</span><span class="plain">(</span><span class="identifier">S1</span><span class="plain">, </span><span class="identifier">S2</span><span class="plain">) != 0)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Str::ne_insensitive</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S1</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S2</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S1</span><span class="plain">) != </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S2</span><span class="plain">)) || (</span><span class="functiontext">Str::cmp_insensitive</span><span class="plain">(</span><span class="identifier">S1</span><span class="plain">, </span><span class="identifier">S2</span><span class="plain">) != 0)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Str::eq is used in 2/dl (<a href="2-dl.html#SP9">§9</a>), 2/dct (<a href="2-dct.html#SP7_3">§7.3</a>), 3/pth (<a href="3-pth.html#SP3">§3</a>), 3/fln (<a href="3-fln.html#SP11">§11</a>).</p>
|
|
|
|
<p class="endnote">The function Str::eq_insensitive appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Str::ne appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Str::ne_insensitive appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19"></a><b>§19. </b>These two routines produce a numerical string difference suitable for
|
|
alphabetic sorting, like <code class="display"><span class="extract">strlen</span></code> in the C standard library.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Str::cmp</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S1</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S2</span><span class="plain">) {</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">string_position</span><span class="plain"> </span><span class="identifier">P</span><span class="plain"> = </span><span class="functiontext">Str::start</span><span class="plain">(</span><span class="identifier">S1</span><span class="plain">), </span><span class="identifier">Q</span><span class="plain"> = </span><span class="functiontext">Str::start</span><span class="plain">(</span><span class="identifier">S2</span><span class="plain">);</span>
|
|
<span class="plain">(</span><span class="identifier">P</span><span class="element">.index</span><span class="plain"> < </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S1</span><span class="plain">)) && (</span><span class="identifier">Q</span><span class="element">.index</span><span class="plain"> < </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S2</span><span class="plain">));</span>
|
|
<span class="identifier">P</span><span class="plain"> = </span><span class="functiontext">Str::forward</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">), </span><span class="identifier">Q</span><span class="plain"> = </span><span class="functiontext">Str::forward</span><span class="plain">(</span><span class="identifier">Q</span><span class="plain">)) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">d</span><span class="plain"> = (</span><span class="reserved">int</span><span class="plain">) </span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">) - (</span><span class="reserved">int</span><span class="plain">) </span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="identifier">Q</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">d</span><span class="plain"> != 0) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">d</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S1</span><span class="plain">) - </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S2</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Str::cmp_insensitive</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S1</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S2</span><span class="plain">) {</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">string_position</span><span class="plain"> </span><span class="identifier">P</span><span class="plain"> = </span><span class="functiontext">Str::start</span><span class="plain">(</span><span class="identifier">S1</span><span class="plain">), </span><span class="identifier">Q</span><span class="plain"> = </span><span class="functiontext">Str::start</span><span class="plain">(</span><span class="identifier">S2</span><span class="plain">);</span>
|
|
<span class="plain">(</span><span class="identifier">P</span><span class="element">.index</span><span class="plain"> < </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S1</span><span class="plain">)) && (</span><span class="identifier">Q</span><span class="element">.index</span><span class="plain"> < </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S2</span><span class="plain">));</span>
|
|
<span class="identifier">P</span><span class="plain"> = </span><span class="functiontext">Str::forward</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">), </span><span class="identifier">Q</span><span class="plain"> = </span><span class="functiontext">Str::forward</span><span class="plain">(</span><span class="identifier">Q</span><span class="plain">)) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">d</span><span class="plain"> = </span><span class="identifier">tolower</span><span class="plain">((</span><span class="reserved">int</span><span class="plain">) </span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">)) - </span><span class="identifier">tolower</span><span class="plain">((</span><span class="reserved">int</span><span class="plain">) </span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="identifier">Q</span><span class="plain">));</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">d</span><span class="plain"> != 0) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">d</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S1</span><span class="plain">) - </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S2</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Str::cmp is used in <a href="#SP18">§18</a>.</p>
|
|
|
|
<p class="endnote">The function Str::cmp_insensitive is used in <a href="#SP18">§18</a>, 3/cla (<a href="3-cla.html#SP10">§10</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP20"></a><b>§20. </b>It's sometimes useful to see whether two strings agree on their last
|
|
<code class="display"><span class="extract">N</span></code> characters, or their first <code class="display"><span class="extract">N</span></code>. For example,
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">Str::suffix_eq(I"wayzgoose", I"snow goose", N)</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph">will return <code class="display"><span class="extract">TRUE</span></code> for <code class="display"><span class="extract">N</span></code> equal to 0 to 5, and <code class="display"><span class="extract">FALSE</span></code> thereafter.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">(The Oxford English Dictionary defines a "wayzgoose" as a holiday outing
|
|
for the staff of a publishing house.)
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Str::prefix_eq</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S1</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S2</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">L1</span><span class="plain"> = </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S1</span><span class="plain">), </span><span class="identifier">L2</span><span class="plain"> = </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S2</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">N</span><span class="plain"> > </span><span class="identifier">L1</span><span class="plain">) || (</span><span class="identifier">N</span><span class="plain"> > </span><span class="identifier">L2</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><</span><span class="identifier">N</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">S1</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">) != </span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">S2</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">))</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Str::suffix_eq</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S1</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S2</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">L1</span><span class="plain"> = </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S1</span><span class="plain">), </span><span class="identifier">L2</span><span class="plain"> = </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S2</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">N</span><span class="plain"> > </span><span class="identifier">L1</span><span class="plain">) || (</span><span class="identifier">N</span><span class="plain"> > </span><span class="identifier">L2</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=1; </span><span class="identifier">i</span><span class="plain"><=</span><span class="identifier">N</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">S1</span><span class="plain">, </span><span class="identifier">L1</span><span class="plain">-</span><span class="identifier">i</span><span class="plain">) != </span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">S2</span><span class="plain">, </span><span class="identifier">L2</span><span class="plain">-</span><span class="identifier">i</span><span class="plain">))</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Str::begins_with_wide_string</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">prefix</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">prefix</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (*</span><span class="identifier">prefix</span><span class="plain"> == 0)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">S</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = 0; </span><span class="identifier">prefix</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]; </span><span class="identifier">i</span><span class="plain">++)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">) != </span><span class="identifier">prefix</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">])</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Str::ends_with_wide_string</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">suffix</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">suffix</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (*</span><span class="identifier">suffix</span><span class="plain"> == 0)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">S</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = 0, </span><span class="identifier">at</span><span class="plain"> = </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">) - (</span><span class="reserved">int</span><span class="plain">) </span><span class="identifier">wcslen</span><span class="plain">(</span><span class="identifier">suffix</span><span class="plain">); </span><span class="identifier">suffix</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]; </span><span class="identifier">i</span><span class="plain">++)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">at</span><span class="plain">+</span><span class="identifier">i</span><span class="plain">) != </span><span class="identifier">suffix</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">])</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Str::prefix_eq is used in 3/pth (<a href="3-pth.html#SP7">§7</a>), 3/fln (<a href="3-fln.html#SP5">§5</a>).</p>
|
|
|
|
<p class="endnote">The function Str::suffix_eq appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Str::begins_with_wide_string is used in 3/cla (<a href="3-cla.html#SP4_1">§4.1</a>).</p>
|
|
|
|
<p class="endnote">The function Str::ends_with_wide_string appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP21"></a><b>§21. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Str::eq_wide_string</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S1</span><span class="plain">, </span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">S2</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S1</span><span class="plain">) == (</span><span class="reserved">int</span><span class="plain">) </span><span class="identifier">wcslen</span><span class="plain">(</span><span class="identifier">S2</span><span class="plain">)) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0;</span>
|
|
<span class="identifier">LOOP_THROUGH_TEXT</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">S1</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">) != </span><span class="identifier">S2</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">++])</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Str::eq_narrow_string</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S1</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">S2</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S1</span><span class="plain">) == (</span><span class="reserved">int</span><span class="plain">) </span><span class="identifier">strlen</span><span class="plain">(</span><span class="identifier">S2</span><span class="plain">)) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0;</span>
|
|
<span class="identifier">LOOP_THROUGH_TEXT</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">S1</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">) != (</span><span class="identifier">wchar_t</span><span class="plain">) </span><span class="identifier">S2</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">++])</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Str::ne_wide_string</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S1</span><span class="plain">, </span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">S2</span><span class="plain">) {</span>
|
|
<span class="reserved">return</span><span class="plain"> (</span><span class="functiontext">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">S1</span><span class="plain">, </span><span class="identifier">S2</span><span class="plain">)?</span><span class="constant">FALSE</span><span class="plain">:</span><span class="constant">TRUE</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Str::eq_wide_string is used in 2/dl (<a href="2-dl.html#SP9">§9</a>), 3/fln (<a href="3-fln.html#SP9">§9</a>), 5/ee (<a href="5-ee.html#SP5">§5</a>, <a href="5-ee.html#SP7_2_1">§7.2.1</a>, <a href="5-ee.html#SP7_3_2_1">§7.3.2.1</a>).</p>
|
|
|
|
<p class="endnote">The function Str::eq_narrow_string appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Str::ne_wide_string appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP22"></a><b>§22. White space. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Str::is_whitespace</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">) {</span>
|
|
<span class="identifier">LOOP_THROUGH_TEXT</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Characters::is_space_or_tab</span><span class="plain">(</span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">)) == </span><span class="constant">FALSE</span><span class="plain">)</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Str::is_whitespace appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP23"></a><b>§23. </b>This removes spaces and tabs from both ends:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Str::trim_white_space</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">len</span><span class="plain"> = </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">), </span><span class="identifier">i</span><span class="plain"> = 0, </span><span class="identifier">j</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">string_position</span><span class="plain"> </span><span class="identifier">F</span><span class="plain"> = </span><span class="functiontext">Str::start</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">);</span>
|
|
<span class="identifier">LOOP_THROUGH_TEXT</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (!(</span><span class="functiontext">Characters::is_space_or_tab</span><span class="plain">(</span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">)))) { </span><span class="identifier">F</span><span class="plain"> = </span><span class="identifier">P</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">; }</span>
|
|
<span class="identifier">i</span><span class="plain">++;</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">LOOP_BACKWARDS_THROUGH_TEXT</span><span class="plain">(</span><span class="identifier">Q</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (!(</span><span class="functiontext">Characters::is_space_or_tab</span><span class="plain">(</span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="identifier">Q</span><span class="plain">)))) </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="identifier">j</span><span class="plain">++;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">+</span><span class="identifier">j</span><span class="plain"> > </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">)) </span><span class="functiontext">Str::truncate</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, 0);</span>
|
|
<span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="identifier">len</span><span class="plain"> = </span><span class="identifier">len</span><span class="plain"> - </span><span class="identifier">j</span><span class="plain">;</span>
|
|
<span class="functiontext">Str::truncate</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">len</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain"> > 0) {</span>
|
|
<span class="reserved">string_position</span><span class="plain"> </span><span class="identifier">P</span><span class="plain"> = </span><span class="functiontext">Str::start</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">);</span>
|
|
<span class="identifier">wchar_t</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">do</span><span class="plain"> {</span>
|
|
<span class="identifier">c</span><span class="plain"> = </span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="identifier">F</span><span class="plain">);</span>
|
|
<span class="functiontext">Str::put</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">c</span><span class="plain">);</span>
|
|
<span class="identifier">P</span><span class="plain"> = </span><span class="functiontext">Str::forward</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">); </span><span class="identifier">F</span><span class="plain"> = </span><span class="functiontext">Str::forward</span><span class="plain">(</span><span class="identifier">F</span><span class="plain">);</span>
|
|
<span class="plain">} </span><span class="reserved">while</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> != 0);</span>
|
|
<span class="identifier">len</span><span class="plain"> = </span><span class="identifier">len</span><span class="plain"> - </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="functiontext">Str::truncate</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">len</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Str::trim_white_space_at_end</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">shortened</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain"> = </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">)-1; </span><span class="identifier">j</span><span class="plain"> >= 0; </span><span class="identifier">j</span><span class="plain">--) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Characters::is_space_or_tab</span><span class="plain">(</span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">j</span><span class="plain">))) {</span>
|
|
<span class="functiontext">Str::truncate</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">j</span><span class="plain">);</span>
|
|
<span class="identifier">shortened</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">shortened</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Str::trim_all_white_space_at_end</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">shortened</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain"> = </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">)-1; </span><span class="identifier">j</span><span class="plain"> >= 0; </span><span class="identifier">j</span><span class="plain">--) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Characters::is_babel_whitespace</span><span class="plain">(</span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">j</span><span class="plain">))) {</span>
|
|
<span class="functiontext">Str::truncate</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">j</span><span class="plain">);</span>
|
|
<span class="identifier">shortened</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">shortened</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Str::trim_white_space appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Str::trim_white_space_at_end appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Str::trim_all_white_space_at_end appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP24"></a><b>§24. Deleting characters. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Str::delete_first_character</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">) {</span>
|
|
<span class="functiontext">Str::delete_nth_character</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, 0);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Str::delete_last_character</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">) > 0)</span>
|
|
<span class="functiontext">Str::truncate</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">) - 1);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Str::delete_nth_character</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">n</span><span class="plain">) {</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">string_position</span><span class="plain"> </span><span class="identifier">P</span><span class="plain"> = </span><span class="functiontext">Str::at</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">n</span><span class="plain">); </span><span class="identifier">P</span><span class="element">.index</span><span class="plain"> < </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">P</span><span class="element">.S</span><span class="plain">); </span><span class="identifier">P</span><span class="plain"> = </span><span class="functiontext">Str::forward</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">))</span>
|
|
<span class="functiontext">Str::put</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="functiontext">Str::forward</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">)));</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Str::delete_n_characters</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">n</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">L</span><span class="plain"> = </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">) - </span><span class="identifier">n</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L</span><span class="plain"> <= 0) </span><span class="functiontext">Str::clear</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">);</span>
|
|
<span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><</span><span class="identifier">L</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
|
|
<span class="functiontext">Str::put</span><span class="plain">(</span><span class="functiontext">Str::at</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">), </span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="functiontext">Str::at</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">+</span><span class="identifier">n</span><span class="plain">)));</span>
|
|
<span class="functiontext">Str::truncate</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Str::delete_first_character appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Str::delete_last_character appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Str::delete_nth_character appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Str::delete_n_characters is used in 3/cla (<a href="3-cla.html#SP4_1">§4.1</a>), 3/pth (<a href="3-pth.html#SP7">§7</a>), 3/fln (<a href="3-fln.html#SP5">§5</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP25"></a><b>§25. Substrings. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Str::substr</span><span class="plain">(</span><span class="constant">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">string_position</span><span class="plain"> </span><span class="identifier">from</span><span class="plain">, </span><span class="reserved">string_position</span><span class="plain"> </span><span class="identifier">to</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">from</span><span class="element">.S</span><span class="plain"> != </span><span class="identifier">to</span><span class="element">.S</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"substr on two different strings"</span><span class="plain">);</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = </span><span class="identifier">from</span><span class="element">.index</span><span class="plain">; </span><span class="identifier">i</span><span class="plain"> < </span><span class="identifier">to</span><span class="element">.index</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
|
|
<span class="identifier">PUT</span><span class="plain">(</span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">from</span><span class="element">.S</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">));</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Str::includes_character</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">wchar_t</span><span class="plain"> </span><span class="identifier">c</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">S</span><span class="plain">)</span>
|
|
<span class="identifier">LOOP_THROUGH_TEXT</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">) == </span><span class="identifier">c</span><span class="plain">)</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Str::includes_wide_string_at</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">prefix</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">prefix</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (*</span><span class="identifier">prefix</span><span class="plain"> == 0)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">S</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = 0; </span><span class="identifier">prefix</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]; </span><span class="identifier">i</span><span class="plain">++)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">+</span><span class="identifier">j</span><span class="plain">) != </span><span class="identifier">prefix</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">])</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Str::includes_wide_string_at_insensitive</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">prefix</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">prefix</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (*</span><span class="identifier">prefix</span><span class="plain"> == 0)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">S</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = 0; </span><span class="identifier">prefix</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]; </span><span class="identifier">i</span><span class="plain">++)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Characters::tolower</span><span class="plain">(</span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">+</span><span class="identifier">j</span><span class="plain">)) != </span><span class="functiontext">Characters::tolower</span><span class="plain">(</span><span class="identifier">prefix</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]))</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Str::includes</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">LS</span><span class="plain"> = </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">LT</span><span class="plain"> = </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">);</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><</span><span class="identifier">LS</span><span class="plain">-</span><span class="identifier">LT</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">failed</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain">=0; </span><span class="identifier">j</span><span class="plain"><</span><span class="identifier">LT</span><span class="plain">; </span><span class="identifier">j</span><span class="plain">++)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">+</span><span class="identifier">j</span><span class="plain">) != </span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">j</span><span class="plain">)) {</span>
|
|
<span class="identifier">failed</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">failed</span><span class="plain"> == </span><span class="constant">FALSE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Str::substr is used in 3/fln (<a href="3-fln.html#SP3">§3</a>).</p>
|
|
|
|
<p class="endnote">The function Str::includes_character appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Str::includes_wide_string_at appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Str::includes_wide_string_at_insensitive appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Str::includes appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP26"></a><b>§26. Shim for literal storage. </b>This is where all of those I-literals created by Inweb are stored at run-time.
|
|
Note that every instance of, say, <code class="display"><span class="extract">I"fish"</span></code> would return the same string,
|
|
that is, the same <code class="display"><span class="extract">text_stream *</span></code> value. To prevent nasty accidents, this
|
|
is marked so that the stream value, "fish", cannot be modified at run-time.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The dictionary look-up here would not be thread-safe, so it's protected by
|
|
a mutex. There's no real performance concern because the following routine
|
|
is run just once per I-literal in the source code, when the program starts up.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">dictionary</span><span class="plain"> *</span><span class="identifier">string_literals_dictionary</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
|
|
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="functiontext">Str::literal</span><span class="plain">(</span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">wide_C_string</span><span class="plain">) {</span>
|
|
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">answer</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">CREATE_MUTEX</span><span class="plain">(</span><span class="identifier">mutex</span><span class="plain">);</span>
|
|
<span class="identifier">LOCK_MUTEX</span><span class="plain">(</span><span class="identifier">mutex</span><span class="plain">);</span>
|
|
<<span class="cwebmacro">Look in dictionary of string literals</span> <span class="cwebmacronumber">26.1</span>><span class="plain">;</span>
|
|
<span class="identifier">UNLOCK_MUTEX</span><span class="plain">(</span><span class="identifier">mutex</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">answer</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Str::literal appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP26_1"></a><b>§26.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Look in dictionary of string literals</span> <span class="cwebmacronumber">26.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">string_literals_dictionary</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)</span>
|
|
<span class="identifier">string_literals_dictionary</span><span class="plain"> = </span><span class="functiontext">Dictionaries::new</span><span class="plain">(100, </span><span class="constant">TRUE</span><span class="plain">);</span>
|
|
<span class="identifier">answer</span><span class="plain"> = </span><span class="functiontext">Dictionaries::get_text_literal</span><span class="plain">(</span><span class="identifier">string_literals_dictionary</span><span class="plain">, </span><span class="identifier">wide_C_string</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">answer</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
|
|
<span class="functiontext">Dictionaries::create_literal</span><span class="plain">(</span><span class="identifier">string_literals_dictionary</span><span class="plain">, </span><span class="identifier">wide_C_string</span><span class="plain">);</span>
|
|
<span class="identifier">answer</span><span class="plain"> = </span><span class="functiontext">Dictionaries::get_text_literal</span><span class="plain">(</span><span class="identifier">string_literals_dictionary</span><span class="plain">, </span><span class="identifier">wide_C_string</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">answer</span><span class="plain">, </span><span class="string">"%w"</span><span class="plain">, </span><span class="identifier">wide_C_string</span><span class="plain">);</span>
|
|
<span class="functiontext">Streams::mark_as_read_only</span><span class="plain">(</span><span class="identifier">answer</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP26">§26</a>.</p>
|
|
|
|
<hr class="tocbar">
|
|
<ul class="toc"><li><a href="4-ws.html">Back to 'Wide Strings.w'</a></li><li><a href="4-tf.html">Continue with 'Text Files'</a></li></ul><hr class="tocbar">
|
|
<!--End of weave-->
|
|
</body>
|
|
</html>
|
|
|