feat: kprintf now goes into dedicated pseudo-dev rather than flooding the framebuffer
[lunaix-os.git] / lunaix-os / kernel / fs / twimap.c
1 #include <lunaix/fs.h>
2 #include <lunaix/fs/twimap.h>
3 #include <lunaix/mm/valloc.h>
4 #include <lunaix/spike.h>
5
6 #include <klibc/strfmt.h>
7 #include <klibc/string.h>
8
9 #define TWIMAP_BUFFER_SIZE 4096
10
11 void
12 __twimap_default_reset(struct twimap* map)
13 {
14     map->index = NULL;
15 }
16
17 int
18 __twimap_default_gonext(struct twimap* map)
19 {
20     return 0;
21 }
22
23 int
24 __twimap_file_read(struct v_inode* inode, void* buf, size_t len, size_t fpos)
25 {
26     struct twimap* map = (struct twimap*)(inode->data);
27     return twimap_read(map, buf, len, fpos);
28 }
29
30 int
31 twimap_read(struct twimap* map, void* buffer, size_t len, size_t fpos)
32 {
33     map->buffer = valloc(TWIMAP_BUFFER_SIZE);
34     map->reset(map);
35
36     // FIXME what if TWIMAP_BUFFER_SIZE is not big enough?
37
38     size_t pos = 0;
39     do {
40         map->size_acc = 0;
41         map->read(map);
42         pos += map->size_acc;
43     } while (pos <= fpos && map->go_next(map));
44
45     if (pos <= fpos) {
46         vfree(map->buffer);
47         return 0;
48     }
49
50     if (!fpos) {
51         pos = 0;
52     }
53
54     size_t acc_size = MIN(len, map->size_acc - (pos - fpos)), rdlen = acc_size;
55     memcpy(buffer, map->buffer + (pos - fpos), acc_size);
56
57     while (acc_size < len && map->go_next(map)) {
58         map->size_acc = 0;
59         map->read(map);
60         rdlen = MIN(len - acc_size, map->size_acc);
61         memcpy(buffer + acc_size, map->buffer, rdlen);
62         acc_size += rdlen;
63     }
64
65     if (acc_size <= len - 1) {
66         // pad zero
67         *(char*)(buffer + acc_size + 1) = 0;
68     }
69
70     vfree(map->buffer);
71     return acc_size;
72 }
73
74 void
75 twimap_printf(struct twimap* mapping, const char* fmt, ...)
76 {
77     va_list args;
78     va_start(args, fmt);
79
80     char* buf = mapping->buffer + mapping->size_acc;
81
82     mapping->size_acc +=
83       ksnprintfv(buf, fmt, TWIMAP_BUFFER_SIZE, args) - 1;
84
85     va_end(args);
86 }
87
88 int
89 twimap_memcpy(struct twimap* mapping, const void* src, const size_t len)
90 {
91     mapping->size_acc = MIN(TWIMAP_BUFFER_SIZE, len);
92     memcpy(mapping->buffer, src, mapping->size_acc);
93
94     return mapping->size_acc;
95 }
96
97 int
98 twimap_memappend(struct twimap* mapping, const void* src, const size_t len)
99 {
100     size_t cpy_len = MIN(TWIMAP_BUFFER_SIZE - mapping->size_acc, len);
101     memcpy(mapping->buffer + mapping->size_acc, src, cpy_len);
102     mapping->size_acc += cpy_len;
103
104     return cpy_len;
105 }
106
107 struct twimap*
108 twimap_create(void* data)
109 {
110     struct twimap* map = vzalloc(sizeof(struct twimap));
111     map->reset = __twimap_default_reset;
112     map->go_next = __twimap_default_gonext;
113     map->data = data;
114
115     return map;
116 }
117
118 struct v_file_ops twimap_file_ops = { .close = default_file_close,
119                                       .read = __twimap_file_read,
120                                       .read_page = __twimap_file_read,
121                                       .readdir = default_file_readdir,
122                                       .seek = default_file_seek,
123                                       .write = default_file_write };