src/core/ngx_resolver.h \
src/core/ngx_open_file_cache.h \
src/core/ngx_crypt.h \
+ src/core/ngx_data.h \
+ src/core/ngx_json.h \
src/core/ngx_proxy_protocol.h \
src/core/ngx_syslog.h"
src/core/ngx_resolver.c \
src/core/ngx_open_file_cache.c \
src/core/ngx_crypt.c \
+ src/core/ngx_data.c \
+ src/core/ngx_json.c \
src/core/ngx_proxy_protocol.c \
src/core/ngx_syslog.c"
#include <ngx_times.h>
#include <ngx_rwlock.h>
#include <ngx_shmtx.h>
+#include <ngx_data.h>
+#include <ngx_json.h>
#include <ngx_slab.h>
#include <ngx_inet.h>
#include <ngx_cycle.h>
--- /dev/null
+
+/*
+ * Copyright (C) Nginx, Inc.
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+static size_t ngx_data_sizes[] = {
+ sizeof(ngx_data_obj_t), /* NGX_DATA_OBJECT_TYPE */
+ sizeof(ngx_data_obj_t), /* NGX_DATA_LIST_TYPE */
+ sizeof(ngx_str_t), /* NGX_DATA_STRING_TYPE */
+ sizeof(int64_t), /* NGX_DATA_INTEGER_TYPE */
+ sizeof(ngx_uint_t), /* NGX_DATA_BOOLEAN_TYPE */
+ 0, /* NGX_DATA_NULL_TYPE */
+};
+
+
+ngx_data_item_t *
+ngx_data_new_item(ngx_pool_t *pool, ngx_uint_t type)
+{
+ ngx_data_item_t *item;
+
+ item = ngx_pcalloc(pool, offsetof(ngx_data_item_t, data)
+ + ngx_data_sizes[type]);
+ if (item == NULL) {
+ return NULL;
+ }
+
+ item->type = type;
+
+ return item;
+}
+
+
+void
+ngx_data_add_item(ngx_data_item_t *obj, ngx_str_t *name, ngx_data_item_t *item)
+{
+ ngx_data_obj_t *object;
+
+ if (obj->type != NGX_DATA_OBJECT_TYPE && obj->type != NGX_DATA_LIST_TYPE) {
+ return;
+ }
+
+ object = &obj->data.object;
+
+ if (name) {
+ item->name = *name;
+ }
+
+ if (object->next == NULL) {
+ object->next = &object->item;
+ }
+
+ *object->next = item;
+ object->next = &item->next;
+}
+
+
+ngx_data_item_t *
+ngx_data_obj_handler(uintptr_t data, ngx_pool_t *pool, void *ctx)
+{
+ ngx_data_item_t *obj, *item;
+ ngx_data_decl_t *decl;
+
+ obj = ngx_data_new_object(pool);
+ if (obj == NULL) {
+ return NULL;
+ }
+
+ decl = (ngx_data_decl_t *) data;
+
+ while (decl->name.len) {
+
+ item = decl->handler(decl->data, pool, ctx);
+ if (item == NULL) {
+ return NULL;
+ }
+
+ if (item != NGX_DATA_DECLINE) {
+ ngx_data_add_item(obj, &decl->name, item);
+ }
+
+ decl++;
+ }
+
+ return obj;
+}
+
+
+ngx_data_item_t *
+ngx_data_obj_fields_handler(uintptr_t data, ngx_pool_t *pool, void *ctx,
+ ngx_array_t *fields)
+{
+ ngx_str_t *value;
+ ngx_uint_t i;
+ ngx_data_item_t *obj, *item;
+ ngx_data_decl_t *decl;
+
+ obj = ngx_data_new_object(pool);
+ if (obj == NULL) {
+ return NULL;
+ }
+
+ decl = (ngx_data_decl_t *) data;
+
+ while (decl->name.len) {
+
+ if (fields) {
+ value = fields->elts;
+
+ for (i = 0; i < fields->nelts; i++) {
+
+ if (decl->name.len == value[i].len
+ && ngx_strncmp(decl->name.data, value[i].data,
+ value[i].len)
+ == 0)
+ {
+ goto found;
+ }
+ }
+
+ decl++;
+ continue;
+ }
+
+found:
+
+ item = decl->handler(decl->data, pool, ctx);
+ if (item == NULL) {
+ return NULL;
+ }
+
+ if (item != NGX_DATA_DECLINE) {
+ ngx_data_add_item(obj, &decl->name, item);
+ }
+
+ decl++;
+ }
+
+ return obj;
+}
+
+
+ngx_data_item_t *
+ngx_data_number_handler(uintptr_t data, ngx_pool_t *pool, void *ctx)
+{
+ ngx_data_item_t *item;
+
+ item = ngx_data_new_integer(pool);
+ if (item == NULL) {
+ return NULL;
+ }
+
+ item->data.integer = data;
+
+ return item;
+}
+
+
+ngx_data_item_t *
+ngx_data_string_handler(uintptr_t data, ngx_pool_t *pool, void *ctx)
+{
+ ngx_str_t *value, *src;
+ ngx_data_item_t *item;
+
+ item = ngx_data_new_string(pool);
+ if (item == NULL) {
+ return NULL;
+ }
+
+ value = &item->data.string;
+
+ src = (ngx_str_t *) data;
+
+ value->len = src->len;
+
+ value->data = ngx_pstrdup(pool, src);
+ if (value->data == NULL) {
+ return NULL;
+ }
+
+ return item;
+}
+
+
+ngx_data_item_t *
+ngx_data_boolean_handler(uintptr_t data, ngx_pool_t *pool, void *ctx)
+{
+ ngx_data_item_t *item;
+
+ item = ngx_data_new_boolean(pool);
+ if (item == NULL) {
+ return NULL;
+ }
+
+ item->data.boolean = data;
+
+ return item;
+}
+
+
+ngx_data_item_t *
+ngx_data_time_handler(uintptr_t data, ngx_pool_t *pool, void *ctx)
+{
+ u_char *p;
+ ngx_tm_t tm;
+ ngx_str_t src;
+ ngx_time_t *tp;
+ u_char iso8601[sizeof("1974-01-19T13:00:00.000Z") - 1];
+
+ tp = (ngx_time_t *) data;
+
+ ngx_gmtime(tp->sec, &tm);
+
+ p = ngx_sprintf(iso8601, "%4d-%02d-%02dT%02d:%02d:%02d",
+ tm.ngx_tm_year, tm.ngx_tm_mon, tm.ngx_tm_mday,
+ tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec);
+
+ if (tp->msec) {
+ p = ngx_sprintf(p, ".%03ui", tp->msec);
+ }
+
+ *p++ = 'Z';
+
+ src.data = iso8601;
+ src.len = p - iso8601;
+
+ return ngx_data_string_handler((uintptr_t) &src, pool, NULL);
+}
+
+
+ngx_data_item_t *
+ngx_data_struct_int64_handler(uintptr_t data, ngx_pool_t *pool, void *ctx)
+{
+ ngx_data_item_t *item;
+
+ item = ngx_data_new_integer(pool);
+ if (item == NULL) {
+ return NULL;
+ }
+
+ item->data.integer = *(int64_t *) ((u_char *) ctx + data);
+
+ return item;
+}
+
+
+ngx_data_item_t *
+ngx_data_struct_int_handler(uintptr_t data, ngx_pool_t *pool, void *ctx)
+{
+ ngx_int_t value;
+
+ value = *(ngx_int_t *) ((u_char *) ctx + data);
+
+ return ngx_data_number_handler(value, pool, NULL);
+}
+
+
+ngx_data_item_t *
+ngx_data_struct_atomic_handler(uintptr_t data, ngx_pool_t *pool, void *ctx)
+{
+ ngx_data_item_t *item;
+
+ item = ngx_data_new_integer(pool);
+ if (item == NULL) {
+ return NULL;
+ }
+
+ item->data.integer = *(ngx_atomic_uint_t *) ((u_char *) ctx + data);
+
+ return item;
+}
+
+
+ngx_data_item_t *
+ngx_data_struct_str_handler(uintptr_t data, ngx_pool_t *pool, void *ctx)
+{
+ ngx_str_t *value, *src;
+ ngx_data_item_t *item;
+
+ item = ngx_data_new_string(pool);
+ if (item == NULL) {
+ return NULL;
+ }
+
+ value = &item->data.string;
+
+ src = (ngx_str_t *) ((u_char *) ctx + data);
+
+ value->len = src->len;
+
+ value->data = ngx_pstrdup(pool, src);
+ if (value->data == NULL) {
+ return NULL;
+ }
+
+ return item;
+}
+
+
+ngx_data_item_t *
+ngx_data_struct_boolean_handler(uintptr_t data, ngx_pool_t *pool, void *ctx)
+{
+ ngx_uint_t value;
+
+ value = *(ngx_uint_t *) ((u_char *) ctx + data);
+
+ return ngx_data_boolean_handler(value, pool, NULL);
+}
--- /dev/null
+
+/*
+ * Copyright (C) Nginx, Inc.
+ */
+
+
+#ifndef _NGX_DATA_H_INCLUDED_
+#define _NGX_DATA_H_INCLUDED_
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+typedef struct ngx_data_item_s ngx_data_item_t;
+
+
+typedef struct {
+ ngx_data_item_t *item;
+ ngx_data_item_t **next;
+} ngx_data_obj_t;
+
+
+struct ngx_data_item_s {
+ ngx_data_item_t *next;
+ ngx_str_t name;
+ ngx_uint_t type;
+
+ union {
+ ngx_data_obj_t object;
+ ngx_str_t string;
+ int64_t integer;
+ ngx_uint_t boolean;
+ } data;
+};
+
+
+ngx_data_item_t *ngx_data_new_item(ngx_pool_t *pool, ngx_uint_t type);
+
+void ngx_data_add_item(ngx_data_item_t *obj, ngx_str_t *name,
+ ngx_data_item_t *item);
+
+#define NGX_DATA_OBJECT_TYPE 0
+#define NGX_DATA_LIST_TYPE 1
+#define NGX_DATA_STRING_TYPE 2
+#define NGX_DATA_INTEGER_TYPE 3
+#define NGX_DATA_BOOLEAN_TYPE 4
+#define NGX_DATA_NULL_TYPE 5
+
+
+#define ngx_data_new_object(pool) \
+ ngx_data_new_item(pool, NGX_DATA_OBJECT_TYPE)
+#define ngx_data_new_list(pool) \
+ ngx_data_new_item(pool, NGX_DATA_LIST_TYPE)
+#define ngx_data_new_string(pool) \
+ ngx_data_new_item(pool, NGX_DATA_STRING_TYPE)
+#define ngx_data_new_integer(pool) \
+ ngx_data_new_item(pool, NGX_DATA_INTEGER_TYPE)
+#define ngx_data_new_boolean(pool) \
+ ngx_data_new_item(pool, NGX_DATA_BOOLEAN_TYPE)
+#define ngx_data_new_null(pool) \
+ ngx_data_new_item(pool, NGX_DATA_NULL_TYPE)
+
+
+typedef struct {
+ ngx_str_t name;
+ ngx_data_item_t *(*handler)(uintptr_t data, ngx_pool_t *pool, void *ctx);
+ uintptr_t data;
+} ngx_data_decl_t;
+
+#define ngx_data_null_decl { ngx_null_string, NULL, 0 }
+
+#define NGX_DATA_DECLINE (ngx_data_item_t *) -1
+
+
+ngx_data_item_t *ngx_data_obj_handler(uintptr_t data, ngx_pool_t *pool,
+ void *ctx);
+ngx_data_item_t *ngx_data_obj_fields_handler(uintptr_t data, ngx_pool_t *pool,
+ void *ctx, ngx_array_t *fields);
+
+ngx_data_item_t *ngx_data_number_handler(uintptr_t data, ngx_pool_t *pool,
+ void *ctx);
+ngx_data_item_t *ngx_data_string_handler(uintptr_t data, ngx_pool_t *pool,
+ void *ctx);
+ngx_data_item_t *ngx_data_boolean_handler(uintptr_t data, ngx_pool_t *pool,
+ void *ctx);
+ngx_data_item_t *ngx_data_time_handler(uintptr_t data, ngx_pool_t *pool,
+ void *ctx);
+
+ngx_data_item_t *ngx_data_struct_int64_handler(uintptr_t data, ngx_pool_t *pool,
+ void *ctx);
+ngx_data_item_t *ngx_data_struct_int_handler(uintptr_t data, ngx_pool_t *pool,
+ void *ctx);
+ngx_data_item_t *ngx_data_struct_atomic_handler(uintptr_t data,
+ ngx_pool_t *pool, void *ctx);
+ngx_data_item_t *ngx_data_struct_str_handler(uintptr_t data, ngx_pool_t *pool,
+ void *ctx);
+ngx_data_item_t *ngx_data_struct_boolean_handler(uintptr_t data,
+ ngx_pool_t *pool, void *ctx);
+
+#endif /* _NGX_DATA_H_INCLUDED_ */
--- /dev/null
+
+/*
+ * Copyright (C) Nginx, Inc.
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+typedef ssize_t (*ngx_json_length_pt)(ngx_data_item_t *item);
+typedef u_char *(*ngx_json_encode_pt)(u_char *p, ngx_data_item_t *item);
+
+
+typedef struct {
+ ngx_json_length_pt length;
+ ngx_json_encode_pt encode;
+} ngx_json_encode_t;
+
+
+static ssize_t ngx_json_obj_length(ngx_data_item_t *item);
+static ssize_t ngx_json_list_length(ngx_data_item_t *item);
+static ssize_t ngx_json_string_length(ngx_data_item_t *item);
+static ssize_t ngx_json_integer_length(ngx_data_item_t *item);
+static ssize_t ngx_json_boolean_length(ngx_data_item_t *item);
+static ssize_t ngx_json_null_length(ngx_data_item_t *item);
+
+static u_char *ngx_json_obj_encode(u_char *p, ngx_data_item_t *item);
+static u_char *ngx_json_list_encode(u_char *p, ngx_data_item_t *item);
+static u_char *ngx_json_string_encode(u_char *p, ngx_data_item_t *item);
+static u_char *ngx_json_integer_encode(u_char *p, ngx_data_item_t *item);
+static u_char *ngx_json_boolean_encode(u_char *p, ngx_data_item_t *item);
+static u_char *ngx_json_null_encode(u_char *p, ngx_data_item_t *item);
+
+
+static ngx_json_encode_t ngx_json_encode[] = {
+
+ /* NGX_DATA_OBJECT_TYPE */
+ { ngx_json_obj_length,
+ ngx_json_obj_encode },
+
+ /* NGX_DATA_LIST_TYPE */
+ { ngx_json_list_length,
+ ngx_json_list_encode },
+
+ /* NGX_DATA_STRING_TYPE */
+ { ngx_json_string_length,
+ ngx_json_string_encode },
+
+ /* NGX_DATA_INTEGER_TYPE */
+ { ngx_json_integer_length,
+ ngx_json_integer_encode },
+
+ /* NGX_DATA_BOOLEAN_TYPE */
+ { ngx_json_boolean_length,
+ ngx_json_boolean_encode },
+
+ /* NGX_DATA_NULL_TYPE */
+ { ngx_json_null_length,
+ ngx_json_null_encode },
+};
+
+
+ngx_buf_t *
+ngx_json_render(ngx_pool_t *pool, ngx_data_item_t *item)
+{
+ size_t length;
+ ngx_buf_t *buf;
+
+ length = ngx_json_encode[item->type].length(item);
+ if (length == (size_t) NGX_ERROR) {
+ return NULL;
+ }
+
+ buf = ngx_create_temp_buf(pool, length);
+ if (buf == NULL) {
+ return NULL;
+ }
+
+ buf->last = ngx_json_encode[item->type].encode(buf->last, item);
+
+ return buf;
+}
+
+
+static ssize_t
+ngx_json_obj_length(ngx_data_item_t *item)
+{
+ size_t len, total;
+ ngx_data_obj_t *obj;
+ ngx_data_item_t *i;
+
+ obj = &item->data.object;
+ total = sizeof("{}") - 1;
+ i = obj->item;
+
+ if (i) {
+ for ( ;; ) {
+ len = sizeof("\"\":") - 1 + i->name.len
+ + ngx_escape_json(NULL, i->name.data, i->name.len);
+
+ if (total > NGX_MAX_SIZE_T_VALUE - len) {
+ return NGX_ERROR;
+ }
+
+ total += len;
+
+ len = ngx_json_encode[i->type].length(i);
+ if (len == (size_t) NGX_ERROR) {
+ return NGX_ERROR;
+ }
+
+ if (total > NGX_MAX_SIZE_T_VALUE - len) {
+ return NGX_ERROR;
+ }
+
+ total += len;
+
+ i = i->next;
+
+ if (i == NULL) {
+ break;
+ }
+
+ if (total > NGX_MAX_SIZE_T_VALUE - (sizeof(",") - 1)) {
+ return NGX_ERROR;
+ }
+
+ total += sizeof(",") - 1;
+ }
+ }
+
+ return total;
+}
+
+
+static u_char *
+ngx_json_obj_encode(u_char *p, ngx_data_item_t *item)
+{
+ ngx_data_obj_t *obj;
+ ngx_data_item_t *i;
+
+ obj = &item->data.object;
+ i = obj->item;
+
+ *p++ = '{';
+
+ if (i) {
+ for ( ;; ) {
+ *p++ = '"';
+
+ p = (u_char *) ngx_escape_json(p, i->name.data, i->name.len);
+
+ *p++ = '"';
+ *p++ = ':';
+
+ p = ngx_json_encode[i->type].encode(p, i);
+
+ i = i->next;
+
+ if (i == NULL) {
+ break;
+ }
+
+ *p++ = ',';
+ }
+ }
+
+ *p++ = '}';
+
+ return p;
+}
+
+
+static ssize_t
+ngx_json_list_length(ngx_data_item_t *item)
+{
+ size_t len, total;
+ ngx_data_obj_t *obj;
+ ngx_data_item_t *i;
+
+ obj = &item->data.object;
+ total = sizeof("[]") - 1;
+ i = obj->item;
+
+ if (i) {
+ for ( ;; ) {
+ len = ngx_json_encode[i->type].length(i);
+ if (len == (size_t) NGX_ERROR) {
+ return NGX_ERROR;
+ }
+
+ if (total > NGX_MAX_SIZE_T_VALUE - len) {
+ return NGX_ERROR;
+ }
+
+ total += len;
+
+ i = i->next;
+
+ if (i == NULL) {
+ break;
+ }
+
+ if (total > NGX_MAX_SIZE_T_VALUE - (sizeof(",") - 1)) {
+ return NGX_ERROR;
+ }
+
+ total += sizeof(",") - 1;
+ }
+ }
+
+ return total;
+}
+
+
+static u_char *
+ngx_json_list_encode(u_char *p, ngx_data_item_t *item)
+{
+ ngx_data_obj_t *obj;
+ ngx_data_item_t *i;
+
+ obj = &item->data.object;
+ i = obj->item;
+
+ *p++ = '[';
+
+ if (i) {
+ for ( ;; ) {
+ p = ngx_json_encode[i->type].encode(p, i);
+
+ i = i->next;
+
+ if (i == NULL) {
+ break;
+ }
+
+ *p++ = ',';
+ }
+ }
+
+ *p++ = ']';
+
+ return p;
+}
+
+
+static ssize_t
+ngx_json_string_length(ngx_data_item_t *item)
+{
+ ngx_str_t *str;
+
+ str = &item->data.string;
+
+ return sizeof("\"\"") - 1 + str->len
+ + ngx_escape_json(NULL, str->data, str->len);
+}
+
+
+static u_char *
+ngx_json_string_encode(u_char *p, ngx_data_item_t *item)
+{
+ ngx_str_t *str;
+
+ str = &item->data.string;
+
+ *p++ = '"';
+
+ p = (u_char *) ngx_escape_json(p, str->data, str->len);
+
+ *p++ = '"';
+
+ return p;
+}
+
+
+static ssize_t
+ngx_json_integer_length(ngx_data_item_t *item)
+{
+ return NGX_INT64_LEN;
+}
+
+
+static u_char *
+ngx_json_integer_encode(u_char *p, ngx_data_item_t *item)
+{
+ return ngx_sprintf(p, "%L", item->data.integer);
+}
+
+
+static ssize_t
+ngx_json_boolean_length(ngx_data_item_t *item)
+{
+ return sizeof("false") - 1;
+}
+
+
+static u_char *
+ngx_json_boolean_encode(u_char *p, ngx_data_item_t *item)
+{
+ return item->data.boolean ? ngx_cpymem(p, "true", 4)
+ : ngx_cpymem(p, "false", 5);
+}
+
+
+static ssize_t
+ngx_json_null_length(ngx_data_item_t *item)
+{
+ return sizeof("null") - 1;
+}
+
+
+static u_char *
+ngx_json_null_encode(u_char *p, ngx_data_item_t *item)
+{
+ return ngx_cpymem(p, "null", 4);
+}
--- /dev/null
+
+/*
+ * Copyright (C) Nginx, Inc.
+ */
+
+
+#ifndef _NGX_JSON_H_INCLUDED_
+#define _NGX_JSON_H_INCLUDED_
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+ngx_buf_t *ngx_json_render(ngx_pool_t *pool, ngx_data_item_t *item);
+
+
+#endif /* _NGX_JSON_H_INCLUDED_ */