#define UNUSED __attribute__((__unused__))
#define PACKED __attribute__((__packed__))
#define PRINTF_FORMAT(FMT, ARG1) __attribute__((__format__(printf, FMT, ARG1)))
+#define STRFTIME_FORMAT(FMT) __attribute__((__format__(__strftime__, FMT, 0)))
#define likely(x) __builtin_expect((x),1)
#define unlikely(x) __builtin_expect((x),0)
#include <stdint.h>
#include "compiler.h"
+struct tm;
+
struct ds {
char *string; /* Null-terminated string. */
size_t length; /* Bytes used, not including null terminator. */
void ds_put_format_valist(struct ds *, const char *, va_list)
PRINTF_FORMAT(2, 0);
void ds_put_printable(struct ds *, const char *, size_t);
+void ds_put_strftime(struct ds *, const char *, const struct tm *)
+ STRFTIME_FORMAT(2);
void ds_put_hex_dump(struct ds *ds, const void *buf_, size_t size,
uintptr_t ofs, bool ascii);
char *ds_cstr(struct ds *);
void ds_destroy(struct ds *);
int ds_last(const struct ds *);
+void ds_chomp(struct ds *, int c);
#endif /* dynamic-string.h */
#include <assert.h>
#include <stdlib.h>
#include <string.h>
+#include <time.h>
#include "util.h"
void
}
}
+void
+ds_put_strftime(struct ds *ds, const char *template, const struct tm *tm)
+{
+ for (;;) {
+ size_t avail = ds->string ? ds->allocated - ds->length + 1 : 0;
+ size_t used = strftime(&ds->string[ds->length], avail, template, tm);
+ if (used) {
+ ds->length += used;
+ return;
+ }
+ ds_reserve(ds, ds->length + (avail < 32 ? 64 : 2 * avail));
+ }
+}
+
char *
ds_cstr(struct ds *ds)
{
{
return ds->length > 0 ? (unsigned char) ds->string[ds->length - 1] : EOF;
}
+
+void
+ds_chomp(struct ds *ds, int c)
+{
+ if (ds->length > 0 && ds->string[ds->length - 1] == (char) c) {
+ ds->string[--ds->length] = '\0';
+ }
+}