+ssize_t query_format(char *dest, size_t len, const char *fmt, const query_t *query)
+{
+ size_t written = 0;
+ size_t pos = 0;
+
+#define WRITE(Src, Len) \
+ do { \
+ size_t __len = (Len); \
+ if (written < len) { \
+ size_t __to_write = MIN(len - written - 1, __len); \
+ memcpy(dest + written, (Src), __to_write); \
+ written += __to_write; \
+ } \
+ pos += __len; \
+ } while (0)
+ while (*fmt != '\0') {
+ const char *next_format = strchr(fmt, '$');
+ while (next_format != NULL && next_format[1] != '{') {
+ next_format = strchr(next_format + 1, '$');
+ }
+ if (next_format == NULL) {
+ next_format = fmt + m_strlen(fmt);
+ }
+ WRITE(fmt, next_format - fmt);
+ fmt = next_format;
+ if (*fmt != '\0') {
+ fmt += 2;
+ next_format = strchr(fmt, '}');
+ if (next_format == NULL) {
+ return -1;
+ }
+
+ postlicyd_token tok = policy_tokenize(fmt, next_format - fmt);
+ if (tok == PTK_UNKNOWN) {
+ warn("unknown field name \"%.*s\"", (int)(next_format - fmt), fmt);
+ }
+ const static_str_t *field = query == NULL ? NULL
+ : query_field_for_id(query, tok);
+ if (field == NULL) {
+ WRITE("(null)", 6);
+ } else {
+ WRITE(field->str, field->len);
+ }
+ fmt = next_format + 1;
+ }
+ }
+
+ if (written > 0 && len > 0) {
+ dest[written] = '\0';
+ }
+ return pos;
+}
+
+bool query_format_buffer(buffer_t *buf, const char *fmt, const query_t *query)
+{
+ buffer_ensure(buf, m_strlen(fmt) + 64);
+
+ ssize_t size = array_free_space(*buf);
+ ssize_t format_size = query_format(array_end(*buf),
+ size, fmt, query);
+ if (format_size == -1) {
+ return false;
+ } else if (format_size > size) {
+ buffer_ensure(buf, format_size + 1);
+ query_format(array_end(*buf),
+ array_free_space(*buf),
+ fmt, query);
+ array_len(*buf) += format_size;
+ } else {
+ array_len(*buf) += format_size;
+ }
+ return true;
+}