LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/geojson/libjson - json_util.c (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 21 106 19.8 %
Date: 2024-05-06 16:27:07 Functions: 3 13 23.1 %

          Line data    Source code
       1             : /*
       2             :  * $Id: json_util.c,v 1.4 2006/01/30 23:07:57 mclark Exp $
       3             :  *
       4             :  * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
       5             :  * Michael Clark <michael@metaparadigm.com>
       6             :  *
       7             :  * This library is free software; you can redistribute it and/or modify
       8             :  * it under the terms of the MIT license. See COPYING for details.
       9             :  *
      10             :  */
      11             : 
      12             : #include "config.h"
      13             : #undef realloc
      14             : 
      15             : #include "strerror_override.h"
      16             : 
      17             : #include <ctype.h>
      18             : #include <limits.h>
      19             : #include <stdarg.h>
      20             : #include <stddef.h>
      21             : #include <stdio.h>
      22             : #include <stdlib.h>
      23             : #include <string.h>
      24             : 
      25             : #ifdef HAVE_SYS_TYPES_H
      26             : #include <sys/types.h>
      27             : #endif /* HAVE_SYS_TYPES_H */
      28             : 
      29             : #ifdef HAVE_SYS_STAT_H
      30             : #include <sys/stat.h>
      31             : #endif /* HAVE_SYS_STAT_H */
      32             : 
      33             : #ifdef HAVE_FCNTL_H
      34             : #include <fcntl.h>
      35             : #endif /* HAVE_FCNTL_H */
      36             : 
      37             : #ifdef HAVE_UNISTD_H
      38             : #include <unistd.h>
      39             : #endif /* HAVE_UNISTD_H */
      40             : 
      41             : #ifdef _WIN32
      42             : #define WIN32_LEAN_AND_MEAN
      43             : #include <io.h>
      44             : #include <windows.h>
      45             : #endif /* defined(_WIN32) */
      46             : 
      47             : #if !defined(HAVE_OPEN) && defined(_WIN32)
      48             : #define open _open
      49             : #endif
      50             : 
      51             : #include "snprintf_compat.h"
      52             : 
      53             : #include "debug.h"
      54             : #include "json_inttypes.h"
      55             : #include "json_object.h"
      56             : #include "json_object_private.h"
      57             : #include "json_tokener.h"
      58             : #include "json_util.h"
      59             : #include "printbuf.h"
      60             : 
      61             : #include "cpl_string.h"
      62             : 
      63             : static int _json_object_to_fd(int fd, struct json_object *obj, int flags, const char *filename);
      64             : 
      65             : static char _last_err[256] = "";
      66             : 
      67           0 : const char *json_util_get_last_err()
      68             : {
      69           0 :   if (_last_err[0] == '\0')
      70           0 :     return NULL;
      71           0 :   return _last_err;
      72             : }
      73             : 
      74           1 : void _json_c_set_last_err(const char *err_fmt, ...)
      75             : {
      76             :   va_list ap;
      77           1 :   va_start(ap, err_fmt);
      78             :   // Ignore (attempted) overruns from snprintf
      79           1 :   (void)vsnprintf(_last_err, sizeof(_last_err), err_fmt, ap);
      80           1 :   va_end(ap);
      81           1 : }
      82             : 
      83           0 : struct json_object *json_object_from_fd(int fd)
      84             : {
      85           0 :   return json_object_from_fd_ex(fd, -1);
      86             : }
      87           0 : struct json_object *json_object_from_fd_ex(int fd, int in_depth)
      88             : {
      89             :   struct printbuf *pb;
      90             :   struct json_object *obj;
      91             :   char buf[JSON_FILE_BUF_SIZE];
      92             :   int ret;
      93           0 :   int depth = JSON_TOKENER_DEFAULT_DEPTH;
      94             :   json_tokener *tok;
      95             : 
      96           0 :   if (!(pb = printbuf_new()))
      97             :   {
      98           0 :     _json_c_set_last_err("json_object_from_file: printbuf_new failed\n");
      99           0 :     return NULL;
     100             :   }
     101             : 
     102           0 :   if (in_depth != -1)
     103           0 :     depth = in_depth;
     104           0 :   tok = json_tokener_new_ex(depth);
     105           0 :   if (!tok)
     106             :   {
     107           0 :     _json_c_set_last_err(
     108             :         "json_object_from_fd: unable to allocate json_tokener(depth=%d): %s\n", depth,
     109           0 :         strerror(errno));
     110           0 :     printbuf_free(pb);
     111           0 :     return NULL;
     112             :   }
     113             : 
     114           0 :   while ((ret = (int)read(fd, buf, JSON_FILE_BUF_SIZE)) > 0)
     115             :   {
     116           0 :     printbuf_memappend(pb, buf, ret);
     117             :   }
     118           0 :   if (ret < 0)
     119             :   {
     120           0 :     _json_c_set_last_err("json_object_from_fd: error reading fd %d: %s\n", fd,
     121           0 :                          strerror(errno));
     122           0 :     json_tokener_free(tok);
     123           0 :     printbuf_free(pb);
     124           0 :     return NULL;
     125             :   }
     126             : 
     127           0 :   obj = json_tokener_parse_ex(tok, pb->buf, printbuf_length(pb));
     128           0 :   if (obj == NULL)
     129           0 :     _json_c_set_last_err("json_tokener_parse_ex failed: %s\n",
     130             :                          json_tokener_error_desc(json_tokener_get_error(tok)));
     131             : 
     132           0 :   json_tokener_free(tok);
     133           0 :   printbuf_free(pb);
     134           0 :   return obj;
     135             : }
     136             : 
     137           0 : struct json_object *json_object_from_file(const char *filename)
     138             : {
     139             :   struct json_object *obj;
     140             :   int fd;
     141             : 
     142           0 :   if ((fd = open(filename, O_RDONLY)) < 0)
     143             :   {
     144           0 :     _json_c_set_last_err("json_object_from_file: error opening file %s: %s\n", filename,
     145           0 :                          strerror(errno));
     146           0 :     return NULL;
     147             :   }
     148           0 :   obj = json_object_from_fd(fd);
     149           0 :   close(fd);
     150           0 :   return obj;
     151             : }
     152             : 
     153             : /* extended "format and write to file" function */
     154             : 
     155           0 : int json_object_to_file_ext(const char *filename, struct json_object *obj, int flags)
     156             : {
     157             :   int fd, ret;
     158             :   int saved_errno;
     159             : 
     160           0 :   if (!obj)
     161             :   {
     162           0 :     _json_c_set_last_err("json_object_to_file: object is null\n");
     163           0 :     return -1;
     164             :   }
     165             : 
     166           0 :   if ((fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0)
     167             :   {
     168           0 :     _json_c_set_last_err("json_object_to_file: error opening file %s: %s\n", filename,
     169           0 :                          strerror(errno));
     170           0 :     return -1;
     171             :   }
     172           0 :   ret = _json_object_to_fd(fd, obj, flags, filename);
     173           0 :   saved_errno = errno;
     174           0 :   close(fd);
     175           0 :   errno = saved_errno;
     176           0 :   return ret;
     177             : }
     178             : 
     179           0 : int json_object_to_fd(int fd, struct json_object *obj, int flags)
     180             : {
     181           0 :   if (!obj)
     182             :   {
     183           0 :     _json_c_set_last_err("json_object_to_fd: object is null\n");
     184           0 :     return -1;
     185             :   }
     186             : 
     187           0 :   return _json_object_to_fd(fd, obj, flags, NULL);
     188             : }
     189           0 : static int _json_object_to_fd(int fd, struct json_object *obj, int flags, const char *filename)
     190             : {
     191             :   int ret;
     192             :   const char *json_str;
     193             :   unsigned int wpos, wsize;
     194             : 
     195           0 :   filename = filename ? filename : "(fd)";
     196             : 
     197           0 :   if (!(json_str = json_object_to_json_string_ext(obj, flags)))
     198             :   {
     199           0 :     return -1;
     200             :   }
     201             : 
     202             :   /* CAW: probably unnecessary, but the most 64bit safe */
     203           0 :   wsize = (unsigned int)(strlen(json_str) & UINT_MAX);
     204           0 :   wpos = 0;
     205           0 :   while (wpos < wsize)
     206             :   {
     207           0 :     if ((ret = (int)write(fd, json_str + wpos, wsize - wpos)) < 0)
     208             :     {
     209           0 :       _json_c_set_last_err("json_object_to_file: error writing file %s: %s\n",
     210           0 :                            filename, strerror(errno));
     211           0 :       return -1;
     212             :     }
     213             : 
     214             :     /* because of the above check for ret < 0, we can safely cast and add */
     215           0 :     wpos += (unsigned int)ret;
     216             :   }
     217             : 
     218           0 :   return 0;
     219             : }
     220             : 
     221             : // backwards compatible "format and write to file" function
     222             : 
     223           0 : int json_object_to_file(const char *filename, struct json_object *obj)
     224             : {
     225           0 :   return json_object_to_file_ext(filename, obj, JSON_C_TO_STRING_PLAIN);
     226             : }
     227             : 
     228             : // Deprecated json_parse_double function.  See json_tokener_parse_double instead.
     229           0 : int json_parse_double(const char *buf, double *retval)
     230             : {
     231             :   char *end;
     232           0 :   *retval = CPLStrtod(buf, &end);
     233           0 :   return end == buf ? 1 : 0;
     234             : }
     235             : 
     236       12269 : int json_parse_int64(const char *buf, int64_t *retval)
     237             : {
     238       12269 :   char *end = NULL;
     239             :   int64_t val;
     240             : 
     241       12269 :   errno = 0;
     242       12269 :   val = strtoll(buf, &end, 10);
     243       12269 :   if (end != buf)
     244       12268 :     *retval = val;
     245       12269 :   return ((val == 0 && errno != 0) || (end == buf)) ? 1 : 0;
     246             : }
     247             : 
     248      260839 : int json_parse_uint64(const char *buf, uint64_t *retval)
     249             : {
     250      260839 :   char *end = NULL;
     251             :   uint64_t val;
     252             : 
     253      260839 :   errno = 0;
     254      260839 :   while (*buf == ' ')
     255           0 :     buf++;
     256      260839 :   if (*buf == '-')
     257           0 :     return 1; /* error: uint cannot be negative */
     258             : 
     259      260839 :   val = strtoull(buf, &end, 10);
     260      260839 :   if (end != buf)
     261      260839 :     *retval = val;
     262      260839 :   return ((val == 0 && errno != 0) || (end == buf)) ? 1 : 0;
     263             : }
     264             : 
     265             : #ifndef HAVE_REALLOC
     266             : void *rpl_realloc(void *p, size_t n)
     267             : {
     268             :   if (n == 0)
     269             :     n = 1;
     270             :   if (p == 0)
     271             :     return malloc(n);
     272             :   return realloc(p, n);
     273             : }
     274             : #endif
     275             : 
     276             : #define NELEM(a) (sizeof(a) / sizeof(a[0]))
     277             : /* clang-format off */
     278             : static const char *json_type_name[] = {
     279             :   /* If you change this, be sure to update the enum json_type definition too */
     280             :   "null",
     281             :   "boolean",
     282             :   "double",
     283             :   "int",
     284             :   "object",
     285             :   "array",
     286             :   "string",
     287             : };
     288             : /* clang-format on */
     289             : 
     290           0 : const char *json_type_to_name(enum json_type o_type)
     291             : {
     292           0 :   int o_type_int = (int)o_type;
     293           0 :   if (o_type_int < 0 || o_type_int >= (int)NELEM(json_type_name))
     294             :   {
     295           0 :     _json_c_set_last_err("json_type_to_name: type %d is out of range [0,%u]\n", o_type,
     296             :                          (unsigned)NELEM(json_type_name));
     297           0 :     return NULL;
     298             :   }
     299           0 :   return json_type_name[o_type];
     300             : }

Generated by: LCOV version 1.14