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