altprintf 0.2.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 +7 -0
- data/altprintf.gemspec +24 -0
- data/ext/altprintf/altprintf.h +6 -0
- data/ext/altprintf/enums.h +15 -0
- data/ext/altprintf/ext.c +270 -0
- data/ext/altprintf/extconf.h +1 -0
- data/ext/altprintf/extconf_helper.rb +35 -0
- data/ext/altprintf/fmt.c +243 -0
- data/ext/altprintf/fmt.h +9 -0
- data/ext/altprintf/fmte.c +98 -0
- data/ext/altprintf/fmte.h +37 -0
- data/ext/altprintf/log.h +12 -0
- data/ext/altprintf/parsef.c +127 -0
- data/ext/altprintf/parsef.h +10 -0
- data/ext/altprintf/strbuf.c +178 -0
- data/ext/altprintf/strbuf.h +38 -0
- data/ext/altprintf/syntax.h +35 -0
- data/lib/altprintf.rb +2 -0
- data/lib/altprintf/alt_printf.so +0 -0
- data/lib/altprintf/altprintf.so +0 -0
- data/lib/altprintf/version.rb +3 -0
- data/readme.md +16 -0
- metadata +91 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: df338e1fe04766f80321b04dc0380e6c022ae06c8e4d13cbaea05522630b7463
|
4
|
+
data.tar.gz: 9b7c74147e5ef03e947467d2c4c89e7471c873a56410d2aa00f4015680352c96
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ba342f2d892020efc12b7e0489a376b005fb2161b81ae235ac9021d04f7d594c9bda20e0c8c1a332a607a4897688faa34143c2bd1dcb100f6b71611992eeaa30
|
7
|
+
data.tar.gz: c19648ebefd35dbdf6b00760e92567be3f42c042227ba3e49d32f9595dcec29ce67ca47169c2f64ca1c164b199e3050c8a912403a1a28855c89b54084026a49d
|
data/altprintf.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'date'
|
2
|
+
require_relative 'lib/altprintf/version'
|
3
|
+
|
4
|
+
Altprintf::SPEC = Gem::Specification.new do |s|
|
5
|
+
s.name = 'altprintf'
|
6
|
+
s.version = Altprintf::VERSION.join('.')
|
7
|
+
s.date = Date.today.strftime('%Y-%m-%d')
|
8
|
+
s.summary = 'A powerful printf-like template language'
|
9
|
+
s.authors = ['Stone Tickle']
|
10
|
+
s.email = 'lattis@mochiro.moe'
|
11
|
+
s.homepage = 'https://github.com/annacrombie/altprintf/tree/master/gem'
|
12
|
+
s.license = 'MIT'
|
13
|
+
|
14
|
+
s.files = Dir['{**/*}'] - ['Rakefile']
|
15
|
+
|
16
|
+
s.platform = Gem::Platform::RUBY
|
17
|
+
s.extensions = Dir["ext/**/extconf.rb"]
|
18
|
+
s.require_paths = ['lib']
|
19
|
+
|
20
|
+
s.required_ruby_version = '>= 2.5.5'
|
21
|
+
|
22
|
+
s.add_development_dependency 'rake-compiler', '~> 1.0'
|
23
|
+
s.add_development_dependency 'rake', '~> 12.3'
|
24
|
+
end unless Altprintf.const_defined?(:'SPEC')
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#ifndef ARGTYPE_H_
|
2
|
+
#define ARGTYPE_H_
|
3
|
+
enum arg_type { FMul, FTern, FAlign, FInt, FChar, FDouble, FString, FRaw, FNone,
|
4
|
+
FEnd };
|
5
|
+
enum align { Left, Right, Center };
|
6
|
+
|
7
|
+
enum altprintf_err {
|
8
|
+
apfe_none,
|
9
|
+
apfe_invalid_token,
|
10
|
+
apfe_missing_argument
|
11
|
+
};
|
12
|
+
|
13
|
+
extern enum altprintf_err apf_err;
|
14
|
+
|
15
|
+
#endif
|
data/ext/altprintf/ext.c
ADDED
@@ -0,0 +1,270 @@
|
|
1
|
+
#ifdef _FORTIFY_SOURCE
|
2
|
+
#undef _FORTIFY_SOURCE
|
3
|
+
#endif
|
4
|
+
|
5
|
+
#ifdef RUBY_EXTCONF_H
|
6
|
+
#undef RUBY_EXTCONF_H
|
7
|
+
#endif
|
8
|
+
|
9
|
+
#include "extconf.h"
|
10
|
+
#include <stdio.h>
|
11
|
+
#include <locale.h>
|
12
|
+
#include <wchar.h>
|
13
|
+
#include <ruby.h>
|
14
|
+
#include <ruby/encoding.h>
|
15
|
+
#include "altprintf.h"
|
16
|
+
#include "log.h"
|
17
|
+
|
18
|
+
#define MODNAME "Altprintf"
|
19
|
+
|
20
|
+
rb_encoding *enc;
|
21
|
+
|
22
|
+
wchar_t *rbstowcs(VALUE str)
|
23
|
+
{
|
24
|
+
const char *cstr;
|
25
|
+
wchar_t *wstr;
|
26
|
+
size_t len;
|
27
|
+
|
28
|
+
cstr = StringValueCStr(str);
|
29
|
+
|
30
|
+
len = mbsrtowcs(NULL, &cstr, 0, NULL);
|
31
|
+
wstr = calloc(len + 1, sizeof(wchar_t));
|
32
|
+
len = mbsrtowcs(wstr, &cstr, len, NULL);
|
33
|
+
|
34
|
+
LOG("rbs to wcs, len: %d, cstr: '%s'\n", len, cstr);
|
35
|
+
LOG("wide string: '%ls'\n", wstr);
|
36
|
+
|
37
|
+
return wstr;
|
38
|
+
}
|
39
|
+
|
40
|
+
VALUE wcstorbs(const wchar_t *wstr)
|
41
|
+
{
|
42
|
+
size_t len;
|
43
|
+
char *cstr;
|
44
|
+
VALUE str;
|
45
|
+
|
46
|
+
LOG("converting wcs to rbs\n");
|
47
|
+
LOG("wcs: '%ls'\n\n", wstr);
|
48
|
+
|
49
|
+
len = wcsrtombs(NULL, &wstr, 0, NULL);
|
50
|
+
LOG("len: %d\n", len);
|
51
|
+
cstr = calloc(len, sizeof(wchar_t));
|
52
|
+
wcsrtombs(cstr, &wstr, len, NULL);
|
53
|
+
LOG("cstr: '%s'\n", cstr);
|
54
|
+
|
55
|
+
LOG("wcs to rbs, len: %d, wcs: %ls, mbs: '%s'\n", len, wstr, cstr);
|
56
|
+
|
57
|
+
if (len == (size_t)-1)
|
58
|
+
return Qnil;
|
59
|
+
|
60
|
+
str = rb_external_str_new_with_enc(cstr, len, enc);
|
61
|
+
free(cstr);
|
62
|
+
|
63
|
+
return str;
|
64
|
+
}
|
65
|
+
|
66
|
+
VALUE get_entry(struct fmte *f, size_t argc, size_t *argi, VALUE *argv, VALUE *hash)
|
67
|
+
{
|
68
|
+
VALUE sym, entry;
|
69
|
+
size_t len;
|
70
|
+
const wchar_t *tmpw;
|
71
|
+
char *cstr;
|
72
|
+
|
73
|
+
LOG("getting entry\n");
|
74
|
+
|
75
|
+
if (f->anglearg_len == 0) {
|
76
|
+
LOG("getting from argv[%d] (argc: %d)\n", *argi, argc);
|
77
|
+
if (*argi >= argc)
|
78
|
+
rb_raise(rb_eArgError, "too few arguments");
|
79
|
+
entry = rb_ary_entry(*argv, *argi);
|
80
|
+
(*argi)++;
|
81
|
+
return entry;
|
82
|
+
}
|
83
|
+
|
84
|
+
LOG("getting from hash\n");
|
85
|
+
|
86
|
+
tmpw = f->anglearg_start;
|
87
|
+
len = wcsnrtombs(NULL, &tmpw, f->anglearg_len, 0, NULL);
|
88
|
+
LOG("allocating %d, maxlen %d\n", len, f->anglearg_len);
|
89
|
+
|
90
|
+
cstr = calloc(len + 1, sizeof(char));
|
91
|
+
wcsnrtombs(cstr, &tmpw, f->anglearg_len, len, NULL);
|
92
|
+
LOG("wrote cstr %s\n", cstr);
|
93
|
+
|
94
|
+
LOG("symbol | cstr: '%s', len %d\n", cstr, len);
|
95
|
+
|
96
|
+
sym = rb_check_symbol_cstr(cstr, len, enc);
|
97
|
+
entry = rb_hash_lookup2(*hash, sym, Qnil);
|
98
|
+
if (entry == Qnil)
|
99
|
+
rb_raise(rb_eKeyError, "missing key :%s", cstr);
|
100
|
+
free(cstr);
|
101
|
+
|
102
|
+
return entry;
|
103
|
+
}
|
104
|
+
|
105
|
+
wchar_t *rb_apformat(wchar_t *fmt, size_t argc, size_t *argi, VALUE *argv, VALUE *hash)
|
106
|
+
{
|
107
|
+
struct fmte *f, *head;
|
108
|
+
wchar_t *final;
|
109
|
+
int loop = 1;
|
110
|
+
long *tmpi;
|
111
|
+
wint_t *tmpc;
|
112
|
+
wchar_t *tmps;
|
113
|
+
double *tmpd;
|
114
|
+
void *tmp;
|
115
|
+
VALUE entry;
|
116
|
+
|
117
|
+
head = f = parsef(&fmt);
|
118
|
+
|
119
|
+
while (loop) {
|
120
|
+
if (apf_err != apfe_none)
|
121
|
+
rb_raise(rb_eArgError, "malformed format string");
|
122
|
+
|
123
|
+
LOG("scanned type: %d\n", f->type);
|
124
|
+
|
125
|
+
if (f->type != FEnd && f->type != FRaw)
|
126
|
+
entry = get_entry(f, argc, argi, argv, hash);
|
127
|
+
else
|
128
|
+
entry = Qnil;
|
129
|
+
|
130
|
+
switch (f->type) {
|
131
|
+
case FString:
|
132
|
+
Check_Type(entry, T_STRING);
|
133
|
+
|
134
|
+
tmp = rbstowcs(entry);
|
135
|
+
goto match;
|
136
|
+
case FTern:
|
137
|
+
tmpi = malloc(sizeof(long));
|
138
|
+
|
139
|
+
*tmpi = (entry == Qfalse || entry == Qnil) ? 0 : 1;
|
140
|
+
|
141
|
+
tmp = tmpi;
|
142
|
+
goto match;
|
143
|
+
case FMul:
|
144
|
+
case FAlign:
|
145
|
+
case FInt:
|
146
|
+
Check_Type(entry, T_FIXNUM);
|
147
|
+
|
148
|
+
tmpi = malloc(sizeof(long));
|
149
|
+
*tmpi = FIX2LONG(entry);
|
150
|
+
tmp = tmpi;
|
151
|
+
goto match;
|
152
|
+
case FChar:
|
153
|
+
Check_Type(entry, T_STRING);
|
154
|
+
|
155
|
+
tmpc = malloc(sizeof(wint_t));
|
156
|
+
tmps = rbstowcs(entry);
|
157
|
+
*tmpc = btowc(tmps[0]);
|
158
|
+
tmp = tmpc;
|
159
|
+
goto match;
|
160
|
+
case FDouble:
|
161
|
+
Check_Type(entry, T_FLOAT);
|
162
|
+
|
163
|
+
tmpd = malloc(sizeof(double));
|
164
|
+
*tmpd = RFLOAT_VALUE(entry);
|
165
|
+
tmp = tmpd;
|
166
|
+
match:
|
167
|
+
f->value = tmp;
|
168
|
+
break;
|
169
|
+
case FRaw:
|
170
|
+
break;
|
171
|
+
case FEnd:
|
172
|
+
LOG("EOS (end of string)\n");
|
173
|
+
loop = 0;
|
174
|
+
break;
|
175
|
+
case FNone:
|
176
|
+
LOG("error! shouldn' t be none\n");
|
177
|
+
break;
|
178
|
+
}
|
179
|
+
|
180
|
+
LOG("pushing fmt\n");
|
181
|
+
#ifdef DEBUG
|
182
|
+
fmte_inspect(f);
|
183
|
+
#endif
|
184
|
+
fmte_push(head, f);
|
185
|
+
if (loop)
|
186
|
+
f = parsef(&fmt);
|
187
|
+
}
|
188
|
+
|
189
|
+
LOG("got all fmt elements\n");
|
190
|
+
final = assemble_fmt(head);
|
191
|
+
fmte_destroy(head);
|
192
|
+
return final;
|
193
|
+
}
|
194
|
+
|
195
|
+
VALUE rb_altprintf(long passes, size_t argc, VALUE *argv, VALUE self)
|
196
|
+
{
|
197
|
+
VALUE fmt, args, hash, final;
|
198
|
+
wchar_t *wfmt;
|
199
|
+
wchar_t *formatted;
|
200
|
+
size_t argi;
|
201
|
+
|
202
|
+
apf_err = apfe_none;
|
203
|
+
rb_scan_args(argc, argv, "1*:", &fmt, &args, &hash);
|
204
|
+
argc--;
|
205
|
+
|
206
|
+
if (hash == Qnil && RB_TYPE_P(argv[argc - 1], T_HASH)) {
|
207
|
+
hash = argv[argc - 1];
|
208
|
+
argc--;
|
209
|
+
}
|
210
|
+
|
211
|
+
if (passes == 0)
|
212
|
+
return fmt;
|
213
|
+
|
214
|
+
wfmt = rbstowcs(fmt);
|
215
|
+
formatted = NULL;
|
216
|
+
|
217
|
+
argi = 0;
|
218
|
+
for (; passes > 0; passes--) {
|
219
|
+
LOG("wfmt: %ls\n", wfmt);
|
220
|
+
|
221
|
+
formatted = rb_apformat(wfmt, argc, &argi, &args, &hash);
|
222
|
+
|
223
|
+
LOG("formatted result: '%ls'\n", formatted);
|
224
|
+
|
225
|
+
free(wfmt);
|
226
|
+
wfmt = formatted;
|
227
|
+
}
|
228
|
+
|
229
|
+
|
230
|
+
LOG("final: '%ls'\n", formatted);
|
231
|
+
final = wcstorbs(formatted);
|
232
|
+
|
233
|
+
free(formatted);
|
234
|
+
|
235
|
+
return final;
|
236
|
+
}
|
237
|
+
|
238
|
+
VALUE rb_altprintf_single_pass(size_t argc, VALUE *argv, VALUE self)
|
239
|
+
{
|
240
|
+
return rb_altprintf(1, argc, argv, self);
|
241
|
+
}
|
242
|
+
|
243
|
+
VALUE rb_altprintf_multi_pass(size_t argc, VALUE *argv, VALUE self)
|
244
|
+
{
|
245
|
+
long passes;
|
246
|
+
|
247
|
+
Check_Type(argv[0], T_FIXNUM);
|
248
|
+
passes = FIX2LONG(argv[0]);
|
249
|
+
if (passes < 0)
|
250
|
+
rb_raise(rb_eArgError, "expected positive number of passes");
|
251
|
+
|
252
|
+
LOG("passes: %ld\n", passes);
|
253
|
+
return rb_altprintf(passes, argc - 1, &argv[1], self);
|
254
|
+
}
|
255
|
+
|
256
|
+
void Init_altprintf()
|
257
|
+
{
|
258
|
+
VALUE mod, ver;
|
259
|
+
size_t len;
|
260
|
+
|
261
|
+
enc = rb_enc_find("UTF-8");
|
262
|
+
mod = rb_define_module(MODNAME);
|
263
|
+
|
264
|
+
len = strlen(ALTPRINTF_VERSION);
|
265
|
+
ver = rb_external_str_new_with_enc(ALTPRINTF_VERSION, len, enc);
|
266
|
+
rb_define_const(mod, "LIB_VERSION", ver);
|
267
|
+
|
268
|
+
rb_define_module_function(mod, "fmt", rb_altprintf_single_pass, -1);
|
269
|
+
rb_define_module_function(mod, "fmtm", rb_altprintf_multi_pass, -1);
|
270
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
|
@@ -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")] + ['ext.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('altprintf')
|
34
|
+
end
|
35
|
+
end
|
data/ext/altprintf/fmt.c
ADDED
@@ -0,0 +1,243 @@
|
|
1
|
+
#include "fmt.h"
|
2
|
+
|
3
|
+
#define BUFNUM 25
|
4
|
+
|
5
|
+
#define CHECKNULL(p) if (p == NULL) { apf_err = apfe_missing_argument; return; }
|
6
|
+
|
7
|
+
enum altprintf_err apf_err;
|
8
|
+
|
9
|
+
void fmt_mul(struct strbuf *sb, struct fmte *f)
|
10
|
+
{
|
11
|
+
CHECKNULL(f->value);
|
12
|
+
|
13
|
+
long *i;
|
14
|
+
|
15
|
+
i = f->value;
|
16
|
+
if (f->parenarg_start == NULL)
|
17
|
+
strbuf_pad(sb, f->chararg, *i);
|
18
|
+
else
|
19
|
+
for (int j = 0; j < *i; j++)
|
20
|
+
strbuf_append_str(sb, f->parenarg_start, -f->parenarg_len);
|
21
|
+
}
|
22
|
+
|
23
|
+
void fmt_tern(struct strbuf *sb, struct fmte *f)
|
24
|
+
{
|
25
|
+
CHECKNULL(f->parenarg_start);
|
26
|
+
CHECKNULL(f->value);
|
27
|
+
|
28
|
+
long int *b = f->value;
|
29
|
+
int first_half = 1;
|
30
|
+
wchar_t sep = f->chararg;
|
31
|
+
wchar_t *p = f->parenarg_start;
|
32
|
+
for (; p <= f->parenarg_end; p++) {
|
33
|
+
LOG("*p: %lc, first half? %d, bool: %ld, sep: %lc\n", (wint_t)*p, first_half, *b, (wint_t)sep);
|
34
|
+
if (*p == sep)
|
35
|
+
first_half = 0;
|
36
|
+
else if (*b && first_half)
|
37
|
+
strbuf_append_char(sb, p);
|
38
|
+
else if (!*b && !first_half)
|
39
|
+
strbuf_append_char(sb, p);
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
wchar_t process_escape_seq(wchar_t seq)
|
44
|
+
{
|
45
|
+
switch (seq) {
|
46
|
+
case FS_ESC_NL:
|
47
|
+
return L'\n';
|
48
|
+
case FS_ESC_ESC:
|
49
|
+
return L'\e';
|
50
|
+
case 'a':
|
51
|
+
return L'\a';
|
52
|
+
case 'b':
|
53
|
+
return L'\b';
|
54
|
+
case 'f':
|
55
|
+
return L'\f';
|
56
|
+
case 'r':
|
57
|
+
return L'\r';
|
58
|
+
case 't':
|
59
|
+
return L'\t';
|
60
|
+
case 'v':
|
61
|
+
return L'\v';
|
62
|
+
default:
|
63
|
+
return seq;
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
67
|
+
void fmt_raw(struct strbuf *sb, struct fmte *f)
|
68
|
+
{
|
69
|
+
CHECKNULL(f->parenarg_start);
|
70
|
+
|
71
|
+
wchar_t *p;
|
72
|
+
wchar_t c;
|
73
|
+
long i;
|
74
|
+
|
75
|
+
p = f->parenarg_start;
|
76
|
+
i = f->parenarg_len;
|
77
|
+
|
78
|
+
for (; i > 0; i--) {
|
79
|
+
LOG("p is '%lc' (%ld)\n", (wint_t)*p, (long)*p);
|
80
|
+
c = (i > 1 && *p == FS_ESC) ? process_escape_seq(*++p) : *p;
|
81
|
+
|
82
|
+
strbuf_append(sb, c);
|
83
|
+
p++;
|
84
|
+
if (*p == EOS)
|
85
|
+
break;
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
void fmt_string(struct strbuf *sb, struct fmte *f)
|
90
|
+
{
|
91
|
+
CHECKNULL(f->value);
|
92
|
+
|
93
|
+
int prec = f->prec == -1 ? 100000000 : f->prec;
|
94
|
+
strbuf_append_str(sb, f->value, prec);
|
95
|
+
}
|
96
|
+
|
97
|
+
void fmt_char(struct strbuf *sb, struct fmte *f)
|
98
|
+
{
|
99
|
+
CHECKNULL(f->value);
|
100
|
+
strbuf_append_char(sb, f->value);
|
101
|
+
}
|
102
|
+
|
103
|
+
void fmt_int(struct strbuf *sb, struct fmte *f)
|
104
|
+
{
|
105
|
+
CHECKNULL(f->value);
|
106
|
+
strbuf_append_int(sb, f->value);
|
107
|
+
}
|
108
|
+
|
109
|
+
void fmt_double(struct strbuf *sb, struct fmte *f)
|
110
|
+
{
|
111
|
+
CHECKNULL(f->value);
|
112
|
+
int prec = f->prec == -1 ? 3 : f->prec;
|
113
|
+
strbuf_append_double(sb, f->value, prec);
|
114
|
+
}
|
115
|
+
|
116
|
+
void fmt(struct strbuf *sb, struct fmte *f, void (*fmtr)(struct strbuf *, struct fmte *))
|
117
|
+
{
|
118
|
+
struct strbuf *tmp = strbuf_new();
|
119
|
+
|
120
|
+
fmtr(tmp, f);
|
121
|
+
|
122
|
+
if (tmp->len == 0) {
|
123
|
+
strbuf_destroy(tmp);
|
124
|
+
return;
|
125
|
+
}
|
126
|
+
|
127
|
+
int pad = f->pad > 0 ? f->pad - strbuf_width(tmp) : 0;
|
128
|
+
|
129
|
+
if (pad > 0) {
|
130
|
+
LOG("padding: %d\n", pad);
|
131
|
+
switch (f->align) {
|
132
|
+
case Right:
|
133
|
+
strbuf_append_strbuf(sb, tmp);
|
134
|
+
strbuf_pad(sb, f->padchar, pad);
|
135
|
+
break;
|
136
|
+
case Left:
|
137
|
+
strbuf_pad(sb, f->padchar, pad);
|
138
|
+
strbuf_append_strbuf(sb, tmp);
|
139
|
+
break;
|
140
|
+
case Center:
|
141
|
+
strbuf_pad(sb, f->padchar, pad / 2);
|
142
|
+
strbuf_append_strbuf(sb, tmp);
|
143
|
+
strbuf_pad(sb, f->padchar, pad / 2 + pad % 2);
|
144
|
+
break;
|
145
|
+
}
|
146
|
+
} else {
|
147
|
+
strbuf_append_strbuf(sb, tmp);
|
148
|
+
}
|
149
|
+
|
150
|
+
strbuf_destroy(tmp);
|
151
|
+
}
|
152
|
+
|
153
|
+
wchar_t *assemble_fmt(struct fmte *head)
|
154
|
+
{
|
155
|
+
struct fmte *f = head;
|
156
|
+
struct strbuf *bufs[BUFNUM];
|
157
|
+
struct fmte *splits[BUFNUM];
|
158
|
+
size_t buf = 0, i;
|
159
|
+
size_t w, tw, rw;
|
160
|
+
wchar_t *final;
|
161
|
+
|
162
|
+
void (*fmtr)(struct strbuf *, struct fmte *) = NULL;
|
163
|
+
int loop = 1;
|
164
|
+
|
165
|
+
bufs[buf] = strbuf_new();
|
166
|
+
|
167
|
+
LOG("assembling elements\n");
|
168
|
+
while (loop) {
|
169
|
+
switch (f->type) {
|
170
|
+
case FMul:
|
171
|
+
fmtr = fmt_mul;
|
172
|
+
break;
|
173
|
+
case FTern:
|
174
|
+
fmtr = fmt_tern;
|
175
|
+
break;
|
176
|
+
case FInt:
|
177
|
+
fmtr = fmt_int;
|
178
|
+
break;
|
179
|
+
case FChar:
|
180
|
+
fmtr = fmt_char;
|
181
|
+
break;
|
182
|
+
case FDouble:
|
183
|
+
fmtr = fmt_double;
|
184
|
+
break;
|
185
|
+
case FString:
|
186
|
+
fmtr = fmt_string;
|
187
|
+
break;
|
188
|
+
case FRaw:
|
189
|
+
fmtr = fmt_raw;
|
190
|
+
break;
|
191
|
+
|
192
|
+
case FAlign:
|
193
|
+
buf++;
|
194
|
+
splits[buf] = f;
|
195
|
+
bufs[buf] = strbuf_new();
|
196
|
+
fmtr = NULL;
|
197
|
+
break;
|
198
|
+
case FEnd:
|
199
|
+
loop = 0;
|
200
|
+
fmtr = NULL;
|
201
|
+
break;
|
202
|
+
case FNone:
|
203
|
+
fmtr = NULL;
|
204
|
+
break;
|
205
|
+
}
|
206
|
+
|
207
|
+
if (fmtr != NULL)
|
208
|
+
fmt(bufs[buf], f, fmtr);
|
209
|
+
f = f->next;
|
210
|
+
}
|
211
|
+
|
212
|
+
// Assemble splits
|
213
|
+
LOG("assembling %d splits\n", buf);
|
214
|
+
if (buf > 0)
|
215
|
+
tw = strbuf_width(bufs[0]);
|
216
|
+
for (i = 1; i <= buf; i++) {
|
217
|
+
rw = *(long*)splits[i]->value;
|
218
|
+
|
219
|
+
if (tw > rw) {
|
220
|
+
LOG("trimming first half to width\n");
|
221
|
+
strbuf_destroy(bufs[i]);
|
222
|
+
bufs[i] = bufs[0];
|
223
|
+
bufs[0] = strbuf_new();
|
224
|
+
strbuf_appendw_strbuf(bufs[0], bufs[i], rw);
|
225
|
+
} else {
|
226
|
+
if (rw > strbuf_width(bufs[i]) + tw) {
|
227
|
+
w = rw - (strbuf_width(bufs[i]) + tw);
|
228
|
+
LOG("padding %d\n", w);
|
229
|
+
strbuf_pad(bufs[0], splits[i]->chararg, w);
|
230
|
+
strbuf_append_strbuf(bufs[0], bufs[i]);
|
231
|
+
} else {
|
232
|
+
LOG("%d %d %d\n", w, rw, tw);
|
233
|
+
strbuf_appendw_strbuf(bufs[0], bufs[i], rw - tw);
|
234
|
+
}
|
235
|
+
}
|
236
|
+
|
237
|
+
tw = rw;
|
238
|
+
}
|
239
|
+
|
240
|
+
final = strbuf_cstr(bufs[0]);
|
241
|
+
for (i = 0; i <= buf; i++) strbuf_destroy(bufs[i]);
|
242
|
+
return final;
|
243
|
+
}
|
data/ext/altprintf/fmt.h
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
#include "fmte.h"
|
2
|
+
|
3
|
+
struct fmte *fmte_ini()
|
4
|
+
{
|
5
|
+
struct fmte *f = malloc(sizeof(struct fmte));
|
6
|
+
|
7
|
+
f->parenarg_start = NULL;
|
8
|
+
f->parenarg_end = NULL;
|
9
|
+
f->parenarg_len = 0;
|
10
|
+
|
11
|
+
f->anglearg_start = NULL;
|
12
|
+
f->anglearg_end = NULL;
|
13
|
+
f->anglearg_len = 0;
|
14
|
+
|
15
|
+
f->chararg = L' ';
|
16
|
+
f->padchar = L' ';
|
17
|
+
f->type = FNone;
|
18
|
+
f->align = Right;
|
19
|
+
f->prec = -1;
|
20
|
+
f->pad = 0;
|
21
|
+
f->value = NULL;
|
22
|
+
|
23
|
+
f->next = NULL;
|
24
|
+
|
25
|
+
return f;
|
26
|
+
}
|
27
|
+
|
28
|
+
void fmte_push(struct fmte *a, struct fmte *b)
|
29
|
+
{
|
30
|
+
if (a == b)
|
31
|
+
return; // refuse to create an infinite loop
|
32
|
+
|
33
|
+
while (a->next != NULL) a = a->next;
|
34
|
+
|
35
|
+
a->next = b;
|
36
|
+
}
|
37
|
+
|
38
|
+
void fmte_destroy(struct fmte *f)
|
39
|
+
{
|
40
|
+
struct fmte *j;
|
41
|
+
|
42
|
+
while (f != NULL) {
|
43
|
+
j = f->next;
|
44
|
+
free(f->value);
|
45
|
+
free(f);
|
46
|
+
f = j;
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
void fmte_inspect(struct fmte *f)
|
51
|
+
{
|
52
|
+
wchar_t *parenarg = calloc(f->parenarg_len + 1, sizeof(wchar_t));
|
53
|
+
wchar_t *anglearg = calloc(f->anglearg_len + 1, sizeof(wchar_t));
|
54
|
+
size_t i;
|
55
|
+
|
56
|
+
for (i = 0; i < f->parenarg_len; i++) parenarg[i] = f->parenarg_start[i];
|
57
|
+
for (i = 0; i < f->anglearg_len; i++) anglearg[i] = f->anglearg_start[i];
|
58
|
+
|
59
|
+
printf(
|
60
|
+
"Format@%p {\n\
|
61
|
+
parenarg_start: %p,\n\
|
62
|
+
parenarg_end: %p,\n\
|
63
|
+
parenarg_len: %ld,\n\
|
64
|
+
(parenarg): %ls,\n\
|
65
|
+
anglearg_start: %p,\n\
|
66
|
+
anglearg_end: %p,\n\
|
67
|
+
anglearg_len: %ld,\n\
|
68
|
+
(anglearg): %ls,\n\
|
69
|
+
chararg: %lc,\n\
|
70
|
+
padchar: %lc,\n\
|
71
|
+
type: %d,\n\
|
72
|
+
align: %d,\n\
|
73
|
+
prec: %ld,\n\
|
74
|
+
pad: %ld,\n\
|
75
|
+
value: %p,\n\
|
76
|
+
next: %p\n\
|
77
|
+
}\n",
|
78
|
+
f,
|
79
|
+
f->parenarg_start,
|
80
|
+
f->parenarg_end,
|
81
|
+
(unsigned long)f->parenarg_len,
|
82
|
+
parenarg,
|
83
|
+
f->anglearg_start,
|
84
|
+
f->anglearg_end,
|
85
|
+
(unsigned long)f->anglearg_len,
|
86
|
+
anglearg,
|
87
|
+
f->chararg,
|
88
|
+
f->padchar,
|
89
|
+
f->type,
|
90
|
+
f->align,
|
91
|
+
f->prec,
|
92
|
+
f->pad,
|
93
|
+
f->value,
|
94
|
+
f->next);
|
95
|
+
|
96
|
+
free(parenarg);
|
97
|
+
free(anglearg);
|
98
|
+
}
|
@@ -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/altprintf/log.h
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#ifndef LOG_H
|
2
|
+
#define LOG_H
|
3
|
+
|
4
|
+
#ifdef DEBUG
|
5
|
+
#define LOG(...) printf("%s:%d [\e[35m%s\e[0m] ", __FILE__, __LINE__, __func__); printf(__VA_ARGS__);
|
6
|
+
#define FLOG(msg, ...) fprintf(stderr, "%s[%d] - "msg, __FILE__, __LINE__ __VA_OPT__(, ) __VA_ARGS__)
|
7
|
+
#else
|
8
|
+
#define LOG(msg, ...)
|
9
|
+
#define FLOG(msg, ...)
|
10
|
+
#endif
|
11
|
+
|
12
|
+
#endif
|
@@ -0,0 +1,127 @@
|
|
1
|
+
#include "parsef.h"
|
2
|
+
|
3
|
+
wchar_t *altprintf_pct = L"%";
|
4
|
+
|
5
|
+
struct fmte *parsef(wchar_t **fmt)
|
6
|
+
{
|
7
|
+
wchar_t *w_c;
|
8
|
+
wchar_t **w_a = &w_c;
|
9
|
+
struct fmte *f = fmte_ini();
|
10
|
+
long *l_a = &f->pad;
|
11
|
+
|
12
|
+
LOG("processing %ld (%lc)\n", **fmt, (wint_t)**fmt);
|
13
|
+
|
14
|
+
if (**fmt != FS_START) {
|
15
|
+
if (**fmt == EOS) {
|
16
|
+
f->type = FEnd;
|
17
|
+
goto return_format;
|
18
|
+
}
|
19
|
+
|
20
|
+
LOG("building raw format\n");
|
21
|
+
f->type = FRaw;
|
22
|
+
|
23
|
+
f->parenarg_start = *fmt;
|
24
|
+
LOG("scanning long arg\n");
|
25
|
+
get_longarg(fmt, &f->parenarg_end, FS_START, &f->parenarg_len);
|
26
|
+
|
27
|
+
f->parenarg_end++;
|
28
|
+
f->parenarg_len++;
|
29
|
+
(*fmt)--;
|
30
|
+
|
31
|
+
goto return_format;
|
32
|
+
} else {
|
33
|
+
LOG("building format\n");
|
34
|
+
(*fmt)++;
|
35
|
+
}
|
36
|
+
|
37
|
+
for (; **fmt != L'\0'; (*fmt)++) {
|
38
|
+
LOG("scanned char '%lc'\n", (wint_t)(**fmt));
|
39
|
+
switch (**fmt) {
|
40
|
+
case FS_A_CHARARG:
|
41
|
+
(*fmt)++;
|
42
|
+
f->chararg = **fmt;
|
43
|
+
break;
|
44
|
+
case FS_A_ANGLEARG_S:
|
45
|
+
f->anglearg_start = *fmt + 1;
|
46
|
+
get_longarg(fmt, &f->anglearg_end, FS_A_ANGLEARG_E, &f->anglearg_len);
|
47
|
+
break;
|
48
|
+
case FS_A_PARENARG_S:
|
49
|
+
f->parenarg_start = *fmt + 1;
|
50
|
+
get_longarg(fmt, &f->parenarg_end, FS_A_PARENARG_E, &f->parenarg_len);
|
51
|
+
break;
|
52
|
+
case FS_A_LALIGN:
|
53
|
+
f->align = Left;
|
54
|
+
break;
|
55
|
+
case FS_A_CALIGN:
|
56
|
+
f->align = Center;
|
57
|
+
break;
|
58
|
+
case FS_A_SPAD:
|
59
|
+
f->padchar = FS_A_SPAD;
|
60
|
+
break;
|
61
|
+
case FS_A_ZPAD:
|
62
|
+
f->padchar = '0';
|
63
|
+
break;
|
64
|
+
case FS_A_PREC:
|
65
|
+
l_a = &f->prec;
|
66
|
+
break;
|
67
|
+
case '1': case '2': case '3': case '4': case '5':
|
68
|
+
case '6': case '7': case '8': case '9':
|
69
|
+
LOG("l_a: %p %ld\n", l_a, *l_a);
|
70
|
+
*l_a = wcstol(*fmt, w_a, 10);
|
71
|
+
*fmt = *w_a - 1;
|
72
|
+
break;
|
73
|
+
// Psuedo-type
|
74
|
+
case FS_START:
|
75
|
+
f->type = FRaw;
|
76
|
+
f->parenarg_start = &altprintf_pct[0];
|
77
|
+
f->parenarg_end = &altprintf_pct[1];
|
78
|
+
f->parenarg_len = 1;
|
79
|
+
goto return_format;
|
80
|
+
// Types
|
81
|
+
case FS_T_STRING:
|
82
|
+
f->type = FString;
|
83
|
+
goto return_format;
|
84
|
+
case FS_T_MUL:
|
85
|
+
f->type = FMul;
|
86
|
+
goto return_format;
|
87
|
+
case FS_T_TERN:
|
88
|
+
f->type = FTern;
|
89
|
+
goto return_format;
|
90
|
+
case FS_T_ALIGN:
|
91
|
+
f->type = FAlign;
|
92
|
+
goto return_format;
|
93
|
+
case FS_T_INT:
|
94
|
+
f->type = FInt;
|
95
|
+
goto return_format;
|
96
|
+
case FS_T_CHAR:
|
97
|
+
f->type = FChar;
|
98
|
+
goto return_format;
|
99
|
+
case FS_T_DOUBLE:
|
100
|
+
f->type = FDouble;
|
101
|
+
goto return_format;
|
102
|
+
default:
|
103
|
+
apf_err = apfe_invalid_token;
|
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
|
+
{
|
116
|
+
*size = 0;
|
117
|
+
|
118
|
+
while (**s != EOS && **s != stop) {
|
119
|
+
LOG("checking (%lc)\n", (wint_t)**s);
|
120
|
+
(*s)++;
|
121
|
+
(*size)++;
|
122
|
+
}
|
123
|
+
|
124
|
+
(*size)--;
|
125
|
+
if (*size > 0)
|
126
|
+
*e = *s - 1;
|
127
|
+
}
|
@@ -0,0 +1,178 @@
|
|
1
|
+
#include "strbuf.h"
|
2
|
+
|
3
|
+
extern struct lconv *locale_info;
|
4
|
+
|
5
|
+
struct strbuf *strbuf_new()
|
6
|
+
{
|
7
|
+
struct strbuf *sb = malloc(sizeof(struct strbuf));
|
8
|
+
|
9
|
+
if (NULL == sb) {
|
10
|
+
LOG("can't alloc memory for new strbuf\n");
|
11
|
+
exit(1);
|
12
|
+
}
|
13
|
+
|
14
|
+
sb->start = sb->end = calloc(STRBUF_INI_SIZE, sizeof(wchar_t));
|
15
|
+
|
16
|
+
if (NULL == sb->start) {
|
17
|
+
LOG("can't alloc memory for new strbuf string\n");
|
18
|
+
exit(1);
|
19
|
+
}
|
20
|
+
|
21
|
+
sb->len = 0;
|
22
|
+
sb->cap = STRBUF_INI_SIZE;
|
23
|
+
sb->width = 0;
|
24
|
+
return sb;
|
25
|
+
}
|
26
|
+
|
27
|
+
size_t strbuf_width(struct strbuf *sb)
|
28
|
+
{
|
29
|
+
if (sb->width == 0)
|
30
|
+
sb->width = wcswidth(sb->start, sb->len);
|
31
|
+
|
32
|
+
return sb->width;
|
33
|
+
}
|
34
|
+
|
35
|
+
void strbuf_destroy(struct strbuf *sb)
|
36
|
+
{
|
37
|
+
free(sb->start);
|
38
|
+
free(sb);
|
39
|
+
}
|
40
|
+
|
41
|
+
void strbuf_append(struct strbuf *sb, wchar_t c)
|
42
|
+
{
|
43
|
+
wchar_t *ns;
|
44
|
+
|
45
|
+
if (sb->cap < sb->len + 2) {
|
46
|
+
ns = calloc(sb->cap + STRBUF_GROW_STEP, sizeof(wchar_t));
|
47
|
+
|
48
|
+
if (ns == NULL) {
|
49
|
+
LOG("can't increase size of strbuf to %d\n", sb->cap + STRBUF_GROW_STEP);
|
50
|
+
exit(1);
|
51
|
+
}
|
52
|
+
|
53
|
+
wcscpy(ns, sb->start);
|
54
|
+
free(sb->start);
|
55
|
+
|
56
|
+
sb->start = ns;
|
57
|
+
sb->cap += STRBUF_GROW_STEP;
|
58
|
+
}
|
59
|
+
|
60
|
+
sb->start[sb->len] = c;
|
61
|
+
sb->start[sb->len + 1] = L'\0';
|
62
|
+
LOG("string so far: %ls\n", sb->start);
|
63
|
+
sb->end = &sb->start[sb->len];
|
64
|
+
sb->len++;
|
65
|
+
}
|
66
|
+
|
67
|
+
void strbuf_append_strbuf(struct strbuf *sb, void *sbuf)
|
68
|
+
{
|
69
|
+
wchar_t *pos;
|
70
|
+
struct strbuf *frm = sbuf;
|
71
|
+
|
72
|
+
LOG("frm->start: %p | frm->end: %p\n", frm->start, frm->end);
|
73
|
+
|
74
|
+
for (pos = frm->start; pos <= frm->end; pos++)
|
75
|
+
strbuf_append(sb, *pos);
|
76
|
+
}
|
77
|
+
|
78
|
+
void strbuf_appendw_strbuf(struct strbuf *sb, void *sbuf, long w)
|
79
|
+
{
|
80
|
+
wchar_t *pos;
|
81
|
+
long ws = 0;
|
82
|
+
struct strbuf *frm = sbuf;
|
83
|
+
|
84
|
+
LOG("frm->start: %p | frm->end: %p\n", frm->start, frm->end);
|
85
|
+
|
86
|
+
for (pos = frm->start; pos <= frm->end; pos++) {
|
87
|
+
ws += wcwidth(*pos);
|
88
|
+
LOG("new width would be: %ld, requested width: %ld\n", ws, w);
|
89
|
+
if (ws > w)
|
90
|
+
break;
|
91
|
+
strbuf_append(sb, *pos);
|
92
|
+
}
|
93
|
+
}
|
94
|
+
|
95
|
+
void strbuf_append_char(struct strbuf *sb, void *chr)
|
96
|
+
{
|
97
|
+
wint_t *c = chr;
|
98
|
+
|
99
|
+
strbuf_append(sb, *c);
|
100
|
+
}
|
101
|
+
|
102
|
+
void strbuf_append_str(struct strbuf *sb, void *str, int maxwidth)
|
103
|
+
{
|
104
|
+
wchar_t *s = str;
|
105
|
+
wchar_t *end = &s[wcslen(s)];
|
106
|
+
int width = 0;
|
107
|
+
int maxlen = -1;
|
108
|
+
|
109
|
+
if (maxwidth < 0)
|
110
|
+
maxlen = maxwidth * -1;
|
111
|
+
|
112
|
+
for (; s < end; s++) {
|
113
|
+
if (maxlen >= 0) {
|
114
|
+
width++;
|
115
|
+
if (width > maxlen)
|
116
|
+
return;
|
117
|
+
} else {
|
118
|
+
width += wcwidth(*s);
|
119
|
+
if (width > maxwidth)
|
120
|
+
return;
|
121
|
+
}
|
122
|
+
|
123
|
+
strbuf_append(sb, *s);
|
124
|
+
}
|
125
|
+
}
|
126
|
+
|
127
|
+
void strbuf_append_int(struct strbuf *sb, void *in)
|
128
|
+
{
|
129
|
+
long int *i = in;
|
130
|
+
wchar_t wcs[TMPLEN];
|
131
|
+
long len = swprintf(wcs, TMPLEN - 1, L"%ld", *i);
|
132
|
+
|
133
|
+
if (len < 0)
|
134
|
+
strbuf_append_str(sb, L"error adding int", 16);
|
135
|
+
else
|
136
|
+
strbuf_append_str(sb, wcs, -1 * len);
|
137
|
+
}
|
138
|
+
|
139
|
+
void strbuf_append_double(struct strbuf *sb, void *dub, int prec)
|
140
|
+
{
|
141
|
+
double *d = dub;
|
142
|
+
wchar_t wcs[TMPLEN];
|
143
|
+
wchar_t format[TMPLEN];
|
144
|
+
int rprec = prec;
|
145
|
+
|
146
|
+
if (rprec > MAXPREC)
|
147
|
+
rprec = MAXPREC;
|
148
|
+
|
149
|
+
swprintf(format, TMPLEN - 1, L"%%.%ldf", rprec);
|
150
|
+
|
151
|
+
LOG("format: %ls\n", format);
|
152
|
+
|
153
|
+
long len = swprintf(wcs, TMPLEN - 1, format, *d);
|
154
|
+
if (len < 0) {
|
155
|
+
strbuf_append_str(sb, L"error adding float", 18);
|
156
|
+
} else {
|
157
|
+
LOG("inserting double: len: %ld\n", len);
|
158
|
+
strbuf_append_str(sb, wcs, len);
|
159
|
+
|
160
|
+
if (rprec < prec)
|
161
|
+
strbuf_pad(sb, L'0', rprec - prec);
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
165
|
+
void strbuf_pad(struct strbuf *sb, wchar_t pc, int amnt)
|
166
|
+
{
|
167
|
+
for (; amnt > 0; amnt--) strbuf_append(sb, pc);
|
168
|
+
}
|
169
|
+
|
170
|
+
wchar_t *strbuf_cstr(struct strbuf *sb)
|
171
|
+
{
|
172
|
+
wchar_t *str;
|
173
|
+
|
174
|
+
str = calloc(sb->len + 1, sizeof(wchar_t));
|
175
|
+
wcscpy(str, sb->start);
|
176
|
+
|
177
|
+
return str;
|
178
|
+
}
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#ifndef STRBUF_H
|
2
|
+
#define STRBUF_H
|
3
|
+
|
4
|
+
#ifndef _XOPEN_SOURCE
|
5
|
+
#define _XOPEN_SOURCE
|
6
|
+
#endif
|
7
|
+
|
8
|
+
#include <wchar.h>
|
9
|
+
#include <stdlib.h>
|
10
|
+
#include <stdio.h>
|
11
|
+
#include "log.h"
|
12
|
+
|
13
|
+
#define STRBUF_INI_SIZE 5
|
14
|
+
#define STRBUF_GROW_STEP 100
|
15
|
+
#define TMPLEN 50
|
16
|
+
#define MAXPREC 25
|
17
|
+
|
18
|
+
struct strbuf *strbuf_new();
|
19
|
+
void strbuf_destroy(struct strbuf *sb);
|
20
|
+
void strbuf_append(struct strbuf *sb, wchar_t);
|
21
|
+
void strbuf_append_char(struct strbuf *sb, void *);
|
22
|
+
void strbuf_append_str(struct strbuf *, void *, int);
|
23
|
+
void strbuf_append_int(struct strbuf *sb, void *);
|
24
|
+
void strbuf_append_double(struct strbuf *, void *, int);
|
25
|
+
void strbuf_append_strbuf(struct strbuf *, void *);
|
26
|
+
void strbuf_appendw_strbuf(struct strbuf *, void *, long);
|
27
|
+
void strbuf_pad(struct strbuf *, wchar_t, int);
|
28
|
+
wchar_t *strbuf_cstr(struct strbuf *);
|
29
|
+
size_t strbuf_width(struct strbuf *);
|
30
|
+
|
31
|
+
struct strbuf {
|
32
|
+
wchar_t *start;
|
33
|
+
wchar_t *end;
|
34
|
+
size_t len;
|
35
|
+
size_t width;
|
36
|
+
size_t cap;
|
37
|
+
};
|
38
|
+
#endif
|
@@ -0,0 +1,35 @@
|
|
1
|
+
#ifndef SYNTAX_H
|
2
|
+
#define SYNTAX_H
|
3
|
+
|
4
|
+
#define FS_START '%'
|
5
|
+
#define FS_DOUBLE_SEP '.'
|
6
|
+
|
7
|
+
#define FS_ESC L'\\'
|
8
|
+
#define FS_ESC_NL 'n'
|
9
|
+
#define FS_ESC_ESC 'e'
|
10
|
+
|
11
|
+
#define FS_T_STRING 's'
|
12
|
+
#define FS_T_CHAR 'c'
|
13
|
+
#define FS_T_DOUBLE 'f'
|
14
|
+
#define FS_T_INT 'd'
|
15
|
+
#define FS_T_MUL '*'
|
16
|
+
#define FS_T_TERN '?'
|
17
|
+
#define FS_T_ALIGN '='
|
18
|
+
|
19
|
+
#define FS_A_PARENARG_S '('
|
20
|
+
#define FS_A_PARENARG_E ')'
|
21
|
+
#define FS_A_ANGLEARG_S '<'
|
22
|
+
#define FS_A_ANGLEARG_E '>'
|
23
|
+
|
24
|
+
#define FS_A_CHARARG '~'
|
25
|
+
#define FS_A_LALIGN '-'
|
26
|
+
#define FS_A_CALIGN '^'
|
27
|
+
#define FS_A_SPAD ' '
|
28
|
+
#define FS_A_ZPAD '0'
|
29
|
+
#define FS_A_PREC '.'
|
30
|
+
|
31
|
+
#define FS_D_PREC 100
|
32
|
+
|
33
|
+
#define EOS L'\0'
|
34
|
+
|
35
|
+
#endif
|
data/lib/altprintf.rb
ADDED
Binary file
|
Binary file
|
data/readme.md
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# Altprintf
|
2
|
+
|
3
|
+
[rubygems.org/gems/altprintf](https://rubygems.org/gems/altprintf)
|
4
|
+
|
5
|
+
altprintf is a gem that wraps `../altprintf`.
|
6
|
+
|
7
|
+
It exposes the following module functions
|
8
|
+
|
9
|
+
+ `Altprintf#fmt(format_string, *args, **kwargs)`
|
10
|
+
+ `Altprintf#fmtm(passes, format_string, *args, **kwargs)`
|
11
|
+
|
12
|
+
In addition to the syntax of vanilla altprintf, the following additional
|
13
|
+
argument is accepted:
|
14
|
+
|
15
|
+
+ `<val>` - access the value of the given hash with key `val` rather than
|
16
|
+
try to read the next argument.
|
metadata
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: altprintf
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Stone Tickle
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-08-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake-compiler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '12.3'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '12.3'
|
41
|
+
description:
|
42
|
+
email: lattis@mochiro.moe
|
43
|
+
executables: []
|
44
|
+
extensions: []
|
45
|
+
extra_rdoc_files: []
|
46
|
+
files:
|
47
|
+
- altprintf.gemspec
|
48
|
+
- ext/altprintf/altprintf.h
|
49
|
+
- ext/altprintf/enums.h
|
50
|
+
- ext/altprintf/ext.c
|
51
|
+
- ext/altprintf/extconf.h
|
52
|
+
- ext/altprintf/extconf_helper.rb
|
53
|
+
- ext/altprintf/fmt.c
|
54
|
+
- ext/altprintf/fmt.h
|
55
|
+
- ext/altprintf/fmte.c
|
56
|
+
- ext/altprintf/fmte.h
|
57
|
+
- ext/altprintf/log.h
|
58
|
+
- ext/altprintf/parsef.c
|
59
|
+
- ext/altprintf/parsef.h
|
60
|
+
- ext/altprintf/strbuf.c
|
61
|
+
- ext/altprintf/strbuf.h
|
62
|
+
- ext/altprintf/syntax.h
|
63
|
+
- lib/altprintf.rb
|
64
|
+
- lib/altprintf/alt_printf.so
|
65
|
+
- lib/altprintf/altprintf.so
|
66
|
+
- lib/altprintf/version.rb
|
67
|
+
- readme.md
|
68
|
+
homepage: https://github.com/annacrombie/altprintf/tree/master/gem
|
69
|
+
licenses:
|
70
|
+
- MIT
|
71
|
+
metadata: {}
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options: []
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: 2.5.5
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
requirements: []
|
87
|
+
rubygems_version: 3.0.3
|
88
|
+
signing_key:
|
89
|
+
specification_version: 4
|
90
|
+
summary: A powerful printf-like template language
|
91
|
+
test_files: []
|