view types.c @ 3:215c0c3b3609

misc: use JSON everywhere (scictl/sciwebd)
author David Demelier <markand@malikania.fr>
date Mon, 14 Jun 2021 22:08:24 +0200
parents
children 3051ef92173a
line wrap: on
line source

#include <assert.h>
#include <errno.h>

#include "types.h"

typedef json_t * (*packer)(const void *);
typedef int      (*unpacker)(void *, json_t *);

static inline json_t *
job_packer(const struct job *job)
{
	return json_pack("{si si ss}",
	    "id",               job->id,
	    "project_id",       job->project_id,
	    "tag",              job->tag
	);
}

static inline int
job_unpacker(struct job *job, json_t *doc)
{
	return json_unpack(doc, "{si si ss}",
	    "id",               &job->id,
	    "project_id",       &job->project_id,
	    "tag",              &job->tag
	);
}

static inline json_t *
jobresult_packer(const struct jobresult *res)
{
	return json_pack("{si si si si ss}",
	    "id",               res->id,
	    "job_id",           res->job_id,
	    "worker_id",        res->worker_id,
	    "exitcode",         res->exitcode,
	    "log",              res->log
	);
}

static inline int
jobresult_unpacker(struct jobresult *res, json_t *doc)
{
	return json_unpack(doc, "{si si si si ss}",
	    "id",               &res->id,
	    "job_id",           &res->job_id,
	    "worker_id",        &res->worker_id,
	    "exitcode",         &res->exitcode,
	    "log",              &res->log
	);
}

static inline json_t *
worker_packer(const struct worker *w)
{
	return json_pack("{si ss ss}",
	    "id",               w->id,
	    "name",             w->name,
	    "desc",             w->desc
	);
}

static inline int
worker_unpacker(struct worker *w, json_t *doc)
{
	return json_unpack(doc, "{si ss ss}",
	    "id",               &w->id,
	    "name",             &w->name,
	    "desc",             &w->desc
	);
}

static inline json_t *
project_packer(struct project *p)
{
	return json_pack("{si ss ss ss ss}",
	    "id",               p->id,
	    "name",             p->name,
	    "desc",             p->desc,
	    "url",              p->url,
	    "script",           p->script
	);
}

static inline int
project_unpacker(struct project *p, json_t *doc)
{
	return json_unpack(doc, "{si ss ss ss ss}",
	    "id",               &p->id,
	    "name",             &p->name,
	    "desc",             &p->desc,
	    "url",              &p->url,
	    "script",           &p->script
	);
}

static json_t *
to(const void *array, size_t arraysz, size_t width, packer fn)
{
	json_t *doc;

	if (arraysz == 1)
		doc = fn(array);
	else {
		doc = json_array();

		for (size_t i = 0; i < arraysz; ++i)
			json_array_append(doc, fn((char *)array + (i * width)));
	}

	return doc;
}

static ssize_t
from(void *array, size_t arraysz, size_t width, json_t *doc, unpacker fn)
{
	json_t *val;
	size_t i, tot = 0;

	if (json_is_array(doc)) {
		json_array_foreach(doc, i, val) {
			if (tot >= arraysz)
				return errno = ERANGE, -1;
			if (fn((char *)array + (tot++ * width), val) < 0)
				return errno = EILSEQ, -1;
		}
	} else if (json_is_object(doc)) {
		tot = 1;

		if (fn(array, doc) < 0)
			return errno = EILSEQ, -1;
	} else
		return errno = EINVAL, -1;

	return tot;
}

json_t *
job_to(const struct job *jobs, size_t jobsz)
{
	assert(jobs);

	return to(jobs, jobsz, sizeof (*jobs), (packer)job_packer);
}

ssize_t
job_from(struct job *jobs, size_t jobsz, json_t *doc)
{
	assert(jobs);
	assert(doc);

	return from(jobs, jobsz, sizeof (*jobs), doc, (unpacker)job_unpacker);
}

json_t *
jobresult_to(const struct jobresult *res, size_t resz)
{
	assert(res);

	return to(res, resz, sizeof (*res), (packer)jobresult_packer);
}

ssize_t
jobresult_from(struct jobresult *res, size_t resz, json_t *doc)
{
	assert(res);
	assert(doc);

	return from(res, resz, sizeof (*res), doc, (unpacker)jobresult_unpacker);
}

json_t *
worker_to(const struct worker *w, size_t wsz)
{
	assert(w);

	return to(w, wsz, sizeof (*w), (packer)worker_packer);
}

ssize_t
worker_from(struct worker *w, size_t wsz, json_t *doc)
{
	assert(w);
	assert(doc);

	return from(w, wsz, sizeof (*w), doc, (unpacker)worker_unpacker);
}

json_t *
project_to(const struct project *proj, size_t projsz)
{
	assert(proj);

	return to(proj, projsz, sizeof (*proj), (packer)project_packer);
}

ssize_t
project_from(struct project *proj, size_t projsz, json_t *doc)
{
	assert(proj);
	assert(doc);

	return from(proj, projsz, sizeof (*proj), doc, (unpacker)project_unpacker);
}