File Coverage

rs.xs
Criterion Covered Total %
statement 0 85 0.0
branch 0 60 0.0
condition n/a
subroutine n/a
pod n/a
total 0 145 0.0


line stmt bran cond sub pod time code
1             /*
2             Copyright © 2018 Yang Bo
3              
4             This file is part of RSLinux.
5              
6             RSLinux is free software: you can redistribute it and/or modify
7             it under the terms of the GNU General Public License as published by
8             the Free Software Foundation, either version 3 of the License, or
9             (at your option) any later version.
10              
11             RSLinux is distributed in the hope that it will be useful,
12             but WITHOUT ANY WARRANTY; without even the implied warranty of
13             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14             GNU General Public License for more details.
15              
16             You should have received a copy of the GNU General Public License
17             along with RSLinux. If not, see .
18             */
19             #define PERL_NO_GET_CONTEXT
20             #include "EXTERN.h"
21             #include "perl.h"
22             #include "XSUB.h"
23             #include "ppport.h"
24              
25             #include
26             #include
27             #include
28             #include
29             #include
30             #include
31             #include
32              
33             #include
34             #include
35             #define STR(a) #a
36             #define STR1(a) STR(a)
37             #define WRAP(a) \
38             do { \
39             a; \
40             } while (0)
41             #define croak_if(cond, s) \
42             WRAP(if (cond) { \
43             perror("File " __FILE__ ", line " STR1(__LINE__) ", " s); \
44             exit(~0); \
45             })
46             #define errn1(a) croak_if((a) == -1, "("#a") == -1")
47             #define unless(a) if (!(a))
48              
49             #define CALL s[sp].st = NEW, sp += 1
50             #define RET(a) v = a, sp -= 1
51              
52             #define BLKSZ 4096
53             #define FLUSH errn1(write(fd, ou, ol)); ol = 0
54              
55             #define LLAC(a) s[sp].st = NEW, sp += 1, v = a
56             #define TER sp -= 1
57             #define HPACK(t, l) *p = t, *(uint32_t*)(p + 1) = (uint32_t)l, cwrite(fd, p, 5)
58              
59 0           void *mmapr(const char *f, off_t *l)
60             {
61             int fd;
62 0 0         errn1(fd = open(f, O_RDONLY));
63             struct stat b;
64 0 0         errn1(fstat(fd, &b));
65 0 0         if (l) *l = b.st_size;
66 0           void *p = NULL;
67 0 0         if (b.st_size)
68 0 0         errn1((long int)(p = mmap(0, b.st_size, PROT_READ, MAP_PRIVATE, fd, 0)));
69 0 0         errn1(close(fd));
70 0           return p;
71             }
72 0           void cwrite(int fd, const char *in, size_t il)
73             {
74             static char ou[BLKSZ];
75             static size_t ol;
76 0 0         unless (in) {
77 0 0         FLUSH;
78 0           return;
79             }
80 0 0         while (il) {
81 0 0         if (ol + il >= BLKSZ) {
82 0 0         if (ol == 0) {
83 0 0         errn1(write(fd, in, il));
84 0           il = 0;
85             } else {
86 0           size_t l = BLKSZ - ol;
87 0           memcpy(ou + ol, in, l); ol += l, in += l, il -= l;
88 0 0         FLUSH;
89             }
90             } else {
91 0           memcpy(ou + ol, in, il); ol += il, il = 0;
92             }
93             }
94             }
95              
96             MODULE = App::rs PACKAGE = App::rs
97              
98             SV*
99             rs_parse(char *f)
100             CODE:
101 0           char *p = (char*)mmapr(f, NULL);
102             struct {
103             enum {
104             NEW, RK, RV
105             }st;
106             uint32_t l;
107             SV *key;
108             HV *v;
109             }s[256], *q;
110             SV *v;
111 0           uint8_t sp = 0;
112 0           CALL;
113 0 0         while (sp) {
114 0           q = s + sp - 1;
115 0 0         if (q->st == NEW) {
116 0           char t = *p++;
117 0           uint32_t l = *(uint32_t*)p;
118 0           p += 4;
119 0 0         if (t == 'S') {
120 0           v = newSV(0);
121 0 0         SvUPGRADE(v, SVt_PV);
122 0           SvPVX(v) = p, SvCUR_set(v, l), SvLEN_set(v, 0);
123 0           SvPOK_only(v);
124 0           p += l, sp -= 1;
125             } else {
126 0 0         if (l) {
127 0           q->v = newHV(), q->l = l, q->st = RK;
128 0           CALL;
129             } else {
130 0           RET(newRV_noinc((SV*)newHV()));
131             }
132             }
133             } else {
134 0 0         if (q->st == RK) {
135 0           q->key = v, q->st = RV;
136 0           CALL;
137             } else {
138 0           hv_store_ent(q->v, q->key, v, 0);
139 0 0         if (q->l -= 1) {
140 0           q->st = RK;
141 0           CALL;
142             } else {
143 0           RET(newRV_noinc((SV*)q->v));
144             }
145             }
146             }
147             }
148 0           RETVAL = v;
149             OUTPUT:
150             RETVAL
151              
152             void
153             rs_unparse(SV *v, int fd)
154             CODE:
155             char p[5];
156             struct {
157             enum {
158             NEW, OLD
159             }st;
160             HV *v;
161             }s[256], *q;
162 0           uint8_t sp = 0;
163 0           LLAC(v);
164 0 0         while (sp) {
165 0           q = s + sp - 1;
166 0 0         if (q->st == NEW) {
167 0 0         unless (SvROK(v)) {
168             char *in;
169             STRLEN il;
170 0 0         in = SvPV(v, il);
171 0           HPACK('S', il);
172 0           cwrite(fd, in, il);
173 0           TER;
174             } else {
175 0           v = SvRV(v);
176 0 0         if (SvTYPE(v) < SVt_PVAV) {
177             off_t il;
178 0 0         char *in = (char*)mmapr(SvPV_nolen(v), &il);
179 0           HPACK('S', il);
180 0 0         if (il) {
181 0           cwrite(fd, in, il);
182 0 0         errn1(munmap(in, il));
183             }
184 0           TER;
185             } else {
186 0           q->v = (HV*)v, q->st = OLD;
187 0           uint32_t l = 0;
188 0           hv_iterinit(q->v);
189 0 0         while (hv_iternext(q->v)) l += 1;
190 0           HPACK('H', l);
191 0           hv_iterinit(q->v);
192             }
193             }
194             } else {
195             char *key;
196             I32 retlen;
197 0           v = hv_iternextsv(q->v, &key, &retlen);
198 0 0         if (v) {
199 0           HPACK('S', retlen);
200 0           cwrite(fd, key, retlen);
201 0           LLAC(v);
202             } else {
203 0           TER;
204             }
205             }
206             }
207 0           cwrite(fd, NULL, 0);
208              
209             bool
210             lchown(char *f, uid_t uid, gid_t gid)
211             POSTCALL:
212 0           RETVAL = !RETVAL;
213              
214             bool
215             utimensat(char *f, int t)
216             CODE:
217             struct timespec times[2];
218 0           times[0].tv_nsec = UTIME_OMIT;
219 0           times[1].tv_sec = t, times[1].tv_nsec = 0;
220 0           RETVAL = !utimensat(AT_FDCWD, f, times, AT_SYMLINK_NOFOLLOW);
221             OUTPUT:
222             RETVAL