alt_printf 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
}
|