2 * Behaves as gmp_printf with new conversion specifier %B for element_t types
6 #include <stdint.h> // for intptr_t
11 #include "pbc_utils.h"
12 #include "pbc_field.h"
13 #include "pbc_memory.h"
22 // TODO: remove repeated code for error handling
23 static int do_print(int(*strcb
)(void *, char *s
),
24 int (*fstrcb
)(void *, char *s
, void *),
25 int(*elcb
)(void *, element_ptr e
),
27 const char *format
, va_list ap
) {
28 // A primitive front-end for printf()-family functions. Only handles types
29 // in specifiers, and assumes they all take void * arguments.
31 // I wish register_printf_specifier() were more widespread.
33 int count
= 0, status
;
34 char *copy
, *c
, *start
, *next
;
38 copy
= pbc_strdup(format
);
43 c
= strchr(next
, '%');
45 status
= strcb(data
, start
);
48 } else count
+= status
;
51 if (!*(c
+ 1)) goto done
;
52 if (*(c
+ 1) != '%') break;
56 status
= strcb(data
, start
);
60 } else count
+= status
;
70 e
= va_arg(ap
, element_ptr
);
71 status
= elcb(data
, e
);
75 } else count
+= status
;
79 if (strchr("diouxXeEfFgGaAcspnmZ", *c
)) {
83 status
= fstrcb(data
, start
, va_arg(ap
, void *));
87 } else count
+= status
;
103 static int string_cb(void *file
, char *s
) {
104 if (fputs(s
, file
) == EOF
) return -1;
105 return (int)strlen(s
);
108 static int format_cb(void *file
, char *fstring
, void *ptr
) {
109 return gmp_fprintf(file
, fstring
, ptr
);
112 static int element_cb(void *file
, element_ptr e
) {
113 return (int)element_out_str(file
, 0, e
);
116 int element_vfprintf(FILE *stream
, const char *format
, va_list ap
) {
117 return do_print(string_cb
, format_cb
, element_cb
, stream
, format
, ap
);
120 int element_fprintf(FILE *stream
, const char *format
, ...) {
124 va_start(ap
, format
);
125 status
= element_vfprintf(stream
, format
, ap
);
130 int element_printf(const char *format
, ...) {
134 va_start(ap
, format
);
135 status
= element_vfprintf(stdout
, format
, ap
);
140 static void next(struct sninfo_s
*p
, int status
) {
142 p
->left
= p
->result
>= p
->size
? 0 : p
->size
- p
->result
;
145 static int string_cbv(void *data
, char *s
) {
146 struct sninfo_s
*p
= data
;
147 int status
= snprintf(p
->s
+ p
->result
, p
->left
, "%s", s
);
148 if (status
< 0) return status
;
153 static int format_cbv(void *data
, char *fstring
, void *ptr
) {
154 struct sninfo_s
*p
= data
;
155 int status
= gmp_snprintf(p
->s
+ p
->result
, p
->left
, fstring
, ptr
);
156 if (status
< 0) return status
;
161 static int element_cbv(void *data
, element_ptr e
) {
162 struct sninfo_s
*p
= data
;
163 int status
= element_snprint(p
->s
+ p
->result
, p
->left
, e
);
164 if (status
< 0) return status
;
169 int element_vsnprintf(char *buf
, size_t size
, const char *fmt
, va_list ap
) {
170 struct sninfo_s info
;
173 info
.left
= info
.size
= size
;
176 do_print(string_cbv
, format_cbv
, element_cbv
, &info
, fmt
, ap
);
178 return (int)info
.result
;
181 int element_snprintf(char *buf
, size_t size
, const char *fmt
, ...) {
186 status
= element_vsnprintf(buf
, size
, fmt
, ap
);