/*
 * ABOUTME: Shared infrastructure for TXT-like DNS resource records.
 * ABOUTME: Provides parsing, formatting, and wire format generation for character-string based RR types.
 *
 * Part of DNS zone file validator `validns`.
 *
 * Copyright 2025-2026 OARC, Inc.
 * Copyright 2011-2025 Anton Berezin <tobez@tobez.org>
 * Modified BSD license.
 * (See LICENSE file in the distribution.)
 *
 */
#include <sys/types.h>
#include <string.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "common.h"
#include "textparse.h"
#include "mempool.h"
#include "carp.h"
#include "rr.h"
#include "txtlike.h"

struct rr *txtlike_parse(char *name, long ttl, int type, char *s, const char *type_name)
{
    struct rr_txtlike *rr;
    struct binary_data txt;
    struct rr_txtlike_segment *first = NULL;
    struct rr_txtlike_segment *last  = NULL;
    struct rr_txtlike_segment *cur   = NULL;
    int i;

    i = 0;
    while (*s) {
        freeall_temp();
        txt = extract_text(&s, "text segment");
        if (txt.length < 0)
            return NULL;
        if (txt.length > 255)
            return bitch("%s segment too long", type_name);
        i++;
        cur = getmem(sizeof(*cur));
        cur->txt = txt;
        cur->next = NULL;
        if (!first)
            first = cur;
        if (last)
            last->next = cur;
        last = cur;
    }
    if (i == 0)
        return bitch("empty %s record", type_name);

    rr = getmem(sizeof(*rr));
    rr->count = i;
    rr->txt = first;

    return store_record(type, name, ttl, rr);
}

char *txtlike_human(struct rr *rrv)
{
    RRCAST(txtlike);
    char ss[1024];
    char *s = ss;
    int l;
    struct rr_txtlike_segment *seg = rr->txt;

    while (seg) {
        l = snprintf(s, 1024-(s-ss), "\"%s\" ", seg->txt.data);
        s += l;
        seg = seg->next;
    }
    return quickstrdup_temp(ss);
}

struct binary_data txtlike_wirerdata(struct rr *rrv)
{
    RRCAST(txtlike);
    struct binary_data r, t;
    struct rr_txtlike_segment *seg = rr->txt;

    r = bad_binary_data();
    t.length = 0;
    t.data = NULL;
    while (seg) {
        r = compose_binary_data("db", 1, t, seg->txt);
        t = r;
        seg = seg->next;
    }
    return r;
}
