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

297 lines
38 KiB
HTML
Raw Normal View History

2019-02-04 22:26:45 +00:00
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
2020-04-08 22:41:00 +00:00
<title>Linked Lists and Stacks</title>
<meta name="viewport" content="width=device-width initial-scale=1">
2019-02-04 22:26:45 +00:00
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
2020-04-10 20:29:28 +00:00
2019-02-04 22:26:45 +00:00
</head>
<body>
<nav role="navigation">
<h1><a href="../webs.html">Sources</a></h1>
<ul>
<li><a href="../inweb/index.html">inweb</a></li>
</ul>
<h2>Foundation</h2>
<ul>
<li><a href="../foundation-module/index.html">foundation-module</a></li>
<li><a href="../foundation-test/index.html">foundation-test</a></li>
</ul>
</nav>
<main role="main">
2020-04-08 22:41:00 +00:00
<!--Weave of 'Linked Lists and Stacks' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">foundation</a></li><li><a href="index.html#2">Chapter 2: Memory, Streams and Collections</a></li><li><b>Linked Lists and Stacks</b></li></ul><p class="purpose">A simple implementation for single-linked lists of objects allocated by Foundation's memory manager, and for last-in-first-out stacks of same.</p>
2019-02-04 22:26:45 +00:00
<ul class="toc"><li><a href="#SP1">&#167;1. Implementation</a></li><li><a href="#SP6">&#167;6. A function call API</a></li><li><a href="#SP7">&#167;7. A macro-ized API</a></li><li><a href="#SP9">&#167;9. LIFO stacks</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Implementation. </b>Basically, there's a head structure, which points to a chain of body structures,
each linking to the next. But to reduce memory manager overhead, we're going to store
the first few body structures inside the head structure: that way, for a list of just
a few items, only one call to the memory manager is needed.
</p>
<pre class="definitions">
2020-04-06 11:26:10 +00:00
<span class="definitionkeyword">define</span> <span class="constant">NO_LL_EARLY_ITEMS</span><span class="plain"> </span><span class="constant">32</span>
2019-02-04 22:26:45 +00:00
</pre>
<pre class="display">
2020-04-06 11:26:10 +00:00
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">linked_list</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">linked_list_item</span><span class="plain"> *</span><span class="identifier">first_list_item</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">linked_list_item</span><span class="plain"> *</span><span class="identifier">last_list_item</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">linked_list_length</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">linked_list_item</span><span class="plain"> </span><span class="identifier">early_items</span><span class="plain">[</span><span class="constant">NO_LL_EARLY_ITEMS</span><span class="plain">];</span>
<span class="constant">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">linked_list</span><span class="plain">;</span>
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">linked_list_item</span><span class="plain"> {</span>
<span class="reserved">void</span><span class="plain"> *</span><span class="identifier">item_contents</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">linked_list_item</span><span class="plain"> *</span><span class="identifier">next_list_item</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">linked_list_item</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure linked_list is private to this section.</p>
<p class="endnote">The structure linked_list_item is private to this section.</p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b></p>
<pre class="display">
2020-04-06 11:26:10 +00:00
<span class="reserved">linked_list</span><span class="plain"> *</span><span class="functiontext">LinkedLists::new</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">linked_list</span><span class="plain"> *</span><span class="identifier">ll</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">linked_list</span><span class="plain">);</span>
<span class="identifier">ll</span><span class="plain">-&gt;</span><span class="element">linked_list_length</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="identifier">ll</span><span class="plain">-&gt;</span><span class="element">first_list_item</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">ll</span><span class="plain">-&gt;</span><span class="element">last_list_item</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">ll</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function LinkedLists::new is used in <a href="#SP7">&#167;7</a>, <a href="#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>The following runs in constant time, i.e., performs no loops. In general we
want speed rather than memory efficiency.
</p>
<pre class="display">
2020-04-06 11:26:10 +00:00
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">LinkedLists::add</span><span class="plain">(</span><span class="reserved">linked_list</span><span class="plain"> *</span><span class="identifier">L</span><span class="plain">, </span><span class="reserved">void</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">to_end</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L</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">"null list"</span><span class="plain">);</span>
<span class="reserved">linked_list_item</span><span class="plain"> *</span><span class="identifier">item</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">linked_list_length</span><span class="plain"> &lt; </span><span class="constant">NO_LL_EARLY_ITEMS</span><span class="plain">)</span>
<span class="identifier">item</span><span class="plain"> = &amp;(</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">early_items</span><span class="plain">[</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">linked_list_length</span><span class="plain">]);</span>
<span class="reserved">else</span>
<span class="identifier">item</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">linked_list_item</span><span class="plain">);</span>
<span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">linked_list_item</span><span class="plain">);</span>
<span class="identifier">item</span><span class="plain">-&gt;</span><span class="element">item_contents</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">to_end</span><span class="plain">) {</span>
<span class="identifier">item</span><span class="plain">-&gt;</span><span class="element">next_list_item</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">last_list_item</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">first_list_item</span><span class="plain"> = </span><span class="identifier">item</span><span class="plain">;</span>
<span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">last_list_item</span><span class="plain"> = </span><span class="identifier">item</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">last_list_item</span><span class="plain">-&gt;</span><span class="element">next_list_item</span><span class="plain"> = </span><span class="identifier">item</span><span class="plain">;</span>
<span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">last_list_item</span><span class="plain"> = </span><span class="identifier">item</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
2020-04-06 11:26:10 +00:00
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">item</span><span class="plain">-&gt;</span><span class="element">next_list_item</span><span class="plain"> = </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">first_list_item</span><span class="plain">;</span>
<span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">first_list_item</span><span class="plain"> = </span><span class="identifier">item</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">last_list_item</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">last_list_item</span><span class="plain"> = </span><span class="identifier">item</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
2020-04-06 11:26:10 +00:00
<span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">linked_list_length</span><span class="plain">++;</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function LinkedLists::add is used in <a href="#SP7">&#167;7</a>, <a href="#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>Because of the direction of the links, only removing from the front is quick:
</p>
<pre class="display">
2020-04-06 11:26:10 +00:00
<span class="reserved">void</span><span class="plain"> *</span><span class="functiontext">LinkedLists::remove_from_front</span><span class="plain">(</span><span class="reserved">linked_list</span><span class="plain"> *</span><span class="identifier">L</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L</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">"null list"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">first_list_item</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">"empty list can't be popped"</span><span class="plain">);</span>
<span class="reserved">linked_list_item</span><span class="plain"> *</span><span class="identifier">top</span><span class="plain"> = </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">first_list_item</span><span class="plain">;</span>
<span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">first_list_item</span><span class="plain"> = </span><span class="identifier">top</span><span class="plain">-&gt;</span><span class="element">next_list_item</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">first_list_item</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">last_list_item</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">linked_list_length</span><span class="plain">--;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">top</span><span class="plain">-&gt;</span><span class="element">item_contents</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function LinkedLists::remove_from_front is used in <a href="#SP5">&#167;5</a>, <a href="#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>It's rather slower to delete from a known position in the middle:
</p>
<pre class="display">
2020-04-06 11:26:10 +00:00
<span class="reserved">void</span><span class="plain"> *</span><span class="functiontext">LinkedLists::delete</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">linked_list</span><span class="plain"> *</span><span class="identifier">L</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L</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">"null list"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">N</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) || (</span><span class="identifier">N</span><span class="plain"> &gt;= </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">linked_list_length</span><span class="plain">)) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"index not valid"</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="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">LinkedLists::remove_from_front</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">);</span>
2019-02-04 22:26:45 +00:00
2020-04-06 11:26:10 +00:00
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">linked_list_item</span><span class="plain"> *</span><span class="identifier">item</span><span class="plain"> = </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="identifier">first_list_item</span><span class="plain">; </span><span class="identifier">item</span><span class="plain">; </span><span class="identifier">item</span><span class="plain"> = </span><span class="identifier">item</span><span class="plain">-&gt;</span><span class="element">next_list_item</span><span class="plain">) {</span>
2019-02-04 22:26:45 +00:00
<span class="identifier">N</span><span class="plain">--;</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">N</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">last_list_item</span><span class="plain"> == </span><span class="identifier">item</span><span class="plain">-&gt;</span><span class="element">next_list_item</span><span class="plain">) </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">last_list_item</span><span class="plain"> = </span><span class="identifier">item</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> *</span><span class="identifier">contents_deleted</span><span class="plain"> = </span><span class="identifier">item</span><span class="plain">-&gt;</span><span class="element">next_list_item</span><span class="plain">-&gt;</span><span class="element">item_contents</span><span class="plain">;</span>
<span class="identifier">item</span><span class="plain">-&gt;</span><span class="element">next_list_item</span><span class="plain"> = </span><span class="identifier">item</span><span class="plain">-&gt;</span><span class="element">next_list_item</span><span class="plain">-&gt;</span><span class="element">next_list_item</span><span class="plain">;</span>
<span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">linked_list_length</span><span class="plain">--;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">contents_deleted</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"index not found"</span><span class="plain">);</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function LinkedLists::delete is used in <a href="#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. A function call API. </b></p>
<pre class="display">
2020-04-06 11:26:10 +00:00
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">LinkedLists::len</span><span class="plain">(</span><span class="reserved">linked_list</span><span class="plain"> *</span><span class="identifier">L</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">L</span><span class="plain">?(</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">linked_list_length</span><span class="plain">):0;</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">linked_list_item</span><span class="plain"> *</span><span class="functiontext">LinkedLists::first</span><span class="plain">(</span><span class="reserved">linked_list</span><span class="plain"> *</span><span class="identifier">L</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">L</span><span class="plain">?(</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">first_list_item</span><span class="plain">):</span><span class="identifier">NULL</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">void</span><span class="plain"> *</span><span class="functiontext">LinkedLists::entry</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">linked_list</span><span class="plain"> *</span><span class="identifier">L</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">N</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) || (</span><span class="identifier">L</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">N</span><span class="plain"> &gt;= </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">linked_list_length</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">for</span><span class="plain"> (</span><span class="reserved">linked_list_item</span><span class="plain"> *</span><span class="identifier">I</span><span class="plain"> = </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">first_list_item</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="identifier">I</span><span class="plain">-&gt;</span><span class="element">next_list_item</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="constant">0</span><span class="plain">)</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">I</span><span class="plain">-&gt;</span><span class="identifier">item_contents</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">linked_list_item</span><span class="plain"> *</span><span class="functiontext">LinkedLists::last</span><span class="plain">(</span><span class="reserved">linked_list</span><span class="plain"> *</span><span class="identifier">L</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">L</span><span class="plain">?(</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">last_list_item</span><span class="plain">):</span><span class="identifier">NULL</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">linked_list_item</span><span class="plain"> *</span><span class="functiontext">LinkedLists::next</span><span class="plain">(</span><span class="reserved">linked_list_item</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">I</span><span class="plain">?(</span><span class="identifier">I</span><span class="plain">-&gt;</span><span class="element">next_list_item</span><span class="plain">):</span><span class="identifier">NULL</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">void</span><span class="plain"> *</span><span class="functiontext">LinkedLists::content</span><span class="plain">(</span><span class="reserved">linked_list_item</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">I</span><span class="plain">?(</span><span class="identifier">I</span><span class="plain">-&gt;</span><span class="element">item_contents</span><span class="plain">):</span><span class="identifier">NULL</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function LinkedLists::len is used in <a href="#SP10">&#167;10</a>, 5/ee (<a href="5-ee.html#SP7_3">&#167;7.3</a>).</p>
2020-03-23 15:04:43 +00:00
<p class="endnote">The function LinkedLists::first is used in <a href="#SP7">&#167;7</a>, 7/vn (<a href="7-vn.html#SP8">&#167;8</a>).</p>
2019-02-04 22:26:45 +00:00
<p class="endnote">The function LinkedLists::entry is used in <a href="#SP7">&#167;7</a>.</p>
<p class="endnote">The function LinkedLists::last is used in <a href="#SP7">&#167;7</a>.</p>
2020-03-23 15:04:43 +00:00
<p class="endnote">The function LinkedLists::next is used in <a href="#SP7">&#167;7</a>, 7/vn (<a href="7-vn.html#SP8">&#167;8</a>).</p>
2019-02-04 22:26:45 +00:00
2020-03-23 15:04:43 +00:00
<p class="endnote">The function LinkedLists::content is used in <a href="#SP7">&#167;7</a>, 7/vn (<a href="7-vn.html#SP8">&#167;8</a>).</p>
2019-02-04 22:26:45 +00:00
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. A macro-ized API. </b>These intentionally hide the implementation. The difference between
<code class="display"><span class="extract">FIRST_IN_LINKED_LIST</span></code> and <code class="display"><span class="extract">FIRST_ITEM_IN_LINKED_LIST</span></code> is that one returns
the first structure in the list, and the other returns the first
<code class="display"><span class="extract">linked_list_item</span></code> chunk in the list. From the latter you can make the
former using <code class="display"><span class="extract">CONTENT_IN_ITEM</span></code>, but not vice versa. The same object
may be listed in many different lists, so if all you have is the object,
you don't know its place in the list.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="identifier">NEW_LINKED_LIST</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">)</span>
2020-04-06 11:26:10 +00:00
<span class="plain">(</span><span class="functiontext">LinkedLists::new</span><span class="plain">())</span>
2019-02-04 22:26:45 +00:00
<span class="definitionkeyword">define</span> <span class="identifier">FIRST_ITEM_IN_LINKED_LIST</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">)</span>
2020-04-06 11:26:10 +00:00
<span class="plain">(</span><span class="functiontext">LinkedLists::first</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">))</span>
2019-02-04 22:26:45 +00:00
<span class="definitionkeyword">define</span> <span class="identifier">ENTRY_IN_LINKED_LIST</span><span class="plain">(</span><span class="identifier">N</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">)</span>
2020-04-06 11:26:10 +00:00
<span class="plain">((</span><span class="identifier">T</span><span class="plain"> *) (</span><span class="functiontext">LinkedLists::entry</span><span class="plain">(</span><span class="identifier">N</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">)))</span>
2019-02-04 22:26:45 +00:00
<span class="definitionkeyword">define</span> <span class="identifier">DELETE_FROM_LINKED_LIST</span><span class="plain">(</span><span class="identifier">N</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">)</span>
2020-04-06 11:26:10 +00:00
<span class="plain">((</span><span class="identifier">T</span><span class="plain"> *) (</span><span class="functiontext">LinkedLists::delete</span><span class="plain">(</span><span class="identifier">N</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">)))</span>
2019-02-04 22:26:45 +00:00
<span class="definitionkeyword">define</span> <span class="identifier">LAST_ITEM_IN_LINKED_LIST</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">)</span>
2020-04-06 11:26:10 +00:00
<span class="plain">(</span><span class="functiontext">LinkedLists::last</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">))</span>
2019-02-04 22:26:45 +00:00
<span class="definitionkeyword">define</span> <span class="identifier">NEXT_ITEM_IN_LINKED_LIST</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">)</span>
2020-04-06 11:26:10 +00:00
<span class="plain">(</span><span class="functiontext">LinkedLists::next</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">))</span>
2019-02-04 22:26:45 +00:00
<span class="definitionkeyword">define</span> <span class="identifier">CONTENT_IN_ITEM</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">)</span>
2020-04-06 11:26:10 +00:00
<span class="plain">((</span><span class="identifier">T</span><span class="plain"> *) (</span><span class="functiontext">LinkedLists::content</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">)))</span>
2019-02-04 22:26:45 +00:00
<span class="definitionkeyword">define</span> <span class="identifier">ADD_TO_LINKED_LIST</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">)</span>
2020-04-06 11:26:10 +00:00
<span class="functiontext">LinkedLists::add</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">, (</span><span class="reserved">void</span><span class="plain"> *) (</span><span class="identifier">I</span><span class="plain">), </span><span class="constant">TRUE</span><span class="plain">)</span>
2019-02-04 22:26:45 +00:00
<span class="definitionkeyword">define</span> <span class="identifier">FIRST_IN_LINKED_LIST</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">)</span>
2020-04-06 11:26:10 +00:00
<span class="plain">((</span><span class="identifier">T</span><span class="plain"> *) (</span><span class="functiontext">LinkedLists::content</span><span class="plain">(</span><span class="functiontext">LinkedLists::first</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">))))</span>
2019-02-04 22:26:45 +00:00
<span class="definitionkeyword">define</span> <span class="identifier">LAST_IN_LINKED_LIST</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">)</span>
2020-04-06 11:26:10 +00:00
<span class="plain">((</span><span class="identifier">T</span><span class="plain"> *) (</span><span class="functiontext">LinkedLists::content</span><span class="plain">(</span><span class="functiontext">LinkedLists::last</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">))))</span>
2019-02-04 22:26:45 +00:00
</pre>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>The following macro requires slight care to use: the list <code class="display"><span class="extract">L</span></code> needs to be
calculable without side-effects. There's no such worry over <code class="display"><span class="extract">P</span></code> or <code class="display"><span class="extract">T</span></code>, since
they're just identifier names: the loop variable and the type name respectively.
</p>
<p class="inwebparagraph">Note that the loop variable <code class="display"><span class="extract">P</span></code> must already be defined. Inside the loop body,
a new variable will also then exist, <code class="display"><span class="extract">P_item</span></code>, to refer to the item which
points to <code class="display"><span class="extract">P</span></code>. This allows us to iterate despite the comments above.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">)</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">linked_list_item</span><span class="plain"> *</span><span class="identifier">P</span><span class="plain">##</span><span class="identifier">_item</span><span class="plain"> = (</span><span class="identifier">P</span><span class="plain"> = </span><span class="identifier">FIRST_IN_LINKED_LIST</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">), </span><span class="identifier">FIRST_ITEM_IN_LINKED_LIST</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">));</span>
2019-02-04 22:26:45 +00:00
<span class="identifier">P</span><span class="plain">##</span><span class="identifier">_item</span><span class="plain">;</span>
<span class="identifier">P</span><span class="plain">##</span><span class="identifier">_item</span><span class="plain"> = (</span><span class="identifier">P</span><span class="plain"> = </span><span class="identifier">CONTENT_IN_ITEM</span><span class="plain">(</span><span class="identifier">NEXT_ITEM_IN_LINKED_LIST</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">##</span><span class="identifier">_item</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">), </span><span class="identifier">T</span><span class="plain">), </span><span class="identifier">NEXT_ITEM_IN_LINKED_LIST</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">##</span><span class="identifier">_item</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">)))</span>
</pre>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. LIFO stacks. </b>The above gives us an almost free implementation of LIFO, last-in-first-out,
stacks, where we represent a stack as a linked list whose first entry is at
the front. To push an item, we add it at the front; to pull, we remove the
front iten.
</p>
<p class="inwebparagraph">We provide an abstract type name for these stacks, even though they're the
exact same structure. For reasons to do with the way <code class="display"><span class="extract">typedef</span></code> works in C,
it is awkward to typedef the two names together, so we'll simply use the
preprocessor:
</p>
<pre class="definitions">
2020-04-06 11:26:10 +00:00
<span class="definitionkeyword">define</span> <span class="constant">lifo_stack</span><span class="plain"> </span><span class="reserved">linked_list</span>
2019-02-04 22:26:45 +00:00
</pre>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. </b>Otherwise, it's macros all the way:
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="identifier">NEW_LIFO_STACK</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">)</span>
2020-04-06 11:26:10 +00:00
<span class="plain">(</span><span class="functiontext">LinkedLists::new</span><span class="plain">())</span>
2019-02-04 22:26:45 +00:00
<span class="definitionkeyword">define</span> <span class="identifier">PUSH_TO_LIFO_STACK</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">)</span>
2020-04-06 11:26:10 +00:00
<span class="functiontext">LinkedLists::add</span><span class="plain">((</span><span class="identifier">L</span><span class="plain">), (</span><span class="reserved">void</span><span class="plain"> *) (</span><span class="identifier">I</span><span class="plain">), </span><span class="constant">FALSE</span><span class="plain">)</span>
2019-02-04 22:26:45 +00:00
<span class="definitionkeyword">define</span> <span class="identifier">PULL_FROM_LIFO_STACK</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">)</span>
2020-04-06 11:26:10 +00:00
<span class="plain">((</span><span class="identifier">T</span><span class="plain"> *) </span><span class="functiontext">LinkedLists::remove_from_front</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">))</span>
2019-02-04 22:26:45 +00:00
<span class="definitionkeyword">define</span> <span class="identifier">POP_LIFO_STACK</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">)</span>
2020-04-06 11:26:10 +00:00
<span class="plain">(</span><span class="functiontext">LinkedLists::remove_from_front</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">))</span>
2019-02-04 22:26:45 +00:00
<span class="definitionkeyword">define</span> <span class="identifier">TOP_OF_LIFO_STACK</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">)</span>
<span class="identifier">FIRST_IN_LINKED_LIST</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">)</span>
<span class="definitionkeyword">define</span> <span class="identifier">LIFO_STACK_EMPTY</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">)</span>
2020-04-06 11:26:10 +00:00
<span class="plain">((</span><span class="functiontext">LinkedLists::len</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">) == </span><span class="constant">0</span><span class="plain">)?</span><span class="identifier">TRUE:FALSE</span><span class="plain">)</span>
2019-02-04 22:26:45 +00:00
<span class="definitionkeyword">define</span> <span class="identifier">LOOP_DOWN_LIFO_STACK</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">)</span>
<span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">)</span>
</pre>
2019-03-12 23:32:12 +00:00
<hr class="tocbar">
<ul class="toc"><li><a href="2-mth.html">Back to 'Methods'</a></li><li><a href="2-dct.html">Continue with 'Dictionaries'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
2019-02-04 22:26:45 +00:00
</body>
</html>