-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparse.c
112 lines (82 loc) · 2.01 KB
/
parse.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
#include <dirent.h>
#include <errno.h>
#include <limits.h>
#include <stdint.h>
#include <inttypes.h>
#include "parse.h"
#include "vec.h"
#include "lsdir.h"
#include "num.h"
/**
* 0 success
* -1 error with errno (ie, vec_add() ENOMEM)
* -2 general parsing error without errno
* -3 parsing error with errno (ie, strtonum() ERANGE)
*/
int lsdir_parse(char **const buf, Vec *const res) {
assert(buf != NULL);
assert(res != NULL);
char *p = *buf;
while (*p != '\0') {
struct tdir *dir = NULL;
if (*p == '-') {
p++;
*buf = p;
return (0);
}
if ((dir = vec_add(res, 1)) == NULL)
return (-1);
if (*p == 'D' || *p == 'L' || *p == 'F' || *p == 'U') dir->type = *p;
else return (-2);
p++;
if (*p != '\0')
return (-2);
p++;
{ /* parse filename */
for (dir->filename = p; *p != '\0'; p++)
continue;
if (dir->filename == p)
return (-2);
p++;
}
if (dir->type == 'D') {
int ret = 0;
dir->info.children = vec_init(sizeof(TDir), 64, (VecCB) tdir_free);
if ((ret = lsdir_parse(&p, &dir->info.children)) < 0)
return (ret);
if (*p != '\0')
return (-2);
p++;
} else if (dir->type == 'L') {
for (dir->info.target = p; *p != '\0'; p++)
continue;
if (dir->info.target == p)
return (-1);
p++;
} else if (dir->type == 'F') {
const char *str = NULL;
long long num = 0;
for (str = p; *p != '\0'; p++)
continue;
if (!strtonum(str, 0, LLONG_MAX, &num))
return (-3);
dir->info.file.mtime = num;
p++;
for (str = p; *p != '\0'; p++)
continue;
if (!strtonum(str, 0, LLONG_MAX, &num))
return (-3);
dir->info.file.size = (unsigned long long) num;
p++;
} else if (dir->type == 'U') {
} else {
assert(false);
}
p++;
}
*buf = p;
return (0);
}