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