alt_printf 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +8 -2
- data/alt_printf.gemspec +1 -1
- data/ext/alt_printf/alt_printf.c +135 -147
- data/ext/alt_printf/altprintf.h +4 -41
- data/ext/alt_printf/enums.h +6 -0
- data/ext/alt_printf/extconf.h +1 -0
- data/ext/alt_printf/extconf.rb +2 -3
- data/ext/alt_printf/extconf_debug.rb +4 -0
- data/ext/alt_printf/extconf_dev.rb +2 -7
- data/ext/alt_printf/extconf_helper.rb +35 -0
- data/ext/alt_printf/fmt.c +174 -0
- data/ext/alt_printf/fmt.h +8 -0
- data/ext/alt_printf/fmte.c +92 -0
- data/ext/alt_printf/fmte.h +37 -0
- data/ext/alt_printf/log.h +2 -1
- data/ext/alt_printf/parsef.c +125 -0
- data/ext/alt_printf/parsef.h +10 -0
- data/ext/alt_printf/strbuf.c +44 -26
- data/ext/alt_printf/strbuf.h +12 -3
- data/ext/alt_printf/syntax.h +8 -5
- data/lib/alt_printf/alt_printf.so +0 -0
- data/lib/alt_printf/version.rb +1 -1
- metadata +12 -6
- data/ext/alt_printf/altprintf.c +0 -250
- data/ext/alt_printf/list.c +0 -81
- data/ext/alt_printf/list.h +0 -24
data/ext/alt_printf/extconf.h
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
|
data/ext/alt_printf/extconf.rb
CHANGED
@@ -1,9 +1,4 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
require 'mkmf'
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
$objs = Dir[File.join(base_dir, 'target/release/*.o')] + ['alt_printf.o']
|
7
|
-
|
8
|
-
create_header
|
9
|
-
create_makefile('alt_printf')
|
3
|
+
require_relative 'extconf_helper'
|
4
|
+
ExtconfHelper.setup('dev')
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
|
3
|
+
module ExtconfHelper
|
4
|
+
BASE_DIR = File.join(__dir__, '../../../')
|
5
|
+
|
6
|
+
module_function
|
7
|
+
|
8
|
+
def dev_header
|
9
|
+
find_header('altprintf.h', File.join(BASE_DIR, 'src'))
|
10
|
+
end
|
11
|
+
|
12
|
+
def dev_objs(folder = 'release')
|
13
|
+
$objs = Dir[File.join(BASE_DIR, "target/#{folder}/*.o")] + ['alt_printf.o']
|
14
|
+
end
|
15
|
+
|
16
|
+
def setup(mode = 'release')
|
17
|
+
puts "extconf setting up #{mode}"
|
18
|
+
case mode
|
19
|
+
when 'release'
|
20
|
+
# do nothing
|
21
|
+
when 'dev'
|
22
|
+
dev_header
|
23
|
+
dev_objs('release')
|
24
|
+
when 'debug'
|
25
|
+
dev_header
|
26
|
+
$defs.push("-DDEBUG")
|
27
|
+
dev_objs('debug')
|
28
|
+
else
|
29
|
+
raise(ArgumentError, "invalid mode #{mode}")
|
30
|
+
end
|
31
|
+
|
32
|
+
create_header
|
33
|
+
create_makefile('alt_printf')
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
#include "fmt.h"
|
2
|
+
|
3
|
+
#define BUFNUM 25
|
4
|
+
|
5
|
+
void fmt_mul(struct strbuf *sb, struct fmte *f) {
|
6
|
+
long int *i = f->value;
|
7
|
+
if (f->parenarg_start == NULL) {
|
8
|
+
strbuf_pad(sb, f->chararg, *i);
|
9
|
+
} else {
|
10
|
+
for (int j=0; j<*i; j++) {
|
11
|
+
strbuf_append_str(sb, f->parenarg_start, -f->parenarg_len);
|
12
|
+
}
|
13
|
+
}
|
14
|
+
}
|
15
|
+
|
16
|
+
void fmt_tern(struct strbuf *sb, struct fmte *f) {
|
17
|
+
if (f->parenarg_start == NULL) return;
|
18
|
+
|
19
|
+
long int *b = f->value;
|
20
|
+
int first_half = 1;
|
21
|
+
wchar_t sep = f->chararg;
|
22
|
+
wchar_t *p = f->parenarg_start;
|
23
|
+
for (;p<=f->parenarg_end;p++) {
|
24
|
+
LOG("*p: %lc, first half? %d, bool: %ld, sep: %lc\n", (wint_t)*p, first_half, *b, (wint_t)sep);
|
25
|
+
if (*p == sep) first_half = 0;
|
26
|
+
else if (*b && first_half) strbuf_append_char(sb, p);
|
27
|
+
else if (!*b && !first_half) strbuf_append_char(sb, p);
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
void fmt_raw(struct strbuf *sb, struct fmte *f) {
|
32
|
+
strbuf_append_str(sb, f->parenarg_start, -1 * f->parenarg_len);
|
33
|
+
}
|
34
|
+
|
35
|
+
void fmt_string(struct strbuf *sb, struct fmte *f) {
|
36
|
+
int prec = f->prec == -1 ? 100000000 : f->prec;
|
37
|
+
strbuf_append_str(sb, f->value, prec);
|
38
|
+
}
|
39
|
+
|
40
|
+
void fmt_char(struct strbuf *sb, struct fmte *f) {
|
41
|
+
strbuf_append_char(sb, f->value);
|
42
|
+
}
|
43
|
+
|
44
|
+
void fmt_int(struct strbuf *sb, struct fmte *f) {
|
45
|
+
strbuf_append_int(sb, f->value);
|
46
|
+
}
|
47
|
+
|
48
|
+
void fmt_double(struct strbuf *sb, struct fmte *f) {
|
49
|
+
int prec = f->prec == -1 ? 3 : f->prec;
|
50
|
+
strbuf_append_double(sb, f->value, prec);
|
51
|
+
}
|
52
|
+
|
53
|
+
void fmt(struct strbuf *sb, struct fmte *f, void (*fmtr)(struct strbuf *, struct fmte *)) {
|
54
|
+
struct strbuf *tmp = strbuf_new();
|
55
|
+
fmtr(tmp, f);
|
56
|
+
|
57
|
+
if (tmp->len == 0) {
|
58
|
+
strbuf_destroy(tmp);
|
59
|
+
return;
|
60
|
+
};
|
61
|
+
|
62
|
+
int pad = f->pad - tmp->width;
|
63
|
+
|
64
|
+
if (pad > 0) {
|
65
|
+
LOG("padding: %d\n", pad);
|
66
|
+
switch(f->align) {
|
67
|
+
case Right:
|
68
|
+
strbuf_append_strbuf(sb, tmp);
|
69
|
+
strbuf_pad(sb, f->padchar, pad);
|
70
|
+
break;
|
71
|
+
case Left:
|
72
|
+
strbuf_pad(sb, f->padchar, pad);
|
73
|
+
strbuf_append_strbuf(sb, tmp);
|
74
|
+
break;
|
75
|
+
case Center:
|
76
|
+
strbuf_pad(sb, f->padchar, pad/2);
|
77
|
+
strbuf_append_strbuf(sb, tmp);
|
78
|
+
strbuf_pad(sb, f->padchar, pad/2 + pad%2);
|
79
|
+
break;
|
80
|
+
}
|
81
|
+
} else {
|
82
|
+
strbuf_append_strbuf(sb, tmp);
|
83
|
+
}
|
84
|
+
|
85
|
+
strbuf_destroy(tmp);
|
86
|
+
}
|
87
|
+
|
88
|
+
wchar_t *assemble_fmt(struct fmte *head) {
|
89
|
+
struct fmte *f = head;
|
90
|
+
struct strbuf *bufs[BUFNUM];
|
91
|
+
struct fmte *splits[BUFNUM];
|
92
|
+
size_t buf = 0, i;
|
93
|
+
size_t w, tw, rw;
|
94
|
+
wchar_t *final;
|
95
|
+
void (*fmtr)(struct strbuf *, struct fmte *) = NULL;
|
96
|
+
int loop = 1;
|
97
|
+
|
98
|
+
bufs[buf] = strbuf_new();
|
99
|
+
|
100
|
+
LOG("assembling elements\n");
|
101
|
+
while (loop) {
|
102
|
+
switch (f->type) {
|
103
|
+
case FMul:
|
104
|
+
fmtr = fmt_mul;
|
105
|
+
break;
|
106
|
+
case FTern:
|
107
|
+
fmtr = fmt_tern;
|
108
|
+
break;
|
109
|
+
case FInt:
|
110
|
+
fmtr = fmt_int;
|
111
|
+
break;
|
112
|
+
case FChar:
|
113
|
+
fmtr = fmt_char;
|
114
|
+
break;
|
115
|
+
case FDouble:
|
116
|
+
fmtr = fmt_double;
|
117
|
+
break;
|
118
|
+
case FString:
|
119
|
+
fmtr = fmt_string;
|
120
|
+
break;
|
121
|
+
case FRaw:
|
122
|
+
fmtr = fmt_raw;
|
123
|
+
break;
|
124
|
+
|
125
|
+
case FAlign:
|
126
|
+
buf++;
|
127
|
+
splits[buf] = f;
|
128
|
+
bufs[buf] = strbuf_new();
|
129
|
+
fmtr = NULL;
|
130
|
+
break;
|
131
|
+
case FEnd:
|
132
|
+
loop = 0;
|
133
|
+
fmtr = NULL;
|
134
|
+
break;
|
135
|
+
case FNone:
|
136
|
+
fmtr = NULL;
|
137
|
+
break;
|
138
|
+
}
|
139
|
+
|
140
|
+
if (fmtr != NULL) fmt(bufs[buf], f, fmtr);
|
141
|
+
f = f->next;
|
142
|
+
}
|
143
|
+
|
144
|
+
// Assemble splits
|
145
|
+
LOG("assembling %d splits\n", buf);
|
146
|
+
tw = bufs[0]->width;
|
147
|
+
for (i = 1; i <= buf; i++) {
|
148
|
+
rw = *(long *)splits[i]->value;
|
149
|
+
|
150
|
+
if (tw > rw) {
|
151
|
+
LOG("trimming first half to width\n");
|
152
|
+
strbuf_destroy(bufs[i]);
|
153
|
+
bufs[i] = bufs[0];
|
154
|
+
bufs[0] = strbuf_new();
|
155
|
+
strbuf_appendw_strbuf(bufs[0], bufs[i], rw);
|
156
|
+
} else {
|
157
|
+
if (rw > bufs[i]->width + tw) {
|
158
|
+
w = rw - (bufs[i]->width + tw);
|
159
|
+
LOG("padding %d\n", w);
|
160
|
+
strbuf_pad(bufs[0], splits[i]->chararg, w);
|
161
|
+
strbuf_append_strbuf(bufs[0], bufs[i]);
|
162
|
+
} else {
|
163
|
+
LOG("%d %d %d\n", w, rw, tw);
|
164
|
+
strbuf_appendw_strbuf(bufs[0], bufs[i], rw - tw);
|
165
|
+
}
|
166
|
+
}
|
167
|
+
|
168
|
+
tw = rw;
|
169
|
+
}
|
170
|
+
|
171
|
+
final = strbuf_cstr(bufs[0]);
|
172
|
+
for (i = 0; i <= buf; i++) strbuf_destroy(bufs[i]);
|
173
|
+
return final;
|
174
|
+
}
|
@@ -0,0 +1,92 @@
|
|
1
|
+
#include "fmte.h"
|
2
|
+
|
3
|
+
struct fmte *fmte_ini() {
|
4
|
+
struct fmte *f = malloc(sizeof(struct fmte));
|
5
|
+
|
6
|
+
f->parenarg_start = NULL;
|
7
|
+
f->parenarg_end = NULL;
|
8
|
+
f->parenarg_len = 0;
|
9
|
+
|
10
|
+
f->anglearg_start = NULL;
|
11
|
+
f->anglearg_end = NULL;
|
12
|
+
f->anglearg_len = 0;
|
13
|
+
|
14
|
+
f->chararg = L' ';
|
15
|
+
f->padchar = L' ';
|
16
|
+
f->type = FNone;
|
17
|
+
f->align = Right;
|
18
|
+
f->prec = -1;
|
19
|
+
f->pad = 0;
|
20
|
+
f->value = NULL;
|
21
|
+
|
22
|
+
f->next = NULL;
|
23
|
+
|
24
|
+
return f;
|
25
|
+
}
|
26
|
+
|
27
|
+
void fmte_push(struct fmte *a, struct fmte *b) {
|
28
|
+
if (a == b) return; // refuse to create an infinite loop
|
29
|
+
|
30
|
+
while (a->next != NULL) a = a->next;
|
31
|
+
|
32
|
+
a->next = b;
|
33
|
+
}
|
34
|
+
|
35
|
+
void fmte_destroy(struct fmte *f) {
|
36
|
+
struct fmte *j;
|
37
|
+
while (f != NULL) {
|
38
|
+
j = f->next;
|
39
|
+
free(f->value);
|
40
|
+
free(f);
|
41
|
+
f = j;
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
void fmte_inspect(struct fmte *f) {
|
46
|
+
wchar_t *parenarg = calloc(f->parenarg_len + 1, sizeof(wchar_t));
|
47
|
+
wchar_t *anglearg = calloc(f->anglearg_len + 1, sizeof(wchar_t));
|
48
|
+
size_t i;
|
49
|
+
|
50
|
+
for (i=0;i<f->parenarg_len;i++) parenarg[i] = f->parenarg_start[i];
|
51
|
+
for (i=0;i<f->anglearg_len;i++) anglearg[i] = f->anglearg_start[i];
|
52
|
+
|
53
|
+
printf(
|
54
|
+
"Format@%p {\n\
|
55
|
+
parenarg_start: %p,\n\
|
56
|
+
parenarg_end: %p,\n\
|
57
|
+
parenarg_len: %d,\n\
|
58
|
+
(parenarg): %ls,\n\
|
59
|
+
anglearg_start: %p,\n\
|
60
|
+
anglearg_end: %p,\n\
|
61
|
+
anglearg_len: %d,\n\
|
62
|
+
(anglearg): %ls,\n\
|
63
|
+
chararg: %lc,\n\
|
64
|
+
padchar: %lc,\n\
|
65
|
+
type: %d,\n\
|
66
|
+
align: %d,\n\
|
67
|
+
prec: %ld,\n\
|
68
|
+
pad: %ld,\n\
|
69
|
+
value: %p,\n\
|
70
|
+
next: %p\n\
|
71
|
+
}\n",
|
72
|
+
f,
|
73
|
+
f->parenarg_start,
|
74
|
+
f->parenarg_end,
|
75
|
+
f->parenarg_len,
|
76
|
+
parenarg,
|
77
|
+
f->anglearg_start,
|
78
|
+
f->anglearg_end,
|
79
|
+
f->anglearg_len,
|
80
|
+
anglearg,
|
81
|
+
f->chararg,
|
82
|
+
f->padchar,
|
83
|
+
f->type,
|
84
|
+
f->align,
|
85
|
+
f->prec,
|
86
|
+
f->pad,
|
87
|
+
f->value,
|
88
|
+
f->next);
|
89
|
+
|
90
|
+
free(parenarg);
|
91
|
+
free(anglearg);
|
92
|
+
}
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#ifndef FMTE_H_
|
2
|
+
#define FMTE_H_
|
3
|
+
#include <wchar.h>
|
4
|
+
#include <stdlib.h>
|
5
|
+
#include <stdio.h>
|
6
|
+
#include "enums.h"
|
7
|
+
#include "log.h"
|
8
|
+
|
9
|
+
struct fmte {
|
10
|
+
wchar_t *parenarg_start;
|
11
|
+
wchar_t *parenarg_end;
|
12
|
+
size_t parenarg_len;
|
13
|
+
|
14
|
+
wchar_t *anglearg_start;
|
15
|
+
wchar_t *anglearg_end;
|
16
|
+
size_t anglearg_len;
|
17
|
+
|
18
|
+
wint_t chararg;
|
19
|
+
|
20
|
+
wint_t padchar;
|
21
|
+
|
22
|
+
enum arg_type type;
|
23
|
+
enum align align;
|
24
|
+
|
25
|
+
long prec;
|
26
|
+
long pad;
|
27
|
+
|
28
|
+
void *value;
|
29
|
+
|
30
|
+
struct fmte *next;
|
31
|
+
};
|
32
|
+
|
33
|
+
struct fmte *fmte_ini();
|
34
|
+
void fmte_inspect(struct fmte *);
|
35
|
+
void fmte_push(struct fmte *, struct fmte *);
|
36
|
+
void fmte_destroy(struct fmte *);
|
37
|
+
#endif
|
data/ext/alt_printf/log.h
CHANGED
@@ -2,10 +2,11 @@
|
|
2
2
|
#define LOG_H
|
3
3
|
|
4
4
|
#ifdef DEBUG
|
5
|
-
#define LOG(...) printf("%s[%
|
5
|
+
#define LOG(...) printf("%s:%d [\e[35m%s\e[0m] ", __FILE__, __LINE__, __func__);printf(__VA_ARGS__);
|
6
6
|
#define FLOG(msg, ...) fprintf(stderr, "%s[%d] - "msg, __FILE__, __LINE__ __VA_OPT__(,) __VA_ARGS__)
|
7
7
|
#else
|
8
8
|
#define LOG(msg, ...)
|
9
9
|
#define FLOG(msg, ...)
|
10
10
|
#endif
|
11
|
+
|
11
12
|
#endif
|
@@ -0,0 +1,125 @@
|
|
1
|
+
#include "parsef.h"
|
2
|
+
|
3
|
+
#define EOS L'\0'
|
4
|
+
|
5
|
+
wchar_t *altprintf_pct = L"%";
|
6
|
+
|
7
|
+
struct fmte *parsef(wchar_t **fmt) {
|
8
|
+
wchar_t *w_c;
|
9
|
+
wchar_t **w_a = &w_c;
|
10
|
+
struct fmte *f = fmte_ini();
|
11
|
+
long *l_a = &f->pad;
|
12
|
+
|
13
|
+
LOG("processing %ld (%lc)\n", **fmt, (wint_t)**fmt);
|
14
|
+
|
15
|
+
if (**fmt != FS_START) {
|
16
|
+
if (**fmt == EOS) {
|
17
|
+
f->type = FEnd;
|
18
|
+
goto return_format;
|
19
|
+
}
|
20
|
+
|
21
|
+
LOG("building raw format\n");
|
22
|
+
f->type = FRaw;
|
23
|
+
|
24
|
+
f->parenarg_start = *fmt;
|
25
|
+
LOG("scanning long arg\n");
|
26
|
+
get_longarg(fmt, &f->parenarg_end, FS_START, &f->parenarg_len);
|
27
|
+
|
28
|
+
f->parenarg_end++;
|
29
|
+
f->parenarg_len++;
|
30
|
+
(*fmt)--;
|
31
|
+
|
32
|
+
goto return_format;
|
33
|
+
} else {
|
34
|
+
LOG("building format\n");
|
35
|
+
(*fmt)++;
|
36
|
+
}
|
37
|
+
|
38
|
+
for (;**fmt != L'\0';(*fmt)++) {
|
39
|
+
LOG("scanned char '%lc'\n", (wint_t)(**fmt));
|
40
|
+
switch (**fmt) {
|
41
|
+
case FS_A_CHARARG:
|
42
|
+
(*fmt)++;
|
43
|
+
f->chararg = **fmt;
|
44
|
+
break;
|
45
|
+
case FS_A_ANGLEARG_S:
|
46
|
+
f->anglearg_start = *fmt + 1;
|
47
|
+
get_longarg(fmt, &f->anglearg_end, FS_A_ANGLEARG_E, &f->anglearg_len);
|
48
|
+
break;
|
49
|
+
case FS_A_PARENARG_S:
|
50
|
+
f->parenarg_start = *fmt + 1;
|
51
|
+
get_longarg(fmt, &f->parenarg_end, FS_A_PARENARG_E, &f->parenarg_len);
|
52
|
+
break;
|
53
|
+
case FS_A_LALIGN:
|
54
|
+
f->align = Left;
|
55
|
+
break;
|
56
|
+
case FS_A_CALIGN:
|
57
|
+
f->align = Center;
|
58
|
+
break;
|
59
|
+
case FS_A_SPAD:
|
60
|
+
f->padchar = FS_A_SPAD;
|
61
|
+
break;
|
62
|
+
case FS_A_ZPAD:
|
63
|
+
f->padchar = '0';
|
64
|
+
break;
|
65
|
+
case FS_A_PREC:
|
66
|
+
l_a = &f->prec;
|
67
|
+
break;
|
68
|
+
case '1': case '2': case '3': case '4': case '5':
|
69
|
+
case '6': case '7': case '8': case '9':
|
70
|
+
LOG("l_a: %p %ld\n", l_a, *l_a);
|
71
|
+
*l_a = wcstol(*fmt, w_a, 10);
|
72
|
+
*fmt = *w_a - 1;
|
73
|
+
break;
|
74
|
+
// Psuedo-type
|
75
|
+
case FS_START:
|
76
|
+
f->type = FRaw;
|
77
|
+
f->parenarg_start = &altprintf_pct[0];
|
78
|
+
f->parenarg_end = &altprintf_pct[1];
|
79
|
+
f->parenarg_len = 1;
|
80
|
+
goto return_format;
|
81
|
+
// Types
|
82
|
+
case FS_T_STRING:
|
83
|
+
f->type = FString;
|
84
|
+
goto return_format;
|
85
|
+
case FS_T_MUL:
|
86
|
+
f->type = FMul;
|
87
|
+
goto return_format;
|
88
|
+
case FS_T_TERN:
|
89
|
+
f->type = FTern;
|
90
|
+
goto return_format;
|
91
|
+
case FS_T_ALIGN:
|
92
|
+
f->type = FAlign;
|
93
|
+
goto return_format;
|
94
|
+
case FS_T_INT:
|
95
|
+
f->type = FInt;
|
96
|
+
goto return_format;
|
97
|
+
case FS_T_CHAR:
|
98
|
+
f->type = FChar;
|
99
|
+
goto return_format;
|
100
|
+
case FS_T_DOUBLE:
|
101
|
+
f->type = FDouble;
|
102
|
+
goto return_format;
|
103
|
+
default:
|
104
|
+
f->type = FRaw;
|
105
|
+
}
|
106
|
+
}
|
107
|
+
|
108
|
+
f->type = FEnd;
|
109
|
+
return_format:
|
110
|
+
(*fmt)++;
|
111
|
+
return f;
|
112
|
+
}
|
113
|
+
|
114
|
+
void get_longarg(wchar_t **s, wchar_t **e, wchar_t stop, size_t *size) {
|
115
|
+
*size = 0;
|
116
|
+
|
117
|
+
while (**s != EOS && **s != stop) {
|
118
|
+
LOG("checking (%lc)\n", (wint_t)**s);
|
119
|
+
(*s)++;
|
120
|
+
(*size)++;
|
121
|
+
}
|
122
|
+
|
123
|
+
(*size)--;
|
124
|
+
if (*size > 0) *e = *s - 1;
|
125
|
+
}
|