src/core/ngx_json.c - nginx-1.31.7 nginx/ @ 939334eff

Global variables defined

Data types defined

Functions defined

Source code


  1. /*
  2. * Copyright (C) Nginx, Inc.
  3. */


  4. #include <ngx_config.h>
  5. #include <ngx_core.h>


  6. ‌typedef ssize_t   (*ngx_json_length_pt)(ngx_data_item_t *item);
  7. ‌typedef u_char   *(*ngx_json_encode_pt)(u_char *p, ngx_data_item_t *item);


  8. ‌typedef struct {
  9.     ngx_json_length_pt        length;
  10.     ngx_json_encode_pt        encode;
  11. ‌} ngx_json_encode_t;


  12. static ssize_t ngx_json_obj_length(ngx_data_item_t *item);
  13. static ssize_t ngx_json_list_length(ngx_data_item_t *item);
  14. static ssize_t ngx_json_string_length(ngx_data_item_t *item);
  15. static ssize_t ngx_json_integer_length(ngx_data_item_t *item);
  16. static ssize_t ngx_json_boolean_length(ngx_data_item_t *item);
  17. static ssize_t ngx_json_null_length(ngx_data_item_t *item);

  18. static u_char *ngx_json_obj_encode(u_char *p, ngx_data_item_t *item);
  19. static u_char *ngx_json_list_encode(u_char *p, ngx_data_item_t *item);
  20. static u_char *ngx_json_string_encode(u_char *p, ngx_data_item_t *item);
  21. static u_char *ngx_json_integer_encode(u_char *p, ngx_data_item_t *item);
  22. static u_char *ngx_json_boolean_encode(u_char *p, ngx_data_item_t *item);
  23. static u_char *ngx_json_null_encode(u_char *p, ngx_data_item_t *item);


  24. ‌static ngx_json_encode_t  ngx_json_encode[] = {

  25.     /* NGX_DATA_OBJECT_TYPE */
  26.     { ngx_json_obj_length,
  27.       ngx_json_obj_encode },

  28.     /* NGX_DATA_LIST_TYPE */
  29.     { ngx_json_list_length,
  30.       ngx_json_list_encode },

  31.     /* NGX_DATA_STRING_TYPE */
  32.     { ngx_json_string_length,
  33.       ngx_json_string_encode },

  34.     /* NGX_DATA_INTEGER_TYPE */
  35.     { ngx_json_integer_length,
  36.       ngx_json_integer_encode },

  37.     /* NGX_DATA_BOOLEAN_TYPE */
  38.     { ngx_json_boolean_length,
  39.       ngx_json_boolean_encode },

  40.     /* NGX_DATA_NULL_TYPE */
  41.     { ngx_json_null_length,
  42.       ngx_json_null_encode },
  43. };


  44. ngx_buf_t *
  45. ‌ngx_json_render(ngx_pool_t *pool, ngx_data_item_t *item)
  46. {
  47.     size_t      length;
  48.     ngx_buf_t  *buf;

  49.     length = ngx_json_encode[item->type].length(item);
  50.     if (length == (size_t) NGX_ERROR) {
  51.         return NULL;
  52.     }

  53.     buf = ngx_create_temp_buf(pool, length);
  54.     if (buf == NULL) {
  55.         return NULL;
  56.     }

  57.     buf->last = ngx_json_encode[item->type].encode(buf->last, item);

  58.     return buf;
  59. }


  60. static ssize_t
  61. ‌ngx_json_obj_length(ngx_data_item_t *item)
  62. {
  63.     size_t            len, total;
  64.     ngx_data_obj_t   *obj;
  65.     ngx_data_item_t  *i;

  66.     obj = &item->data.object;
  67.     total = sizeof("{}") - 1;
  68.     i = obj->item;

  69.     if (i) {
  70.         for ( ;; ) {
  71.             if (i->name.len > NGX_MAX_SIZE_T_VALUE - (sizeof("\"\":") - 1)) {
  72.                 return NGX_ERROR;
  73.             }

  74.             len = sizeof("\"\":") - 1 + i->name.len;

  75.             if (len > NGX_MAX_SIZE_T_VALUE - total) {
  76.                 return NGX_ERROR;
  77.             }

  78.             total += len;

  79.             len = ngx_escape_json(NULL, i->name.data, i->name.len);

  80.             if (len > NGX_MAX_SIZE_T_VALUE - total) {
  81.                 return NGX_ERROR;
  82.             }

  83.             total += len;

  84.             len = ngx_json_encode[i->type].length(i);
  85.             if (len == (size_t) NGX_ERROR) {
  86.                 return NGX_ERROR;
  87.             }

  88.             if (len > NGX_MAX_SIZE_T_VALUE - total) {
  89.                 return NGX_ERROR;
  90.             }

  91.             total += len;

  92.             i = i->next;

  93.             if (i == NULL) {
  94.                 break;
  95.             }

  96.             if (total > NGX_MAX_SIZE_T_VALUE - (sizeof(",") - 1)) {
  97.                 return NGX_ERROR;
  98.             }

  99.             total += sizeof(",") - 1;
  100.         }
  101.     }

  102.     return total;
  103. }


  104. static u_char *
  105. ‌ngx_json_obj_encode(u_char *p, ngx_data_item_t *item)
  106. {
  107.     ngx_data_obj_t   *obj;
  108.     ngx_data_item_t  *i;

  109.     obj = &item->data.object;
  110.     i = obj->item;

  111.     *p++ = '{';

  112.     if (i) {
  113.         for ( ;; ) {
  114.             *p++ = '"';

  115.             p = (u_char *) ngx_escape_json(p, i->name.data, i->name.len);

  116.             *p++ = '"';
  117.             *p++ = ':';

  118.             p = ngx_json_encode[i->type].encode(p, i);

  119.             i = i->next;

  120.             if (i == NULL) {
  121.                 break;
  122.             }

  123.             *p++ = ',';
  124.         }
  125.     }

  126.     *p++ = '}';

  127.     return p;
  128. }


  129. static ssize_t
  130. ‌ngx_json_list_length(ngx_data_item_t *item)
  131. {
  132.     size_t            len, total;
  133.     ngx_data_obj_t   *obj;
  134.     ngx_data_item_t  *i;

  135.     obj = &item->data.object;
  136.     total = sizeof("[]") - 1;
  137.     i = obj->item;

  138.     if (i) {
  139.         for ( ;; ) {
  140.             len = ngx_json_encode[i->type].length(i);
  141.             if (len == (size_t) NGX_ERROR) {
  142.                 return NGX_ERROR;
  143.             }

  144.             if (len > NGX_MAX_SIZE_T_VALUE - total) {
  145.                 return NGX_ERROR;
  146.             }

  147.             total += len;

  148.             i = i->next;

  149.             if (i == NULL) {
  150.                 break;
  151.             }

  152.             if (total > NGX_MAX_SIZE_T_VALUE - (sizeof(",") - 1)) {
  153.                 return NGX_ERROR;
  154.             }

  155.             total += sizeof(",") - 1;
  156.         }
  157.     }

  158.     return total;
  159. }


  160. static u_char *
  161. ‌ngx_json_list_encode(u_char *p, ngx_data_item_t *item)
  162. {
  163.     ngx_data_obj_t   *obj;
  164.     ngx_data_item_t  *i;

  165.     obj = &item->data.object;
  166.     i = obj->item;

  167.     *p++ = '[';

  168.     if (i) {
  169.         for ( ;; ) {
  170.             p = ngx_json_encode[i->type].encode(p, i);

  171.             i = i->next;

  172.             if (i == NULL) {
  173.                 break;
  174.             }

  175.             *p++ = ',';
  176.         }
  177.     }

  178.     *p++ = ']';

  179.     return p;
  180. }


  181. static ssize_t
  182. ‌ngx_json_string_length(ngx_data_item_t *item)
  183. {
  184.     size_t      len, total;
  185.     ngx_str_t  *str;

  186.     str = &item->data.string;

  187.     if (str->len > NGX_MAX_SIZE_T_VALUE - (sizeof("\"\"") - 1)) {
  188.         return NGX_ERROR;
  189.     }

  190.     total = sizeof("\"\"") - 1 + str->len;

  191.     len = ngx_escape_json(NULL, str->data, str->len);

  192.     if (len > NGX_MAX_SIZE_T_VALUE - total) {
  193.         return NGX_ERROR;
  194.     }

  195.     return total + len;
  196. }


  197. static u_char *
  198. ‌ngx_json_string_encode(u_char *p, ngx_data_item_t *item)
  199. {
  200.     ngx_str_t  *str;

  201.     str = &item->data.string;

  202.     *p++ = '"';

  203.     p = (u_char *) ngx_escape_json(p, str->data, str->len);

  204.     *p++ = '"';

  205.     return p;
  206. }


  207. static ssize_t
  208. ‌ngx_json_integer_length(ngx_data_item_t *item)
  209. {
  210.     return NGX_INT64_LEN;
  211. }


  212. static u_char *
  213. ‌ngx_json_integer_encode(u_char *p, ngx_data_item_t *item)
  214. {
  215.     return ngx_sprintf(p, "%L", item->data.integer);
  216. }


  217. static ssize_t
  218. ‌ngx_json_boolean_length(ngx_data_item_t *item)
  219. {
  220.     return sizeof("false") - 1;
  221. }


  222. static u_char *
  223. ‌ngx_json_boolean_encode(u_char *p, ngx_data_item_t *item)
  224. {
  225.     return item->data.boolean ? ngx_cpymem(p, "true", 4)
  226.                               : ngx_cpymem(p, "false", 5);
  227. }


  228. static ssize_t
  229. ‌ngx_json_null_length(ngx_data_item_t *item)
  230. {
  231.     return sizeof("null") - 1;
  232. }


  233. static u_char *
  234. ‌ngx_json_null_encode(u_char *p, ngx_data_item_t *item)
  235. {
  236.     return ngx_cpymem(p, "null", 4);
  237. }