-
Notifications
You must be signed in to change notification settings - Fork 0
/
imply_range.c
102 lines (77 loc) · 2.78 KB
/
imply_range.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
#include"strglob.h"
/*! @fn char **imply_range(STR_GLOB *const ugcur)
*
* @brief create an array of strings defined by the glob list elements' `beg` and `end` members
*
* @details depending upon the `type` and `zlen` members of `ugcur`, the created string array can consist of
* alphabetic, numeric or padded numeric strings. For example, if `type` is equal to `2` then alphabetic
* (i.e. single character) strings will be created. If `zlen` is non-zero then numeric strings which are
* padded with the number of zeroes defined by `zlen` are created (like `0001` if `zlen` is `3`.) Otherwise,
* an array of unpadded numeric strings is created.
*
* @param [in] ugcur the element of the glob list to operate on
*
* @return an array of strings containing a range of characters or numbers
*/
static inline int lteq(const intmax_t a, const intmax_t b) {
return a <= b;
}
static inline int gteq(const intmax_t x, const intmax_t y) {
return x >= y;
}
char **imply_range(STR_GLOB *const ugcur) {
assert(ugcur);
register STR_GLOB *const ugptr = ugcur;
const intmax_t lo = ugcur->runi.crng.beg, hi = ugcur->runi.crng.end;
register intmax_t nm = 0, in = ugcur->runi.crng.inc;
size_t rngln = 1 + ugptr->runi.crng.end - ugptr->runi.crng.beg;
int (*fp)(const intmax_t, const intmax_t) = lteq;
bool nopre = true; /* no prepend */
if(lo < 0 || hi < 0)
nopre = false;
if(lo > hi) { /* determine the increment direction (important for support of signed integer ranges) */
if(in > 0)
in = -in;
fp = gteq;
rngln = 1 + ugptr->runi.crng.beg - ugptr->runi.crng.end;
}
char **pp = malloc(++rngln * sizeof*pp);
if(!pp)
exit_verbose("malloc", __FILE__, __LINE__);
ugptr->out = pp;
/* #pragma omp parallel for */
for(nm = lo;fp(nm, hi);nm += in) {
size_t vlen = measure_integer(nm);
char *rpt = NULL;
if(ugptr->type == 2) {
rpt = malloc(2);
if(!rpt)
exit_verbose("malloc", __FILE__, __LINE__);
rpt[0] = (char) nm;
rpt[1] = '\0';
} else if(nopre && ugptr->zlen > vlen) {
rpt = malloc(1 + ugptr->zlen);
if(!rpt)
exit_verbose("malloc", __FILE__, __LINE__);
if(!nm)
vlen++;
memset(rpt, '0', ugptr->zlen - vlen);
#if __WORDSIZE == 64
if(nm > UINT_MAX)
sprintf(&rpt[ugptr->zlen - vlen], "%ld", (intmax_t) nm);
else
sprintf(&rpt[ugptr->zlen - vlen], "%d", (int) nm);
#else
sprintf(&rpt[ugptr->zlen - vlen], "%ld", (intmax_t) nm);
#endif
} else {
rpt = malloc(++vlen);
if(!rpt)
exit_verbose("malloc", __FILE__, __LINE__);
sprintf(rpt, "%ld", (intmax_t) nm);
}
*pp++ = rpt;
}
*pp = NULL;
return ugptr->out;
}