/* This file is part of GNUnet Copyright (C) 2021 GNUnet e.V. GNUnet is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. GNUnet 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 Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . SPDX-License-Identifier: AGPL3.0-or-later */ /** * @file json/json_pack.c * @brief functions to pack JSON objects * @author Christian Grothoff */ #include "platform.h" #include "gnunet_json_lib.h" json_t * GNUNET_JSON_pack_ (struct GNUNET_JSON_PackSpec spec[]) { json_t *ret; if (NULL == spec[0].field_name) { ret = spec[0].object; spec[0].object = NULL; return ret; } ret = json_object (); GNUNET_assert (NULL != ret); for (unsigned int i = 0; NULL != spec[i].field_name; i++) { if (NULL == spec[i].object) { GNUNET_assert (spec[i].allow_null); } else { GNUNET_assert (0 == json_object_set_new (ret, spec[i].field_name, spec[i].object)); spec[i].object = NULL; } } return ret; } struct GNUNET_JSON_PackSpec GNUNET_JSON_pack_end_ (void) { struct GNUNET_JSON_PackSpec ps = { .field_name = NULL }; return ps; } struct GNUNET_JSON_PackSpec GNUNET_JSON_pack_allow_null (struct GNUNET_JSON_PackSpec in) { in.allow_null = true; return in; } struct GNUNET_JSON_PackSpec GNUNET_JSON_pack_bool (const char *name, bool b) { struct GNUNET_JSON_PackSpec ps = { .field_name = name, .object = json_boolean (b) }; return ps; } struct GNUNET_JSON_PackSpec GNUNET_JSON_pack_string (const char *name, const char *s) { struct GNUNET_JSON_PackSpec ps = { .field_name = name, .object = json_string (s) }; return ps; } struct GNUNET_JSON_PackSpec GNUNET_JSON_pack_uint64 (const char *name, uint64_t num) { struct GNUNET_JSON_PackSpec ps = { .field_name = name, .object = json_integer ((json_int_t) num) }; #if JSON_INTEGER_IS_LONG_LONG GNUNET_assert (num <= LLONG_MAX); #else GNUNET_assert (num <= LONG_MAX); #endif return ps; } struct GNUNET_JSON_PackSpec GNUNET_JSON_pack_int64 (const char *name, int64_t num) { struct GNUNET_JSON_PackSpec ps = { .field_name = name, .object = json_integer ((json_int_t) num) }; #if JSON_INTEGER_IS_LONG_LONG GNUNET_assert (num <= LLONG_MAX); GNUNET_assert (num >= LLONG_MIN); #else GNUNET_assert (num <= LONG_MAX); GNUNET_assert (num >= LONG_MIN); #endif return ps; } struct GNUNET_JSON_PackSpec GNUNET_JSON_pack_object_steal (const char *name, json_t *o) { struct GNUNET_JSON_PackSpec ps = { .field_name = name, .object = o }; if (NULL == o) return ps; if (! json_is_object (o)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected JSON object for field `%s'\n", name); GNUNET_assert (0); } return ps; } struct GNUNET_JSON_PackSpec GNUNET_JSON_pack_object_incref (const char *name, json_t *o) { struct GNUNET_JSON_PackSpec ps = { .field_name = name, .object = o }; if (NULL == o) return ps; (void) json_incref (o); if (! json_is_object (o)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected JSON object for field `%s'\n", name); GNUNET_assert (0); } return ps; } struct GNUNET_JSON_PackSpec GNUNET_JSON_pack_array_steal (const char *name, json_t *a) { struct GNUNET_JSON_PackSpec ps = { .field_name = name, .object = a }; if (NULL == a) return ps; if (! json_is_array (a)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected JSON array for field `%s'\n", name); GNUNET_assert (0); } return ps; } struct GNUNET_JSON_PackSpec GNUNET_JSON_pack_array_incref (const char *name, json_t *a) { struct GNUNET_JSON_PackSpec ps = { .field_name = name, .object = a }; if (NULL == a) return ps; (void) json_incref (a); if (! json_is_array (a)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected JSON array for field `%s'\n", name); GNUNET_assert (0); } return ps; } struct GNUNET_JSON_PackSpec GNUNET_JSON_pack_data_varsize (const char *name, const void *blob, size_t blob_size) { struct GNUNET_JSON_PackSpec ps = { .field_name = name, .object = (NULL != blob) ? GNUNET_JSON_from_data (blob, blob_size) : NULL }; return ps; } struct GNUNET_JSON_PackSpec GNUNET_JSON_pack_timestamp (const char *name, struct GNUNET_TIME_Timestamp t) { struct GNUNET_JSON_PackSpec ps = { .field_name = name }; if (! GNUNET_TIME_absolute_is_zero (t.abs_time)) { ps.object = GNUNET_JSON_from_timestamp (t); GNUNET_assert (NULL != ps.object); } else { ps.object = NULL; } return ps; } struct GNUNET_JSON_PackSpec GNUNET_JSON_pack_timestamp_nbo (const char *name, struct GNUNET_TIME_TimestampNBO at) { return GNUNET_JSON_pack_timestamp (name, GNUNET_TIME_timestamp_ntoh (at)); } struct GNUNET_JSON_PackSpec GNUNET_JSON_pack_time_rel (const char *name, struct GNUNET_TIME_Relative rt) { json_t *json; json = GNUNET_JSON_from_time_rel (rt); GNUNET_assert (NULL != json); return GNUNET_JSON_pack_object_steal (name, json); } struct GNUNET_JSON_PackSpec GNUNET_JSON_pack_time_rel_nbo (const char *name, struct GNUNET_TIME_RelativeNBO rt) { return GNUNET_JSON_pack_time_rel (name, GNUNET_TIME_relative_ntoh (rt)); } struct GNUNET_JSON_PackSpec GNUNET_JSON_pack_rsa_public_key (const char *name, const struct GNUNET_CRYPTO_RsaPublicKey *pk) { struct GNUNET_JSON_PackSpec ps = { .field_name = name, .object = GNUNET_JSON_from_rsa_public_key (pk) }; return ps; } struct GNUNET_JSON_PackSpec GNUNET_JSON_pack_rsa_signature (const char *name, const struct GNUNET_CRYPTO_RsaSignature *sig) { struct GNUNET_JSON_PackSpec ps = { .field_name = name, .object = GNUNET_JSON_from_rsa_signature (sig) }; return ps; } /* end of json_pack.c */