/* GNU Mailutils -- a suite of utilities for electronic mail
   Copyright (C) 2025 Free Software Foundation, Inc.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 3 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General
   Public License along with this library.  If not, see
   <http://www.gnu.org/licenses/>. */

#include <config.h>
#include <stdlib.h>
#include <string.h>
#include <mailutils/cstr.h>
#include <mailutils/util.h>

struct quotename
{
  char *alloc_buf;                      /* Dynamically allocated buffer. */
  size_t alloc_size;                    /* Size of alloc_buf. */
  char stat_buf[MU_QUOTENAME_SIZE_MAX]; /* Static buffer. */
};

static struct quotename quotetab[MU_QUOTENAME_IDX_MAX];

static int
quotename_realloc (struct quotename *q, size_t n)
{
  if (q->alloc_size < n)
    {
      char *p = realloc (q->alloc_buf, n);
      if (!p)
	return -1;
      q->alloc_buf = p;
      q->alloc_size = n;
    }
  return 0;
}

/*
 * Encloses NAME in a pair of double-quotes, escaping each occurrence of
 * " and \ with backslashes.  N gives the number of slot where to store the
 * quoted string.  There are MU_QUOTENAME_IDX_MAX slots available.
 *
 * The function always returns a non-NULL value.  It tries to use static
 * buffer, if the resulting string does not overflow it (the buffer is
 * MU_QUOTENAME_SIZE_MAX bytes long).  Otherwise, if overflow occurs, an
 * attempt to allocate dynamic memory is made.  If that is not possible,
 * a truncated string is left in the static storage and the fact is indicated
 * by replacing last three characters in it by dots.
 */
char const *
mu_quotename_n (int n, char const *name)
{
  struct quotename *q;
  char const *end;
  size_t len;

  if (n < 0 || n >= MU_QUOTENAME_IDX_MAX)
    return "INTERNAL ERROR: bad quotename index; please report!";

  q = quotetab + n;
  q->stat_buf[0] = '"';
  len = mu_c_str_escape_buf (name, "\\\"", NULL,
			     q->stat_buf + 1, sizeof (q->stat_buf) - 1,
			     &end);
  if (len < sizeof (q->stat_buf) - 3)
    {
      q->stat_buf[++len] = '"';
      q->stat_buf[++len] = 0;
      return q->stat_buf;
    }
  else if (quotename_realloc (q, len + 3) == 0)
    {
      char *p = mu_stpcpy (q->alloc_buf, q->stat_buf);
      if (len >= sizeof (q->stat_buf) - 1)
	mu_c_str_escape_buf (end, "\\\"", NULL,
			     p, q->alloc_size - (p - q->alloc_buf),
			     NULL);
      q->alloc_buf[++len] = '"';
      q->alloc_buf[++len] = 0;
      return q->alloc_buf;
    }
  else
    {
      strcpy (q->stat_buf + sizeof (q->stat_buf) - 5, "...\"");
      return q->stat_buf;
    }
}
