summaryrefslogtreecommitdiff
path: root/doc/weave.html
blob: 9e851baede0994d0a5a2254fdd9e91691b67da02 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
* {box-sizing: border-box;}
html {
--fs-sans: Helvetica, "Helvetica Neue", Arial, "San Francisco", sans;
--fs-mono: jetbrains-mono-regular, Consolas, Menlo, monospace;
font-size: 16px;
}
body {background-color: #111; color: #ddd; margin: 2rem calc(50% - 32rem); font-family: var(--fs-sans); font-size: 1rem; font-style: normal;}
body * {line-height: 1.5; text-align: justify; text-justify: inter-word;}
h1,h2 {font-family: var(--fs-sans); margin: 2rem 0 1rem; font-weight: bold; line-height: 1;}
h1 {font-size: 3rem;}
h2 {font-size: 2rem;}
h3 {margin: 1rem; font-size: 1rem; font-weight: normal; font-style: italic;}
code,code * {font-family: var(--fs-mono); hyphens: none; line-height: 1.25rem;}
body>pre {background-color: #000; margin: 1rem; padding: 1rem; white-space: pre-wrap; border-radius: 0.25rem;}
ul,ol {margin: 1rem 0; padding: 0 0 0 2rem;}
ul ul,ol ol {margin: 0;}
.ref {font-family: var(--fs-sans); font-style: italic;}
@media screen and (max-width: 68rem) {body {margin: 2rem calc(50% - 24rem);}}
@media screen and (max-width: 52rem) {body {margin: 2rem calc(50% - 16rem);}}
@media screen and (max-width: 36rem) {body {margin: 2rem; hyphens: auto;} h3,body>pre {margin: 1rem 0;}}
</style>
</head>

<body>
<h1>weave.lp</h1>
<p>The structure of this file is quite similar to that of <code>tangle.zig</code>, only differing in terms of which functions are used to transform the input data.</p>

<h3 id="section">*:</h3>

<pre><code><span class="ref" >(License)</span>

<span class="ref" >(Imports)</span>

pub fn main() !u8 {
    <span class="ref" >(IO initialization)</span>

    <span class="ref" >(Allocator initialization)</span>

    <span class="ref" >(Read file from stdin)</span>

    <span class="ref" >(Split into lines)</span>

    <span class="ref" >(Generate text)</span>

    <span class="ref" >(Write to stdout)</span>

    return 0;
}
</code></pre>

<h3 id="license">License:</h3>

<pre><code>&#47;&#47; Copyright 2022 DistressNetwork° &#60;uplink@distress.network&#62;
&#47;&#47; This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https:&#47;&#47;mozilla.org&#47;MPL&#47;2.0&#47;.
</code></pre>

<p>First we import the other files containing the core functions.</p>

<h3 id="imports">Imports:</h3>

<pre><code>const std = @import("std");
const data = @import("data.zig");
const log = @import("log.zig").log;

const Allocator = std.mem.Allocator;
</code></pre>

<p>Within the main procedure, we first initialize the stdin and stdout interfaces.</p>

<h3 id="io-initialization">IO initialization:</h3>

<pre><code>const stdin = std.io.getStdIn();
const stdout = std.io.getStdOut();
</code></pre>

<p>We then initialize the allocator, deferring its deinitialization to the end of the process. Since the overall memory usage pattern is one in which all resources may be freed at once, the arena allocator is the most appropriate choice for this program.</p>

<h3 id="allocator-initialization">Allocator initialization:</h3>

<pre><code>var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
var alloc = arena.allocator();
defer arena.deinit();
</code></pre>

<p>The input file is then read from stdin. In the case of input exceeding the maximum permitted file size, the program may report the error and exit normally. All other errors which may be returned are memory allocation failures and should thus yield control to the panic handler.</p>

<h3 id="read-file-from-stdin">Read file from stdin:</h3>

<pre><code>const input = stdin.reader().readAllAlloc(alloc, data.input_max) catch |err| switch (err) {
    error.StreamTooLong =&#62; {
        log(.err, "input too large (maximum {})", .{std.fmt.fmtIntSizeBin(data.input_max)});
        return 1;
    },
    else =&#62; |e| return e,
};
</code></pre>

<p>We then pass the input into the line splitting function, creating an array of strings.</p>

<h3 id="split-into-lines">Split into lines:</h3>

<pre><code>const lines = try data.split_lines(input, alloc);
</code></pre>

<p>The text file is then generated. This entails searching for the configuration declarations, which may fail and thus return an error. Logging such errors is handled by the function itself, and thus the errors are handled here solely by exiting.</p>

<h3 id="generate-text">Generate text:</h3>

<pre><code>const text = data.textgen(lines, alloc) catch |err| switch (err) {
    error.NotFound =&#62; {
        return 1;
    },
    else =&#62; |e| return e,
};
</code></pre>

<p>Finally, the lines of the text file are written to stdout, separated by newlines.</p>

<h3 id="write-to-stdout">Write to stdout:</h3>

<pre><code>for (text) |line| {
    try stdout.writer().print("{s}\n", .{line});
}
</code></pre>
</body>
</html>