kmx.io/kv/kv_path.c

Branch

Thomas de Grivel cbd7ffcba 2021-12-29T18:12:45
WIP
/*
 * kv - key value text file format
 *
 * Copyright 2022 Thomas de Grivel
*/

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "kv_path.h"

void kv_path_init (s_kv_path *p, const char *k, size_t ks,
                   s_kv_path *parent)
{
  assert(p);
  p->k = k;
  p->ks = ks;
  p->parent = parent;
}

s_kv_path * kv_path_new (const char *k, size_t ks, s_kv_path *parent)
{
  s_kv_path *p = calloc(sizeof(s_kv_path), 1);
  if (p)
    kv_path_init(p, k, ks, parent);
  return p;
}

void kv_path_delete (s_kv_path *p)
{
  free(p);
}

size_t kv_path_print (s_kv_path *p, FILE *fp)
{
  s_kv_path *acc;
  size_t r = 0;
  while (p) {
    acc = kv_path_new(p->k, p->ks, acc);
    p = p->parent;
  }
  while (acc) {
    r += fprintf(fp, "%s", acc->k);
    kv_path_delete(acc);
    acc = acc->parent;
    if (acc)
      r += fprintf(fp, " ");
  }
  return r;
}

s_kv_path * kv_path_reverse (s_kv_path *p)
{
  s_kv_path *acc = NULL;
  while (p) {
    acc = kv_path_new(p->k, p->ks, acc);
    p = p->parent;
  }
  return acc;
}

void kv_path_delete_all (s_kv_path *p)
{
  while (p) {
    s_kv_path *parent = p->parent;
    kv_path_delete(p);
    p = parent;
  }
}

size_t min (size_t a, size_t b)
{
  if (a < b)
    return a;
  return b;
}

int kv_path_compare (s_kv_path *a, s_kv_path *b)
{
  int cmp;
  a = kv_path_reverse(a);
  b = kv_path_reverse(b);
  while (a && b) {
    if (a == b)
      return 0;
    cmp = memcmp(a->k, b->k, min(a->ks, b->ks));
    if (cmp)
      return cmp;
    if (a->ks < b->ks)
      return -1;
    if (a->ks > b->ks)
      return 1;
    a = a->parent;
    b = b->parent;
  }
  return 0;
}
Download