You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

174 lines
3.8 KiB

#pragma once
#include <errno.h>
#include <inttypes.h>
#include <jsmn.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static inline char *
jsmn_type(jsmntype_t type)
{
switch (type) {
case JSMN_UNDEFINED:
return "Undefined";
case JSMN_OBJECT:
return "Object";
case JSMN_ARRAY:
return "Array";
case JSMN_STRING:
return "String";
case JSMN_PRIMITIVE:
return "Primitive";
default:
return "Invalid";
}
}
static inline bool
has_valid_size(jsmntok_t tok, char *key, int expected_size)
{
if (tok.size != expected_size) {
fprintf(stderr, "%s has size %d, expected %d\n", key, tok.size, expected_size);
return false;
}
return true;
}
static inline bool
has_valid_type(jsmntok_t tok, char *key, jsmntype_t expected_type, const char *json_buf)
{
if (tok.type != expected_type) {
fprintf(stderr, "The value of the key %s should be a %s, was a %s\n", key, jsmn_type(expected_type),
jsmn_type(tok.type));
if (json_buf != NULL) fprintf(stderr, "Token: %.*s\n", tok.end - tok.start, &json_buf[tok.start]);
return false;
}
return true;
}
static inline bool
is_nonempty_string(jsmntok_t tok, char *key)
{
if (!has_valid_type(tok, key, JSMN_STRING, NULL)) return false;
if (tok.end - tok.start < 1) {
fprintf(stderr, "The value of the key %s was an empty string\n", key);
return false;
}
return true;
}
static inline bool
is_nonempty_object(jsmntok_t tok, char *key)
{
if (!has_valid_type(tok, key, JSMN_OBJECT, NULL)) return false;
if (tok.size == 0) {
fprintf(stderr, "The value of the key %s was an empty object\n", key);
return false;
}
return true;
}
static inline bool
is_nonempty_array(jsmntok_t tok, char *key)
{
if (!has_valid_type(tok, key, JSMN_ARRAY, NULL)) return false;
if (tok.size == 0) {
fprintf(stderr, "The value of the key %s was an empty array\n", key);
return false;
}
return true;
}
static inline bool
is_valid_key(jsmntok_t tok)
{
if (tok.type != JSMN_STRING) {
fprintf(stderr, "Expected token to be a key with a type of string, was a %s\n", jsmn_type(tok.type));
return false;
}
if (tok.end - tok.start < 1) {
fprintf(stderr, "Key was an empty string\n");
return false;
}
return true;
}
static inline int
parse_uint8_t(jsmntok_t tok, const char *json_buf, const char *key, uint8_t *ret)
{
char *end = NULL;
intmax_t temp = strtoimax(&json_buf[tok.start], &end, 10);
if (end != &json_buf[tok.end] || temp < 0 || temp > UINT8_MAX) {
fprintf(stderr, "Unable to parse uint8_t for key %s\n", key);
return -1;
}
*ret = (uint8_t)temp;
return 0;
}
static inline int
parse_uint16_t(jsmntok_t tok, const char *json_buf, const char *key, uint16_t *ret)
{
char *end = NULL;
intmax_t temp = strtoimax(&json_buf[tok.start], &end, 10);
if (end != &json_buf[tok.end] || temp < 0 || temp > UINT16_MAX) {
fprintf(stderr, "Unable to parse uint16_t for key %s\n", key);
return -1;
}
*ret = (uint16_t)temp;
return 0;
}
static inline int
parse_uint32_t(jsmntok_t tok, const char *json_buf, const char *key, uint32_t *ret)
{
char *end = NULL;
intmax_t temp = strtoimax(&json_buf[tok.start], &end, 10);
if (end != &json_buf[tok.end] || temp < 0 || temp > UINT32_MAX) {
fprintf(stderr, "Unable to parse uint32_t for key %s\n", key);
return -1;
}
*ret = (uint32_t)temp;
return 0;
}
static inline int
parse_uint64_t(jsmntok_t tok, const char *json_buf, const char *key, uint64_t *ret)
{
if (json_buf[tok.start] == '-') {
fprintf(stderr, "Unable to parse uint64_t for key %s, had negative number\n", key);
}
errno = 0;
char *end = NULL;
uintmax_t temp = strtoumax(&json_buf[tok.start], &end, 10);
if (end != &json_buf[tok.end] || (temp == UINT64_MAX && errno == ERANGE)) {
fprintf(stderr, "Unable to parse uint64_t for key %s\n", key);
return -1;
}
*ret = temp;
return 0;
}