Exemplo n.º 1
0
const struct sj_conf_entry *sj_conf_find_schema_entry(
    const char *path, const struct sj_conf_entry *obj) {
  const char *sep = strchr(path, '.');
  int kl = (sep == 0 ? (int) strlen(path) : (sep - path));
  for (int i = 1; i <= obj->num_desc; i++) {
    const struct sj_conf_entry *e = obj + i;
    if (strncmp(path, e->key, kl) == 0 && ((int) strlen(e->key) == kl)) {
      if (path[kl] == '\0') return e;
      if (e->type != CONF_TYPE_OBJECT) return NULL;
      return sj_conf_find_schema_entry(path + kl + 1, e);
    }
  }
  return NULL;
}
Exemplo n.º 2
0
void sj_conf_parse_cb(void *data, const char *path,
                      const struct json_token *tok) {
  struct parse_ctx *ctx = (struct parse_ctx *) data;
  if (!ctx->result) return;
  if (path[0] != '.') {
    if (path[0] == '\0') return; /* Last entry, the entire object */
    LOG(LL_ERROR, ("Not an object"));
    ctx->result = false;
    return;
  }
  path++;
  const struct sj_conf_entry *e = sj_conf_find_schema_entry(path, ctx->schema);
  if (e == NULL) {
    LOG(LL_INFO, ("Extra key: [%s]", path));
    return;
  }
  char *vp = (((char *) ctx->cfg) + e->offset);
  switch (e->type) {
    case CONF_TYPE_INT: {
      if (tok->type != JSON_TYPE_NUMBER) {
        LOG(LL_ERROR, ("[%s] is not a number", path));
        ctx->result = false;
        return;
      }
      *((int *) vp) = strtod(tok->ptr, NULL);
      break;
    }
    case CONF_TYPE_BOOL: {
      if (tok->type != JSON_TYPE_TRUE && tok->type != JSON_TYPE_FALSE) {
        LOG(LL_ERROR, ("[%s] is not a boolean", path));
        ctx->result = false;
        return;
      }
      *((int *) vp) = (tok->type == JSON_TYPE_TRUE);
      break;
    }
    case CONF_TYPE_STRING: {
      if (tok->type != JSON_TYPE_STRING) {
        LOG(LL_ERROR, ("[%s] is not a string", path));
        ctx->result = false;
        return;
      }
      char **sp = (char **) vp;
      char *s = NULL;
      if (*sp != NULL) free(*sp);
      if (tok->len > 0) {
        s = (char *) malloc(tok->len + 1);
        if (s == NULL) {
          ctx->result = false;
          return;
        }
        /* TODO(rojer): Unescape the string. */
        memcpy(s, tok->ptr, tok->len);
        s[tok->len] = '\0';
      } else {
        /* Empty string - keep value as NULL. */
      }
      *sp = s;
      break;
    }
    case CONF_TYPE_OBJECT: {
      /* Ignore */
      return;
    }
  }
  LOG(LL_DEBUG, ("Set [%s] = [%.*s]", path, (int) tok->len, tok->ptr));
}