Scanning directories in alphabetical order

This commit is contained in:
Graham Nelson 2022-04-19 22:06:18 +01:00
parent 7d1fcb2260
commit 3adb9a7dfa
8 changed files with 154 additions and 13 deletions

View file

@ -1,6 +1,6 @@
# Inweb 7
v7-alpha.1+1A89 'Escape to Danger' (15 April 2022)
v7-alpha.1+1A90 'Escape to Danger' (19 April 2022)
## About Inweb

View file

@ -3138,6 +3138,10 @@ scan_directory * Directories__open(pathname *P) ;
int Directories__next(scan_directory *D, text_stream *leafname) ;
#line 42 "inweb/foundation-module/Chapter 3/Directories.w"
void Directories__close(scan_directory *D) ;
#line 58 "inweb/foundation-module/Chapter 3/Directories.w"
linked_list * Directories__listing(pathname *P) ;
#line 86 "inweb/foundation-module/Chapter 3/Directories.w"
int Directories__compare_names(const void *ent1, const void *ent2) ;
#line 13 "inweb/foundation-module/Chapter 3/Time.w"
void Time__begin(void) ;
#line 26 "inweb/foundation-module/Chapter 3/Time.w"
@ -8621,11 +8625,11 @@ int CommandLine__read_pair_p(text_stream *opt, text_stream *opt_val, int N,
; innocuous = TRUE; break;
case VERSION_CLSW: {
PRINT("inweb");
char *svn = "7-alpha.1+1A88";
char *svn = "7-alpha.1+1A89";
if (svn[0]) PRINT(" version %s", svn);
char *vname = "Escape to Danger";
if (vname[0]) PRINT(" '%s'", vname);
char *d = "13 April 2022";
char *d = "15 April 2022";
if (d[0]) PRINT(" (%s)", d);
PRINT("\n");
innocuous = TRUE; break;
@ -9856,6 +9860,41 @@ void Directories__close(scan_directory *D) {
Platform__closedir(D->directory_handle);
}
#line 58 "inweb/foundation-module/Chapter 3/Directories.w"
linked_list *Directories__listing(pathname *P) {
int capacity = 4, used = 0;
text_stream **listing_array = (text_stream **)
(Memory__calloc(capacity, sizeof(text_stream *), ARRAY_SORTING_MREASON));
scan_directory *D = Directories__open(P);
if (D) {
text_stream *entry = Str__new();
while (Directories__next(D, entry)) {
if (used == capacity) {
int new_capacity = 4*capacity;
text_stream **new_listing_array = (text_stream **)
(Memory__calloc(new_capacity, sizeof(text_stream *), ARRAY_SORTING_MREASON));
for (int i=0; i<used; i++) new_listing_array[i] = listing_array[i];
listing_array = new_listing_array;
capacity = new_capacity;
}
listing_array[used++] = entry;
entry = Str__new();
}
Directories__close(D);
}
qsort(listing_array, (size_t) used, sizeof(text_stream *), Directories__compare_names);
linked_list *L = NEW_LINKED_LIST(text_stream);
for (int i=0; i<used; i++) ADD_TO_LINKED_LIST(listing_array[i], text_stream, L);
Memory__I7_free(listing_array, ARRAY_SORTING_MREASON, capacity*((int) sizeof(text_stream *)));
return L;
}
int Directories__compare_names(const void *ent1, const void *ent2) {
text_stream *tx1 = *((text_stream **) ent1);
text_stream *tx2 = *((text_stream **) ent2);
return Str__cmp_insensitive(tx1, tx2);
}
#line 9 "inweb/foundation-module/Chapter 3/Time.w"
time_t right_now;
struct tm *the_present = NULL;
@ -30963,7 +31002,7 @@ void Ctags__write(web *W, filename *F) {
WRITE("!_TAG_FILE_SORTED\t0\t/0=unsorted, 1=sorted, 2=foldcase/\n");
WRITE("!_TAG_PROGRAM_AUTHOR\tGraham Nelson\t/graham.nelson@mod-langs.ox.ac.uk/\n");
WRITE("!_TAG_PROGRAM_NAME\tinweb\t//\n");
WRITE("!_TAG_PROGRAM_VERSION\t7-alpha.1+1A88\t/built 13 April 2022/\n");
WRITE("!_TAG_PROGRAM_VERSION\t7-alpha.1+1A89\t/built 15 April 2022/\n");
}
#line 47 "inweb/Chapter 6/Ctags Support.w"

View file

@ -1,3 +1,3 @@
Prerelease: alpha.1
Build Date: 15 April 2022
Build Number: 1A89
Build Date: 19 April 2022
Build Number: 1A90

View file

@ -622,7 +622,7 @@ values of these functions are always non-<span class="extract"><span class="extr
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> *</span><span class="function-syntax">Memory::calloc</span><button class="popup" onclick="togglePopup('usagePopup9')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup9">Usage of <span class="code-font"><span class="function-syntax">Memory::calloc</span></span>:<br/>Streams - <a href="2-str.html#SP26">&#167;26</a><br/>Dictionaries - <a href="2-dct.html#SP2">&#167;2</a><br/>Command Line Arguments - <a href="3-cla.html#SP14">&#167;14</a><br/>Time - <a href="3-tm.html#SP7_1">&#167;7.1</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">how_many</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">size_in_bytes</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">reason</span><span class="plain-syntax">) {</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> *</span><span class="function-syntax">Memory::calloc</span><button class="popup" onclick="togglePopup('usagePopup9')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup9">Usage of <span class="code-font"><span class="function-syntax">Memory::calloc</span></span>:<br/>Streams - <a href="2-str.html#SP26">&#167;26</a><br/>Dictionaries - <a href="2-dct.html#SP2">&#167;2</a><br/>Command Line Arguments - <a href="3-cla.html#SP14">&#167;14</a><br/>Directories - <a href="3-drc.html#SP3">&#167;3</a><br/>Time - <a href="3-tm.html#SP7_1">&#167;7.1</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">how_many</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">size_in_bytes</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">reason</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><a href="2-mmr.html#SP25" class="function-link"><span class="function-syntax">Memory::alloc_inner</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">how_many</span><span class="plain-syntax">, </span><span class="identifier-syntax">size_in_bytes</span><span class="plain-syntax">, </span><span class="identifier-syntax">reason</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> *</span><span class="function-syntax">Memory::malloc</span><button class="popup" onclick="togglePopup('usagePopup10')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup10">Usage of <span class="code-font"><span class="function-syntax">Memory::malloc</span></span>:<br/>Streams - <a href="2-str.html#SP35_3">&#167;35.3</a><br/>C Strings - <a href="4-cst.html#SP11">&#167;11</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">size_in_bytes</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">reason</span><span class="plain-syntax">) {</span>
@ -699,7 +699,7 @@ rarely and to allocate large blocks of memory.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Memory::I7_free</span><button class="popup" onclick="togglePopup('usagePopup12')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup12">Usage of <span class="code-font"><span class="function-syntax">Memory::I7_free</span></span>:<br/>Streams - <a href="2-str.html#SP34_2">&#167;34.2</a><br/>Dictionaries - <a href="2-dct.html#SP7_2">&#167;7.2</a>, <a href="2-dct.html#SP11">&#167;11</a><br/>Command Line Arguments - <a href="3-cla.html#SP14">&#167;14</a><br/>C Strings - <a href="4-cst.html#SP12">&#167;12</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pointer</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">R</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">bytes_freed</span><span class="plain-syntax">) {</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Memory::I7_free</span><button class="popup" onclick="togglePopup('usagePopup12')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup12">Usage of <span class="code-font"><span class="function-syntax">Memory::I7_free</span></span>:<br/>Streams - <a href="2-str.html#SP34_2">&#167;34.2</a><br/>Dictionaries - <a href="2-dct.html#SP7_2">&#167;7.2</a>, <a href="2-dct.html#SP11">&#167;11</a><br/>Command Line Arguments - <a href="3-cla.html#SP14">&#167;14</a><br/>Directories - <a href="3-drc.html#SP3">&#167;3</a><br/>C Strings - <a href="4-cst.html#SP12">&#167;12</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pointer</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">R</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">bytes_freed</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">R</span><span class="plain-syntax"> &lt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">R</span><span class="plain-syntax"> &gt;= </span><span class="identifier-syntax">NO_DEFINED_MREASON_VALUES</span><span class="plain-syntax">)) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"no such memory reason"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pointer</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"can't free NULL memory"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOCK_MUTEX</span><span class="plain-syntax">(</span><span class="identifier-syntax">memory_statistics_mutex</span><span class="plain-syntax">);</span>

View file

@ -12,6 +12,14 @@
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
<script>
function togglePopup(material_id) {
var popup = document.getElementById(material_id);
popup.classList.toggle("show");
}
</script>
<link href="../docs-assets/Popups.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
@ -59,7 +67,7 @@ transcoded the other way.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">scan_directory</span><span class="plain-syntax"> *</span><span class="function-syntax">Directories::open</span><span class="plain-syntax">(</span><span class="reserved-syntax">pathname</span><span class="plain-syntax"> *</span><span class="identifier-syntax">P</span><span class="plain-syntax">) {</span>
<span class="reserved-syntax">scan_directory</span><span class="plain-syntax"> *</span><span class="function-syntax">Directories::open</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">Directories::open</span></span>:<br/><a href="3-drc.html#SP3">&#167;3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">pathname</span><span class="plain-syntax"> *</span><span class="identifier-syntax">P</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">scan_directory</span><span class="plain-syntax"> *</span><span class="identifier-syntax">D</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CREATE</span><span class="plain-syntax">(</span><span class="reserved-syntax">scan_directory</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">TEMPORARY_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="string-syntax">"%p"</span><span class="plain-syntax">, </span><span class="identifier-syntax">P</span><span class="plain-syntax">);</span>
@ -70,7 +78,7 @@ transcoded the other way.
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">D</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Directories::next</span><span class="plain-syntax">(</span><span class="reserved-syntax">scan_directory</span><span class="plain-syntax"> *</span><span class="identifier-syntax">D</span><span class="plain-syntax">, </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">leafname</span><span class="plain-syntax">) {</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Directories::next</span><button class="popup" onclick="togglePopup('usagePopup2')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup2">Usage of <span class="code-font"><span class="function-syntax">Directories::next</span></span>:<br/><a href="3-drc.html#SP3">&#167;3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">scan_directory</span><span class="plain-syntax"> *</span><span class="identifier-syntax">D</span><span class="plain-syntax">, </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">leafname</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">char</span><span class="plain-syntax"> </span><span class="identifier-syntax">leafname_Cs</span><span class="plain-syntax">[</span><span class="constant-syntax">MAX_FILENAME_LENGTH</span><span class="plain-syntax">];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">rv</span><span class="plain-syntax"> = </span><span class="constant-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">rv</span><span class="plain-syntax">) {</span>
@ -82,10 +90,58 @@ transcoded the other way.
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">rv</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Directories::close</span><span class="plain-syntax">(</span><span class="reserved-syntax">scan_directory</span><span class="plain-syntax"> *</span><span class="identifier-syntax">D</span><span class="plain-syntax">) {</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Directories::close</span><button class="popup" onclick="togglePopup('usagePopup3')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup3">Usage of <span class="code-font"><span class="function-syntax">Directories::close</span></span>:<br/><a href="3-drc.html#SP3">&#167;3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">scan_directory</span><span class="plain-syntax"> *</span><span class="identifier-syntax">D</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><a href="1-wp.html#SP9" class="function-link"><span class="function-syntax">Platform::closedir</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">D</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">directory_handle</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP3" class="paragraph-anchor"></a><b>&#167;3. </b>It turns out to be useful to scan the contents of a directory in an order
which is predictable regardless of platform &mdash; <span class="extract"><span class="extract-syntax">Platform::readdir</span></span> works in a
different order on MacOS, Windows and Linux, even given the same directory
of files to work on. So the following returns a linked list of the contents,
sorted into alphabetical order, but case-insensitively. For the Inform project,
at least, we don't anticipate ever dealing with files whose names disagree only
in casing, so this ordering is effectively deterministic.
</p>
<p class="commentary">There's some time and memory overhead here, but unless we're dealing with
directories holding upwards of 10,000 files or so, it'll be trivial.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">linked_list</span><span class="plain-syntax"> *</span><span class="function-syntax">Directories::listing</span><span class="plain-syntax">(</span><span class="reserved-syntax">pathname</span><span class="plain-syntax"> *</span><span class="identifier-syntax">P</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">capacity</span><span class="plain-syntax"> = </span><span class="constant-syntax">4</span><span class="plain-syntax">, </span><span class="identifier-syntax">used</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> **</span><span class="identifier-syntax">listing_array</span><span class="plain-syntax"> = (</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> **)</span>
<span class="plain-syntax"> (</span><a href="2-mmr.html#SP24" class="function-link"><span class="function-syntax">Memory::calloc</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">capacity</span><span class="plain-syntax">, </span><span class="reserved-syntax">sizeof</span><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *), </span><span class="constant-syntax">ARRAY_SORTING_MREASON</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">scan_directory</span><span class="plain-syntax"> *</span><span class="identifier-syntax">D</span><span class="plain-syntax"> = </span><a href="3-drc.html#SP2" class="function-link"><span class="function-syntax">Directories::open</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">D</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">entry</span><span class="plain-syntax"> = </span><a href="4-sm.html#SP2" class="function-link"><span class="function-syntax">Str::new</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><a href="3-drc.html#SP2" class="function-link"><span class="function-syntax">Directories::next</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">D</span><span class="plain-syntax">, </span><span class="identifier-syntax">entry</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">used</span><span class="plain-syntax"> == </span><span class="identifier-syntax">capacity</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">new_capacity</span><span class="plain-syntax"> = </span><span class="constant-syntax">4</span><span class="plain-syntax">*</span><span class="identifier-syntax">capacity</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> **</span><span class="identifier-syntax">new_listing_array</span><span class="plain-syntax"> = (</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> **)</span>
<span class="plain-syntax"> (</span><a href="2-mmr.html#SP24" class="function-link"><span class="function-syntax">Memory::calloc</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">new_capacity</span><span class="plain-syntax">, </span><span class="reserved-syntax">sizeof</span><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *), </span><span class="constant-syntax">ARRAY_SORTING_MREASON</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">i</span><span class="plain-syntax">&lt;</span><span class="identifier-syntax">used</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++) </span><span class="identifier-syntax">new_listing_array</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">] = </span><span class="identifier-syntax">listing_array</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">];</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">listing_array</span><span class="plain-syntax"> = </span><span class="identifier-syntax">new_listing_array</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">capacity</span><span class="plain-syntax"> = </span><span class="identifier-syntax">new_capacity</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">listing_array</span><span class="plain-syntax">[</span><span class="identifier-syntax">used</span><span class="plain-syntax">++] = </span><span class="identifier-syntax">entry</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">entry</span><span class="plain-syntax"> = </span><a href="4-sm.html#SP2" class="function-link"><span class="function-syntax">Str::new</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><a href="3-drc.html#SP2" class="function-link"><span class="function-syntax">Directories::close</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">D</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">qsort</span><span class="plain-syntax">(</span><span class="identifier-syntax">listing_array</span><span class="plain-syntax">, (</span><span class="identifier-syntax">size_t</span><span class="plain-syntax">) </span><span class="identifier-syntax">used</span><span class="plain-syntax">, </span><span class="reserved-syntax">sizeof</span><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *), </span><a href="3-drc.html#SP3" class="function-link"><span class="function-syntax">Directories::compare_names</span></a><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">linked_list</span><span class="plain-syntax"> *</span><span class="identifier-syntax">L</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NEW_LINKED_LIST</span><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">i</span><span class="plain-syntax">&lt;</span><span class="identifier-syntax">used</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++) </span><span class="identifier-syntax">ADD_TO_LINKED_LIST</span><span class="plain-syntax">(</span><span class="identifier-syntax">listing_array</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">], </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax">, </span><span class="identifier-syntax">L</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="2-mmr.html#SP26" class="function-link"><span class="function-syntax">Memory::I7_free</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">listing_array</span><span class="plain-syntax">, </span><span class="constant-syntax">ARRAY_SORTING_MREASON</span><span class="plain-syntax">, </span><span class="identifier-syntax">capacity</span><span class="plain-syntax">*((</span><span class="reserved-syntax">int</span><span class="plain-syntax">) </span><span class="reserved-syntax">sizeof</span><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *)));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">L</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Directories::compare_names</span><span class="plain-syntax">(</span><span class="reserved-syntax">const</span><span class="plain-syntax"> </span><span class="reserved-syntax">void</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ent1</span><span class="plain-syntax">, </span><span class="reserved-syntax">const</span><span class="plain-syntax"> </span><span class="reserved-syntax">void</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ent2</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tx1</span><span class="plain-syntax"> = *((</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> **) </span><span class="identifier-syntax">ent1</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tx2</span><span class="plain-syntax"> = *((</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> **) </span><span class="identifier-syntax">ent2</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><a href="4-sm.html#SP20" class="function-link"><span class="function-syntax">Str::cmp_insensitive</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">tx1</span><span class="plain-syntax">, </span><span class="identifier-syntax">tx2</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<nav role="progress"><div class="progresscontainer">
<ul class="progressbar"><li class="progressprev"><a href="3-shl.html">&#10094;</a></li><li class="progresschapter"><a href="P-abgtf.html">P</a></li><li class="progresschapter"><a href="1-fm.html">1</a></li><li class="progresschapter"><a href="2-dl.html">2</a></li><li class="progresscurrentchapter">3</li><li class="progresssection"><a href="3-em.html">em</a></li><li class="progresssection"><a href="3-cla.html">cla</a></li><li class="progresssection"><a href="3-pth.html">pth</a></li><li class="progresssection"><a href="3-fln.html">fln</a></li><li class="progresssection"><a href="3-cf.html">cf</a></li><li class="progresssection"><a href="3-shl.html">shl</a></li><li class="progresscurrent">drc</li><li class="progresssection"><a href="3-tm.html">tm</a></li><li class="progresschapter"><a href="4-chr.html">4</a></li><li class="progresschapter"><a href="5-htm.html">5</a></li><li class="progresschapter"><a href="6-bf.html">6</a></li><li class="progresschapter"><a href="7-vn.html">7</a></li><li class="progresschapter"><a href="8-ws.html">8</a></li><li class="progressnext"><a href="3-tm.html">&#10095;</a></li></ul></div>
</nav><!--End of weave-->

View file

@ -88,7 +88,7 @@ access.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="function-syntax">Str::new</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">Str::new</span></span>:<br/><a href="4-sm.html#SP3">&#167;3</a><br/>Debugging Log - <a href="2-dl.html#SP4_1">&#167;4.1</a><br/>Dictionaries - <a href="2-dct.html#SP7_3_1">&#167;7.3.1</a><br/>Command Line Arguments - <a href="3-cla.html#SP6">&#167;6</a>, <a href="3-cla.html#SP11">&#167;11</a><br/>HTML - <a href="5-htm.html#SP27_2">&#167;27.2</a><br/>Epub Ebooks - <a href="5-ee.html#SP5">&#167;5</a><br/>Version Numbers - <a href="7-vn.html#SP7">&#167;7</a><br/>Web Structure - <a href="8-ws.html#SP5_2">&#167;5.2</a>, <a href="8-ws.html#SP6_1">&#167;6.1</a>, <a href="8-ws.html#SP7_2_1">&#167;7.2.1</a>, <a href="8-ws.html#SP7_2_2_1">&#167;7.2.2.1</a><br/>Build Files - <a href="8-bf.html#SP3">&#167;3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="function-syntax">Str::new</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">Str::new</span></span>:<br/><a href="4-sm.html#SP3">&#167;3</a><br/>Debugging Log - <a href="2-dl.html#SP4_1">&#167;4.1</a><br/>Dictionaries - <a href="2-dct.html#SP7_3_1">&#167;7.3.1</a><br/>Command Line Arguments - <a href="3-cla.html#SP6">&#167;6</a>, <a href="3-cla.html#SP11">&#167;11</a><br/>Directories - <a href="3-drc.html#SP3">&#167;3</a><br/>HTML - <a href="5-htm.html#SP27_2">&#167;27.2</a><br/>Epub Ebooks - <a href="5-ee.html#SP5">&#167;5</a><br/>Version Numbers - <a href="7-vn.html#SP7">&#167;7</a><br/>Web Structure - <a href="8-ws.html#SP5_2">&#167;5.2</a>, <a href="8-ws.html#SP6_1">&#167;6.1</a>, <a href="8-ws.html#SP7_2_1">&#167;7.2.1</a>, <a href="8-ws.html#SP7_2_2_1">&#167;7.2.2.1</a><br/>Build Files - <a href="8-bf.html#SP3">&#167;3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><a href="4-sm.html#SP2" class="function-link"><span class="function-syntax">Str::new_with_capacity</span></a><span class="plain-syntax">(32);</span>
<span class="plain-syntax">}</span>
@ -462,7 +462,7 @@ around 1%.
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">L1</span><span class="plain-syntax"> - </span><span class="identifier-syntax">L2</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Str::cmp_insensitive</span><button class="popup" onclick="togglePopup('usagePopup29')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup29">Usage of <span class="code-font"><span class="function-syntax">Str::cmp_insensitive</span></span>:<br/><a href="4-sm.html#SP19">&#167;19</a><br/>Command Line Arguments - <a href="3-cla.html#SP15">&#167;15</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">S1</span><span class="plain-syntax">, </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">S2</span><span class="plain-syntax">) {</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Str::cmp_insensitive</span><button class="popup" onclick="togglePopup('usagePopup29')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup29">Usage of <span class="code-font"><span class="function-syntax">Str::cmp_insensitive</span></span>:<br/><a href="4-sm.html#SP19">&#167;19</a><br/>Command Line Arguments - <a href="3-cla.html#SP15">&#167;15</a><br/>Directories - <a href="3-drc.html#SP3">&#167;3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">S1</span><span class="plain-syntax">, </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">S2</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">string_position</span><span class="plain-syntax"> </span><span class="identifier-syntax">P</span><span class="plain-syntax"> = </span><a href="4-sm.html#SP10" class="function-link"><span class="function-syntax">Str::start</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">S1</span><span class="plain-syntax">), </span><span class="identifier-syntax">Q</span><span class="plain-syntax"> = </span><a href="4-sm.html#SP10" class="function-link"><span class="function-syntax">Str::start</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">S2</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> (</span><span class="identifier-syntax">P</span><span class="plain-syntax">.</span><span class="identifier-syntax">index</span><span class="plain-syntax"> &lt; </span><a href="4-sm.html#SP8" class="function-link"><span class="function-syntax">Str::len</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">S1</span><span class="plain-syntax">)) &amp;&amp; (</span><span class="identifier-syntax">Q</span><span class="plain-syntax">.</span><span class="element-syntax">index</span><span class="plain-syntax"> &lt; </span><a href="4-sm.html#SP8" class="function-link"><span class="function-syntax">Str::len</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">S2</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">P</span><span class="plain-syntax"> = </span><a href="4-sm.html#SP11" class="function-link"><span class="function-syntax">Str::forward</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">), </span><span class="identifier-syntax">Q</span><span class="plain-syntax"> = </span><a href="4-sm.html#SP11" class="function-link"><span class="function-syntax">Str::forward</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">Q</span><span class="plain-syntax">)) {</span>

Binary file not shown.

View file

@ -42,3 +42,49 @@ int Directories::next(scan_directory *D, text_stream *leafname) {
void Directories::close(scan_directory *D) {
Platform::closedir(D->directory_handle);
}
@ It turns out to be useful to scan the contents of a directory in an order
which is predictable regardless of platform -- |Platform::readdir| works in a
different order on MacOS, Windows and Linux, even given the same directory
of files to work on. So the following returns a linked list of the contents,
sorted into alphabetical order, but case-insensitively. For the Inform project,
at least, we don't anticipate ever dealing with files whose names disagree only
in casing, so this ordering is effectively deterministic.
There's some time and memory overhead here, but unless we're dealing with
directories holding upwards of 10,000 files or so, it'll be trivial.
=
linked_list *Directories::listing(pathname *P) {
int capacity = 4, used = 0;
text_stream **listing_array = (text_stream **)
(Memory::calloc(capacity, sizeof(text_stream *), ARRAY_SORTING_MREASON));
scan_directory *D = Directories::open(P);
if (D) {
text_stream *entry = Str::new();
while (Directories::next(D, entry)) {
if (used == capacity) {
int new_capacity = 4*capacity;
text_stream **new_listing_array = (text_stream **)
(Memory::calloc(new_capacity, sizeof(text_stream *), ARRAY_SORTING_MREASON));
for (int i=0; i<used; i++) new_listing_array[i] = listing_array[i];
listing_array = new_listing_array;
capacity = new_capacity;
}
listing_array[used++] = entry;
entry = Str::new();
}
Directories::close(D);
}
qsort(listing_array, (size_t) used, sizeof(text_stream *), Directories::compare_names);
linked_list *L = NEW_LINKED_LIST(text_stream);
for (int i=0; i<used; i++) ADD_TO_LINKED_LIST(listing_array[i], text_stream, L);
Memory::I7_free(listing_array, ARRAY_SORTING_MREASON, capacity*((int) sizeof(text_stream *)));
return L;
}
int Directories::compare_names(const void *ent1, const void *ent2) {
text_stream *tx1 = *((text_stream **) ent1);
text_stream *tx2 = *((text_stream **) ent2);
return Str::cmp_insensitive(tx1, tx2);
}