aboutsummaryrefslogtreecommitdiff
path: root/builtins
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-09-09 22:16:40 -0400
committerBruce Hill <bruce@bruce-hill.com>2024-09-09 22:16:40 -0400
commitd356309023fce996a549440aa14e3239f909fe33 (patch)
tree1c797f41be25c457a09b9187550136afd8550d96 /builtins
parent36572573300eaba9d0adbb63fc55067aa0fe5e0c (diff)
Add (/path):by_line()
Diffstat (limited to 'builtins')
-rw-r--r--builtins/nextline.c108
-rw-r--r--builtins/nextline.h31
-rw-r--r--builtins/path.c52
-rw-r--r--builtins/path.h1
-rw-r--r--builtins/siphash.h1
-rw-r--r--builtins/tomo.h1
6 files changed, 192 insertions, 2 deletions
diff --git a/builtins/nextline.c b/builtins/nextline.c
new file mode 100644
index 00000000..3fa37412
--- /dev/null
+++ b/builtins/nextline.c
@@ -0,0 +1,108 @@
+// An enum used for iterating over lines in a file
+// Most of the code here was generated by compiling:
+// enum NextLine(Done, Next(line:Text))
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "siphash.h"
+#include "datatypes.h"
+#include "nextline.h"
+#include "text.h"
+#include "util.h"
+
+static Text_t NextLine$Next$as_text(NextLine$Next_t *obj, bool use_color)
+{
+ if (!obj)
+ return Text("Next");
+ return Text$concat(use_color ? Text("\x1b[0;1mNext\x1b[m(") : Text("Next("), Text("line="),
+ Text$as_text((Text_t[1]){obj->$line}, use_color, &Text$info), Text(")"));
+}
+
+public inline NextLine_t NextLine$tagged$Next(Text_t $line)
+{
+ return (NextLine_t) {
+ .tag = NextLine$tag$Next,.$Next = { $line }
+ };
+}
+
+static Text_t NextLine$as_text(NextLine_t *obj, bool use_color)
+{
+ if (!obj)
+ return Text("NextLine");
+ switch (obj->tag) {
+ case NextLine$tag$Done:
+ return use_color ? Text("\x1b[36;1mNextLine.Done\x1b[m") : Text("NextLine.Done");
+ case NextLine$tag$Next:
+ return Text$concat(use_color ? Text("\x1b[36;1mNextLine.Next\x1b[m(") :
+ Text("NextLine.Next("), Text("line="),
+ Text$as_text((Text_t[1]){obj->$Next.$line}, use_color, &Text$info), Text(")"));
+ default:
+ return (Text_t) {
+ .length = 0};
+ }
+}
+
+static bool NextLine$equal(const NextLine_t *x, const NextLine_t *y,
+ const TypeInfo *info)
+{
+ (void) info;
+ if (x->tag != y->tag)
+ return false;
+ switch (x->tag) {
+ case NextLine$tag$Done:
+ return false;
+ case NextLine$tag$Next:
+ return generic_equal(&x->$Next, &y->$Next, (&NextLine$Next));
+ default:
+ return 0;
+ }
+}
+
+static int NextLine$compare(const NextLine_t *x, const NextLine_t *y,
+ const TypeInfo *info)
+{
+ (void) info;
+ int diff = (int)x->tag - (int)y->tag;
+ if (diff)
+ return diff;
+ switch (x->tag) {
+ case NextLine$tag$Done:
+ return 0;
+ case NextLine$tag$Next:
+ return generic_compare(&x->$Next, &y->$Next, (&NextLine$Next));
+ default:
+ return 0;
+ }
+}
+
+static uint64_t NextLine$hash(const NextLine_t *obj, const TypeInfo *info)
+{
+ (void) info;
+ uint64_t hashes[2] = { (uint64_t) obj->tag, 0 };
+ switch (obj->tag) {
+ case NextLine$tag$Done:
+ break;
+ case NextLine$tag$Next:
+ hashes[1] = generic_hash(&obj->$Next, (&NextLine$Next));
+ break;
+ default: break;
+ }
+ return siphash24((void *) &hashes, sizeof(hashes));
+}
+
+public const TypeInfo NextLine$Done = { 0, 0, {.tag = EmptyStruct,.EmptyStruct.name =
+ "NextLine$Done" } };
+public const TypeInfo NextLine$Next = { 24, 8, {.tag = CustomInfo,.CustomInfo =
+ {.as_text =
+ (void *) NextLine$Next$as_text,.hash =
+ (void *) Text$hash,.compare =
+ (void *) Text$compare,.equal =
+ (void *) Text$equal,} } };
+public const TypeInfo NextLine = { 32, 8, {.tag = CustomInfo,.CustomInfo =
+ {.as_text = (void *) NextLine$as_text,.equal =
+ (void *) NextLine$equal,.hash =
+ (void *) NextLine$hash,.compare =
+ (void *) NextLine$compare} } };
+
+// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/builtins/nextline.h b/builtins/nextline.h
new file mode 100644
index 00000000..ce4c9fab
--- /dev/null
+++ b/builtins/nextline.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include "datatypes.h"
+#include "types.h"
+
+// An enum used for iterating over lines in a file
+// Most of the code here was generated by compiling:
+// enum NextLine(Done, Next(line:Text))
+
+typedef struct NextLine_s NextLine_t;
+typedef struct NextLine$Done_s NextLine$Done_t;
+#pragma GCC diagnostic ignored "-Wpedantic"
+struct NextLine$Done_s {
+};
+typedef struct NextLine$Next_s NextLine$Next_t;
+struct NextLine$Next_s {
+ Text_t $line;
+};
+struct NextLine_s {
+ enum { NextLine$tag$Done = 0, NextLine$tag$Next = 1 } tag;
+ union {
+ NextLine$Done_t $Done;
+ NextLine$Next_t $Next;
+ };
+};
+extern const TypeInfo NextLine;
+extern const TypeInfo NextLine$Done;
+extern const TypeInfo NextLine$Next;
+NextLine_t NextLine$tagged$Next(Text_t $line);
+
+// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/builtins/path.c b/builtins/path.c
index 7c2198cf..096cbdd0 100644
--- a/builtins/path.c
+++ b/builtins/path.c
@@ -1,10 +1,11 @@
// A lang for filesystem paths
#include <dirent.h>
-#include <fcntl.h>
#include <errno.h>
-#include <string.h>
+#include <fcntl.h>
+#include <gc.h>
#include <stdbool.h>
#include <stdint.h>
+#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -15,6 +16,7 @@
#include "files.h"
#include "functions.h"
#include "integers.h"
+#include "nextline.h"
#include "path.h"
#include "text.h"
#include "types.h"
@@ -423,6 +425,51 @@ public Text_t Path$extension(Path_t path, bool full)
return Text("");
}
+static void _line_reader_cleanup(FILE **f)
+{
+ if (f && *f) {
+ fclose(*f);
+ *f = NULL;
+ }
+}
+
+static NextLine_t _next_line(FILE **f)
+{
+ if (!f || !*f) return (NextLine_t){NextLine$tag$Done};
+
+ char *line = NULL;
+ size_t size = 0;
+ ssize_t len = getline(&line, &size, *f);
+ if (len <= 0) {
+ _line_reader_cleanup(f);
+ return (NextLine_t){NextLine$tag$Done};
+ }
+
+ while (len > 0 && (line[len-1] == '\r' || line[len-1] == '\n'))
+ --len;
+
+ if (u8_check((uint8_t*)line, (size_t)len) != NULL)
+ fail("Invalid UTF8!");
+
+ Text_t line_text = Text$format("%.*s", len, line);
+ free(line);
+ return NextLine$tagged$Next(line_text);
+}
+
+public closure_t Path$by_line(Path_t path)
+{
+ path = Path$_expand_home(path);
+
+ FILE *f = fopen(Text$as_c_string(path), "r");
+ if (f == NULL)
+ fail("Could not read file: %k (%s)", &path, strerror(errno));
+
+ FILE **wrapper = GC_MALLOC(sizeof(FILE*));
+ *wrapper = f;
+ GC_register_finalizer(wrapper, (void*)_line_reader_cleanup, NULL, NULL, NULL);
+ return (closure_t){.fn=(void*)_next_line, .userdata=wrapper};
+}
+
public const TypeInfo Path$info = {
.size=sizeof(Path_t),
.align=__alignof__(Path_t),
@@ -430,4 +477,5 @@ public const TypeInfo Path$info = {
.TextInfo={.lang="Path"},
};
+
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/builtins/path.h b/builtins/path.h
index 6772f72d..dd42af85 100644
--- a/builtins/path.h
+++ b/builtins/path.h
@@ -39,6 +39,7 @@ Text_t Path$write_unique(Path_t path, Text_t text);
Path_t Path$parent(Path_t path);
Text_t Path$base_name(Path_t path);
Text_t Path$extension(Path_t path, bool full);
+closure_t Path$by_line(Path_t path);
#define Path$hash Text$hash
#define Path$compare Text$compare
diff --git a/builtins/siphash.h b/builtins/siphash.h
index a466200c..0fc7614c 100644
--- a/builtins/siphash.h
+++ b/builtins/siphash.h
@@ -3,6 +3,7 @@
// An implementation of the SipHash algorithm.
#include <stdint.h>
+#include <stddef.h>
uint64_t siphash24(const uint8_t *src, size_t src_sz);
diff --git a/builtins/tomo.h b/builtins/tomo.h
index c7814376..29f71f71 100644
--- a/builtins/tomo.h
+++ b/builtins/tomo.h
@@ -17,6 +17,7 @@
#include "datatypes.h"
#include "functions.h"
#include "integers.h"
+#include "nextline.h"
#include "macros.h"
#include "memory.h"
#include "nums.h"