/*
 * 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);
    struct rr_txtlike_segment* seg    = rr->txt;
    char**                     quoted = getmem_temp(rr->count * sizeof(*quoted));
    int                        n      = 0;
    size_t                     total  = 0;
    char*                      s;
    char*                      p;

    while (seg) {
        quoted[n] = text2str(seg->txt);
        total += strlen(quoted[n]);
        n++;
        seg = seg->next;
    }
    total += n - 1; /* separating spaces */

    p = s = getmem_temp(total + 1);
    for (int i = 0; i < n; i++) {
        if (i > 0)
            *p++ = ' ';
        p = mystpcpy(p, quoted[i]);
    }
    *p = '\0';
    return s;
}

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;
}
