<'
# Copyright (c) 2012-2015, 2017-2019, 2025-2026 LAAS/CNRS
# All rights reserved.
#
# Redistribution and use  in source  and binary  forms,  with or without
# modification, are permitted provided that the following conditions are
# met:
#
#   1. Redistributions of  source  code must retain the  above copyright
#      notice and this list of conditions.
#   2. Redistributions in binary form must reproduce the above copyright
#      notice and  this list of  conditions in the  documentation and/or
#      other materials provided with the distribution.
#
#                                      Anthony Mallet on Mon Apr  9 2012
#

args components
lang c
'>
#include <stdlib.h>
#include <string.h>

#include "jsonops-c.h"

<'foreach c $components {'>
<'  set comp [$c name]'>

/* <"[--- $comp =========================================================] "> */

#include "<"$comp">/c/client.h"

<'  foreach s [$c services] {'>

/* <"[--- Service [$s name] encoding/decoding ---------------------------]"> */

int
genom_<"$comp">_client_<"[$s name]">_json_scan(
  struct genom_<"$comp">_<"[$s name]">_input *in, const char *json,
  char **endptr)
{
  int s = 0;
<'    if {![llength [$s parameters in inout]]} {'>
  (void)in; /* fix -Wunused-parameter */
<'    }'>
  genom_json_skipspace(json);
  if (*(json++) != '{') { s = EINVAL; goto done; }
  genom_json_skipspace(json);
  while(*json != '}') {
    if (*(json++) != '"') { s = EINVAL; goto done; };
<'    foreach p [$s parameters in inout] {'>
    if (!strncmp(json, "<"[$p name]">\"", 1+<"[string length [$p name]]">)) {
      json += 1+<"[string length [$p name]]">;
      genom_json_skipspace(json);
      if (*(json++) != ':') { s = EINVAL; goto done; }
      if ((s = genom_json_scan_<"[[$p type] mangle]">(
             <"[[$p type] pass reference in->[$p name]]">, &json)))
        goto done;
    } else
<'    }'>
    { s = EINVAL; goto done; }

    genom_json_skipspace(json);
    if (*json == ',') {
      json++;
      genom_json_skipspace(json);
    }
  }

done:
  if (endptr) *endptr = (char *)json;
  return s;
}

int
genom_<"$comp">_client_<"[$s name]">_json_print(char **json,
             const struct genom_<"$comp">_<"[$s name]">_output *out)
{
  size_t len;
  char *end;
  int s;
<'    if {![llength [$s parameters inout out]]} {'>
  (void)out; /* fix -Wunused-parameter */
<'    }'>

  len = JSON_MINBUF;
  *json = end = malloc(len);
  if (!*json) return ENOMEM;

  if ((s = genom_bufcat(json, &end, &len, 0, "{"))) goto done;

<'    set sep {}'>
<'    foreach p [$s parameters inout out] {'>
  if ((s = genom_bufcat(json, &end, &len, 0, "<"$sep">\"<"[$p name]">\":")))
    goto done;
  if ((s = genom_json_print_<"[[$p type] mangle]">(json, &end, &len,
         <"[[$p type] pass value out->[$p name]]">)))
    goto done;
<'  set sep ,'>
<'    }'>

  if ((s = genom_bufcat(json, &end, &len, 0, "}"))) goto done;

done:
  if (s && *json) {
    free(*json);
    *json = NULL;
  }
  return s;
}

<'  }'>

<'  foreach p [$c port] {'>

/* <"[--- Port [$p name] encoding ---------------------------------------]"> */

<'    if {"in" in [$p dir]} {'>
int
genom_<"$comp">_client_<"[$p name]">_json_scan(
  <"[[$p datatype] argument reference data]">,
  const char *json, char **endptr)
{
  int s = 0;

  genom_json_skipspace(json);
  if (*(json++) != '{') { s = EINVAL; goto done; }
  genom_json_skipspace(json);
  while(*json != '}') {
    if (*(json++) != '"') { s = EINVAL; goto done; };

    if (strncmp(json, "<"[$p name]">\"", 1+<"[string length [$p name]]">)) {
      s = EINVAL; goto done;
    }

    json += 1+<"[string length [$p name]]">;
    genom_json_skipspace(json);
    if (*(json++) != ':') { s = EINVAL; goto done; }
    if ((s = genom_json_scan_<"[[$p datatype] mangle]">(data, &json)))
      goto done;

    genom_json_skipspace(json);
    if (*json == ',') {
      json++;
      genom_json_skipspace(json);
    }
  }

done:
  if (endptr) *endptr = (char *)json;
  return s;
}
<'    }'>

int
genom_<"$comp">_client_<"[$p name]">_json_print(char **json,
  const <"[[$p datatype] argument reference data]">)
{
  size_t len;
  char *end;
  int s;

  len = JSON_MINBUF;
  *json = end = malloc(len);
  if (!*json) return ENOMEM;

  if ((s = genom_bufcat(json, &end, &len, 0, "{"))) goto done;

  if ((s = genom_bufcat(json, &end, &len, 0, "\"<"[$p name]">\":")))
    goto done;

<'    set data [[$p datatype] dereference reference data]'>
  if ((s = genom_json_print_<"[[$p datatype] mangle]">(
         json, &end, &len, <"[[$p datatype] pass value $data]">)))
    goto done;

  if ((s = genom_bufcat(json, &end, &len, 0, "}"))) goto done;

done:
  if (s && *json) {
    free(*json);
    *json = NULL;
  }
  return s;
}

<'  }'>

/* <"[--- ${comp}_json_error --------------------------------------------]"> */

char *
genom_<"$comp">_client_json_error(genom_client h,
                         genom_event e, const void *detail)
{
  char *json;

  if (!e && h) {
    genom_context self = genom_<"$comp">_client_context(h);
    detail = self->raised(&e, self);
  }

  if (genom_json_printex(&json, e, detail))
    return "{\"ex\":\"::genom::fatal\"}";
  return json;
}

<'}'>
/* eof */
