/*
 *  $Id: file--make-key.c 29826 2026-04-16 18:08:14Z yeti-dn $
 *  Copyright (C) 2025 David Necas (Yeti).
 *  E-mail: yeti@gwyddion.net.
 *
 *  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public
 *  License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any
 *  later version.
 *
 *  This program 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 General Public License for more
 *  details.
 *
 *  You should have received a copy of the GNU General Public License along with this program; if not, write to the
 *  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "config.h"
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>

#include "libgwyapp/file.h"

#define gwy_strlen0(s) (s ? strlen(s) : 0)

static guint
append_uint(gchar *buf, guint u)
{
    static const gchar digits[11] = "0123456789";

    guint len = 0;
    do {
        buf[len++] = digits[u % 10];
        u /= 10;
    } while (u);

    for (guint i = 0; i < len/2; i++)
        GWY_SWAP(gchar, buf[i], buf[len-1 - i]);

    return len;
}

static GQuark
make_key_for_id(gint id, const gchar *prefix, const gchar *suffix)
{
    g_return_val_if_fail(id >= 0, 0);

    guint plen = strlen(prefix), slen = gwy_strlen0(suffix);
    gchar key[plen + slen + 12];
    memcpy(key, prefix, plen);

    /* An implied ‘/’ at the beginning of the numeric part. Count it to plen to simplify subsequent artihmetic. */
    key[plen++] = '/';
    guint numlen = append_uint(key + plen, id);

    if (slen)
        memcpy(key + plen + numlen, suffix, slen+1);
    else
        key[plen + numlen] = '\0';

    return g_quark_from_string(key);
}

/**
 * gwy_file_key_filename:
 *
 * Returns the file name quark identifier.
 *
 * Returns: The quark key identifying the file name.
 **/
GQuark
gwy_file_key_filename(void)
{
    return g_quark_from_static_string("/filename");
}

/**
 * gwy_file_key_data:
 * @data_kind: Type of data item.
 * @id: Numerical id of a data item in file.
 *
 * Constructs the quark identifier for a data kind and numerical id.
 *
 * Returns: The quark key identifying the data.
 **/
GQuark
gwy_file_key_data(GwyDataKind data_kind,
                  gint id)
{
    if (data_kind == GWY_FILE_IMAGE)
        return make_key_for_id(id, GWY_FILE_PREFIX_IMAGE, NULL);
    if (data_kind == GWY_FILE_GRAPH)
        return make_key_for_id(id, GWY_FILE_PREFIX_GRAPH, NULL);
    if (data_kind == GWY_FILE_SPECTRA)
        return make_key_for_id(id, GWY_FILE_PREFIX_SPECTRA, NULL);
    if (data_kind == GWY_FILE_VOLUME)
        return make_key_for_id(id, GWY_FILE_PREFIX_VOLUME, NULL);
    if (data_kind == GWY_FILE_XYZ)
        return make_key_for_id(id, GWY_FILE_PREFIX_XYZ, NULL);
    if (data_kind == GWY_FILE_CMAP)
        return make_key_for_id(id, GWY_FILE_PREFIX_CMAP, NULL);
    g_return_val_if_reached(0);
    return 0;
}

/**
 * gwy_file_key_image:
 * @id: Numerical id of an image in file.
 *
 * Constructs image data quark identifier from its id.
 *
 * Returns: The quark key identifying image data with number @id.
 **/
GQuark
gwy_file_key_image(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_IMAGE, NULL);
}

/**
 * gwy_file_key_image_picture:
 * @id: Numerical id of an image in file.
 *
 * Constructs image presentation data quark identifier from its id.
 *
 * Returns: The quark key identifying image presentation data with number @id.
 **/
GQuark
gwy_file_key_image_picture(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_IMAGE, "/show");
}

/**
 * gwy_file_key_graph:
 * @id: Numerical id of a graph in file.
 *
 * Constructs graph model quark identifier from its id.
 *
 * Returns: The quark key identifying graph model with number @id.
 **/
GQuark
gwy_file_key_graph(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_GRAPH, NULL);
}

/**
 * gwy_file_key_spectra:
 * @id: Numerical id of a spectra set in file.
 *
 * Constructs spectra quark identifier from its id.
 *
 * Returns: The quark key identifying spectra with number @id.
 **/
GQuark
gwy_file_key_spectra(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_SPECTRA, NULL);
}

/**
 * gwy_file_key_volume:
 * @id: Numerical id of a data brick in file.
 *
 * Constructs data brick quark identifier from its id.
 *
 * Returns: The quark key identifying data brick with number @id.
 **/
GQuark
gwy_file_key_volume(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_VOLUME, NULL);
}

/**
 * gwy_file_key_xyz:
 * @id: Numerical id of an XYZ scattered data in file.
 *
 * Constructs XYZ scattered data quark identifier from its id.
 *
 * Returns: The quark key identifying XYZ scattered data with number @id.
 **/
GQuark
gwy_file_key_xyz(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_XYZ, NULL);
}

/**
 * gwy_file_key_cmap:
 * @id: Numerical id of a #GwyLawn curve map in file.
 *
 * Constructs #GwyLawn curve map quark identifier from its id.
 *
 * Returns: The quark key identifying #GwyLawn curve map with number @id.
 **/
GQuark
gwy_file_key_cmap(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_CMAP, NULL);
}

/**
 * gwy_file_key_image_title:
 * @id: Numerical id of a image in file.
 *
 * Constructs data field title quark identifier from its id.
 *
 * Returns: The quark key identifying string title of image with number @id.
 **/
GQuark
gwy_file_key_image_title(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_IMAGE, "/title");
}

/**
 * gwy_file_key_image_mask:
 * @id: Numerical id of an image mask in file.
 *
 * Constructs image mask data quark identifier from its id.
 *
 * Returns: The quark key identifying image mask data with number @id.
 **/
GQuark
gwy_file_key_image_mask(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_IMAGE, "/mask");
}

/**
 * gwy_file_key_volume_mask:
 * @id: Numerical id of a volume data in file.
 *
 * Constructs volume mask data quark identifier from its id.
 *
 * Returns: The quark key identifying volume mask data with number @id.
 **/
GQuark
gwy_file_key_volume_mask(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_VOLUME, "/mask");
}

/**
 * gwy_file_key_image_mask_color:
 * @id: Numerical id of an image in file.
 *
 * Constructs image mask color quark identifier from its id.
 *
 * Returns: The quark key identifying string color of image mask with number @id.
 **/
GQuark
gwy_file_key_image_mask_color(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_IMAGE, "/mask-color");
}

/**
 * gwy_file_key_volume_mask_color:
 * @id: Numerical id of a volume data in file.
 *
 * Constructs volume mask color quark identifier from its id.
 *
 * Returns: The quark key identifying string color of volume mask with number @id.
 **/
GQuark
gwy_file_key_volume_mask_color(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_VOLUME, "/mask-color");
}

/**
 * gwy_file_key_image_color_mapping:
 * @id: Numerical id of a image in file.
 *
 * Constructs data field color mapping quark identifier from its id.
 *
 * Returns: The quark key identifying #GwyColorMappingType false colour mapping type of image with number @id.
 **/
GQuark
gwy_file_key_image_color_mapping(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_IMAGE, "/color-mapping");
}

/**
 * gwy_file_key_image_range_min:
 * @id: Numerical id of a image in file.
 *
 * Constructs data field fixed range minimum quark identifier from its id.
 *
 * Returns: The quark key identifying floating fixed false colour range minimum of image with number @id.
 **/
GQuark
gwy_file_key_image_range_min(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_IMAGE, "/range/min");
}

/**
 * gwy_file_key_image_range_max:
 * @id: Numerical id of a image in file.
 *
 * Constructs data field fixed range maximum quark identifier from its id.
 *
 * Returns: The quark key identifying floating fixed false colour range maximum of image with number @id.
 **/
GQuark
gwy_file_key_image_range_max(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_IMAGE, "/range/max");
}

/**
 * gwy_file_key_image_meta:
 * @id: Numerical id of a image in file.
 *
 * Constructs data field metadata quark identifier from its id.
 *
 * Returns: The quark key identifying metadata container of image with number @id.
 **/
GQuark
gwy_file_key_image_meta(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_IMAGE, "/meta");
}

/**
 * gwy_file_key_image_palette:
 * @id: Numerical id of a image in file.
 *
 * Constructs data field palette quark identifier from its id.
 *
 * Returns: The quark key identifying string name palette of image with number @id.
 **/
GQuark
gwy_file_key_image_palette(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_IMAGE, "/palette");
}

/**
 * gwy_file_key_image_real_square:
 * @id: Numerical id of a image in file.
 *
 * Constructs data field real-square quark identifier from its id.
 *
 * Returns: The quark key identifying boolean controlling real-square setting of image with number @id.
 **/
GQuark
gwy_file_key_image_real_square(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_IMAGE, "/real-square");
}

/**
 * gwy_file_key_image_selection:
 * @id: Numerical id of a image in file.
 * @name: (nullable):
 *        Selection name (suffix of the string key).
 *
 * Constructs data field selection quark identifier from its id and selection name.
 *
 * If @name is %NULL or empty the base selections key is constructed, with no suffix for a specific selection.
 *
 * Returns: The quark key identifying a #GwySelection for image with number @id.
 **/
GQuark
gwy_file_key_image_selection(gint id,
                             const gchar *name)
{
    enum { slen = sizeof("/selection/")-1 };
    guint len = gwy_strlen0(name);
    if (!len)
        return make_key_for_id(id, GWY_FILE_PREFIX_IMAGE, "/selection");

    gchar suffix[slen + len+1];
    memcpy(suffix, "/selection/", slen);
    memcpy(suffix + slen, name, len+1);
    return make_key_for_id(id, GWY_FILE_PREFIX_IMAGE, suffix);
}

/**
 * gwy_file_key_volume_title:
 * @id: Numerical id of a data brick in file.
 *
 * Constructs data brick title quark identifier from its id.
 *
 * Returns: The quark key identifying string title of data brick with number @id.
 **/
GQuark
gwy_file_key_volume_title(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_VOLUME, "/title");
}

/**
 * gwy_file_key_volume_picture:
 * @id: Numerical id of a data brick in file.
 *
 * Constructs data brick preview quark identifier from its id.
 *
 * Returns: The quark key identifying preview data field of data brick with number @id.
 **/
GQuark
gwy_file_key_volume_picture(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_VOLUME, "/show");
}

/**
 * gwy_file_key_volume_palette:
 * @id: Numerical id of a data brick in file.
 *
 * Constructs data brick palette quark identifier from its id.
 *
 * Returns: The quark key identifying string name palette of data brick with number @id.
 **/
GQuark
gwy_file_key_volume_palette(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_VOLUME, "/palette");
}

/**
 * gwy_file_key_volume_meta:
 * @id: Numerical id of a data brick in file.
 *
 * Constructs data brick title quark identifier from its id.
 *
 * Returns: The quark key identifying metadata container of data brick with number @id.
 **/
GQuark
gwy_file_key_volume_meta(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_VOLUME, "/meta");
}

/**
 * gwy_file_key_xyz_title:
 * @id: Numerical id of a XYZ scattered data in file.
 *
 * Constructs XYZ scattered data title quark identifier from its id.
 *
 * Returns: The quark key identifying string title of XYZ scattered data with number @id.
 **/
GQuark
gwy_file_key_xyz_title(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_XYZ, "/title");
}

/**
 * gwy_file_key_xyz_palette:
 * @id: Numerical id of an XYZ scattered data in file.
 *
 * Constructs XYZ scattered data palette quark identifier from its id.
 *
 * Returns: The quark key identifying string name palette of XYZ scattered data with number @id.
 **/
GQuark
gwy_file_key_xyz_palette(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_XYZ, "/palette");
}

/**
 * gwy_file_key_xyz_meta:
 * @id: Numerical id of an XYZ scattered data in file.
 *
 * Constructs XYZ scattered data title quark identifier from its id.
 *
 * Returns: The quark key identifying metadata container of XYZ scattered data with number @id.
 **/
GQuark
gwy_file_key_xyz_meta(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_XYZ, "/meta");
}

/**
 * gwy_file_key_xyz_picture:
 * @id: Numerical id of an XYZ scattered data in file.
 *
 * Constructs XYZ scattered data preview quark identifier from its id.
 *
 * Returns: The quark key identifying preview data field of XYZ scattered data with number @id.
 **/
GQuark
gwy_file_key_xyz_picture(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_XYZ, "/show");
}

/**
 * gwy_file_key_cmap_title:
 * @id: Numerical id of a #GwyLawn curve map in file.
 *
 * Constructs #GwyLawn curve map title quark identifier from its id.
 *
 * Returns: The quark key identifying string title of #GwyLawn curve map with number @id.
 **/
GQuark
gwy_file_key_cmap_title(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_CMAP, "/title");
}

/**
 * gwy_file_key_cmap_palette:
 * @id: Numerical id of a #GwyLawn curve map in file.
 *
 * Constructs #GwyLawn curve map palette quark identifier from its id.
 *
 * Returns: The quark key identifying string name palette of #GwyLawn curve map with number @id.
 **/
GQuark
gwy_file_key_cmap_palette(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_CMAP, "/show");
}

/**
 * gwy_file_key_cmap_meta:
 * @id: Numerical id of a #GwyLawn curve map in file.
 *
 * Constructs #GwyLawn curve map title quark identifier from its id.
 *
 * Returns: The quark key identifying metadata container of #GwyLawn curve map with number @id.
 **/
GQuark
gwy_file_key_cmap_meta(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_CMAP, "/meta");
}

/**
 * gwy_file_key_cmap_picture:
 * @id: Numerical id of a #GwyLawn curve map in file.
 *
 * Constructs #GwyLawn curve map preview quark identifier from its id.
 *
 * Returns: The quark key identifying preview data field of #GwyLawn curve map with number @id.
 **/
GQuark
gwy_file_key_cmap_picture(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_CMAP, "/show");
}

/**
 * gwy_file_key_cmap_real_square:
 * @id: Numerical id of a #GwyLawn curve map in file.
 *
 * Constructs #GwyLawn curve map real-square quark identifier from its id.
 *
 * Returns: The quark key identifying boolean controlling real-square setting of #GwyLawn curve map with number @id.
 **/
GQuark
gwy_file_key_cmap_real_square(gint id)
{
    return make_key_for_id(id, GWY_FILE_PREFIX_CMAP, "/real-square");
}

/* vim: set cin columns=120 tw=118 et ts=4 sw=4 cino=>1s,e0,n0,f0,{0,}0,^0,\:1s,=0,g1s,h0,t0,+1s,c3,(0,u0 : */
