Add (/path):by_line()
This commit is contained in:
parent
3657257330
commit
d356309023
2
Makefile
2
Makefile
@ -30,7 +30,7 @@ CFLAGS_PLACEHOLDER="$$(echo -e '\033[2m<flags...>\033[m')"
|
||||
LDLIBS=-lgc -lcord -lm -lunistring -lgmp -ldl
|
||||
BUILTIN_OBJS=builtins/siphash.o builtins/array.o builtins/bool.o builtins/channel.o builtins/nums.o builtins/functions.o builtins/integers.o \
|
||||
builtins/pointer.o builtins/memory.o builtins/text.o builtins/thread.o builtins/c_string.o builtins/table.o \
|
||||
builtins/types.o builtins/util.o builtins/files.o builtins/range.o builtins/shell.o builtins/path.o
|
||||
builtins/types.o builtins/util.o builtins/files.o builtins/range.o builtins/shell.o builtins/path.o builtins/nextline.o
|
||||
TESTS=$(patsubst %.tm,%.tm.testresult,$(wildcard test/*.tm))
|
||||
|
||||
all: libtomo.so tomo
|
||||
|
108
builtins/nextline.c
Normal file
108
builtins/nextline.c
Normal file
@ -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
|
31
builtins/nextline.h
Normal file
31
builtins/nextline.h
Normal file
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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"
|
||||
|
@ -69,6 +69,16 @@ env_t *new_compilation_unit(CORD *libname)
|
||||
.next=new(arg_t, .name="step", .type=INT_TYPE, .default_val=FakeAST(Int, .str="1")))));
|
||||
}
|
||||
|
||||
type_t *next_line_type;
|
||||
{
|
||||
next_line_type = Type(
|
||||
EnumType, .name="NextLine", .env=namespace_env(env, "NextLine"),
|
||||
.tags=new(tag_t, .name="Done", .tag_value=0, .type=Type(StructType, .name="NextLine$Done"),
|
||||
.next=new(tag_t, .name="Next", .tag_value=1, .type=Type(StructType, .name="NextLine$Next",
|
||||
.env=namespace_env(env, "NextLine$Next"),
|
||||
.fields=new(arg_t, .name="line", .type=TEXT_TYPE)))));
|
||||
}
|
||||
|
||||
{
|
||||
env_t *thread_env = namespace_env(env, "Thread");
|
||||
THREAD_TYPE = Type(StructType, .name="Thread", .env=thread_env, .opaque=true);
|
||||
@ -245,12 +255,14 @@ env_t *new_compilation_unit(CORD *libname)
|
||||
{"reversed", "Range$reversed", "func(range:Range)->Range"},
|
||||
{"by", "Range$by", "func(range:Range, step:Int)->Range"},
|
||||
)},
|
||||
{"NextLine", next_line_type, "NextLine_t", "NextLine", {}},
|
||||
{"Pattern", Type(TextType, .lang="Pattern", .env=namespace_env(env, "Pattern")), "Pattern_t", "Pattern$info", TypedArray(ns_entry_t,
|
||||
{"escape_text", "Pattern$escape_text", "func(text:Text)->Pattern"},
|
||||
)},
|
||||
{"Path", Type(TextType, .lang="Path", .env=namespace_env(env, "Path")), "Text_t", "Text$info", TypedArray(ns_entry_t,
|
||||
{"append", "Path$append", "func(path:Path, text:Text, permissions=0o644_i32)"},
|
||||
{"base_name", "Path$base_name", "func(path:Path)->Text"},
|
||||
{"by_line", "Path$by_line", "func(path:Path)->func()->NextLine"},
|
||||
{"children", "Path$children", "func(path:Path, include_hidden=no)->[Path]"},
|
||||
{"create_directory", "Path$create_directory", "func(path:Path, permissions=0o644_i32)"},
|
||||
{"escape_path", "Path$escape_path", "func(path:Path)->Path"},
|
||||
|
Loading…
Reference in New Issue
Block a user