src/core/ngx_json.c - nginx-1.31.4 nginx/ @ 8d9666701

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.             len = sizeof("\"\":") - 1 + i->name.len
  72.                   + ngx_escape_json(NULL, i->name.data, i->name.len);

  73.             if (total > NGX_MAX_SIZE_T_VALUE - len) {
  74.                 return NGX_ERROR;
  75.             }

  76.             total += len;

  77.             len = ngx_json_encode[i->type].length(i);
  78.             if (len == (size_t) NGX_ERROR) {
  79.                 return NGX_ERROR;
  80.             }

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

  84.             total += len;

  85.             i = i->next;

  86.             if (i == NULL) {
  87.                 break;
  88.             }

  89.             if (total > NGX_MAX_SIZE_T_VALUE - (sizeof(",") - 1)) {
  90.                 return NGX_ERROR;
  91.             }

  92.             total += sizeof(",") - 1;
  93.         }
  94.     }

  95.     return total;
  96. }


  97. static u_char *
  98. ngx_json_obj_encode(u_char *p, ngx_data_item_t *item)
  99. {
  100.     ngx_data_obj_t   *obj;
  101.     ngx_data_item_t  *i;

  102.     obj = &item->data.object;
  103.     i = obj->item;

  104.     *p++ = '{';

  105.     if (i) {
  106.         for ( ;; ) {
  107.             *p++ = '"';

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

  109.             *p++ = '"';
  110.             *p++ = ':';

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

  112.             i = i->next;

  113.             if (i == NULL) {
  114.                 break;
  115.             }

  116.             *p++ = ',';
  117.         }
  118.     }

  119.     *p++ = '}';

  120.     return p;
  121. }


  122. static ssize_t
  123. ngx_json_list_length(ngx_data_item_t *item)
  124. {
  125.     size_t            len, total;
  126.     ngx_data_obj_t   *obj;
  127.     ngx_data_item_t  *i;

  128.     obj = &item->data.object;
  129.     total = sizeof("[]") - 1;
  130.     i = obj->item;

  131.     if (i) {
  132.         for ( ;; ) {
  133.             len = ngx_json_encode[i->type].length(i);
  134.             if (len == (size_t) NGX_ERROR) {
  135.                 return NGX_ERROR;
  136.             }

  137.             if (total > NGX_MAX_SIZE_T_VALUE - len) {
  138.                 return NGX_ERROR;
  139.             }

  140.             total += len;

  141.             i = i->next;

  142.             if (i == NULL) {
  143.                 break;
  144.             }

  145.             if (total > NGX_MAX_SIZE_T_VALUE - (sizeof(",") - 1)) {
  146.                 return NGX_ERROR;
  147.             }

  148.             total += sizeof(",") - 1;
  149.         }
  150.     }

  151.     return total;
  152. }


  153. static u_char *
  154. ngx_json_list_encode(u_char *p, ngx_data_item_t *item)
  155. {
  156.     ngx_data_obj_t   *obj;
  157.     ngx_data_item_t  *i;

  158.     obj = &item->data.object;
  159.     i = obj->item;

  160.     *p++ = '[';

  161.     if (i) {
  162.         for ( ;; ) {
  163.             p = ngx_json_encode[i->type].encode(p, i);

  164.             i = i->next;

  165.             if (i == NULL) {
  166.                 break;
  167.             }

  168.             *p++ = ',';
  169.         }
  170.     }

  171.     *p++ = ']';

  172.     return p;
  173. }


  174. static ssize_t
  175. ngx_json_string_length(ngx_data_item_t *item)
  176. {
  177.     ngx_str_t  *str;

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

  179.     return sizeof("\"\"") - 1 + str->len
  180.            + ngx_escape_json(NULL, str->data, str->len);
  181. }


  182. static u_char *
  183. ngx_json_string_encode(u_char *p, ngx_data_item_t *item)
  184. {
  185.     ngx_str_t  *str;

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

  187.     *p++ = '"';

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

  189.     *p++ = '"';

  190.     return p;
  191. }


  192. static ssize_t
  193. ngx_json_integer_length(ngx_data_item_t *item)
  194. {
  195.     return NGX_INT64_LEN;
  196. }


  197. static u_char *
  198. ngx_json_integer_encode(u_char *p, ngx_data_item_t *item)
  199. {
  200.     return ngx_sprintf(p, "%L", item->data.integer);
  201. }


  202. static ssize_t
  203. ngx_json_boolean_length(ngx_data_item_t *item)
  204. {
  205.     return sizeof("false") - 1;
  206. }


  207. static u_char *
  208. ngx_json_boolean_encode(u_char *p, ngx_data_item_t *item)
  209. {
  210.     return item->data.boolean ? ngx_cpymem(p, "true", 4)
  211.                               : ngx_cpymem(p, "false", 5);
  212. }


  213. static ssize_t
  214. ngx_json_null_length(ngx_data_item_t *item)
  215. {
  216.     return sizeof("null") - 1;
  217. }


  218. static u_char *
  219. ngx_json_null_encode(u_char *p, ngx_data_item_t *item)
  220. {
  221.     return ngx_cpymem(p, "null", 4);
  222. }