| Index: third_party/grpc/src/core/json/json_writer.c
|
| diff --git a/third_party/grpc/src/core/json/json_writer.c b/third_party/grpc/src/core/json/json_writer.c
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..326ec2d431f0613b131f32941c39674802023750
|
| --- /dev/null
|
| +++ b/third_party/grpc/src/core/json/json_writer.c
|
| @@ -0,0 +1,258 @@
|
| +/*
|
| + *
|
| + * Copyright 2015, Google Inc.
|
| + * All rights reserved.
|
| + *
|
| + * Redistribution and use in source and binary forms, with or without
|
| + * modification, are permitted provided that the following conditions are
|
| + * met:
|
| + *
|
| + * * Redistributions of source code must retain the above copyright
|
| + * notice, this list of conditions and the following disclaimer.
|
| + * * Redistributions in binary form must reproduce the above
|
| + * copyright notice, this list of conditions and the following disclaimer
|
| + * in the documentation and/or other materials provided with the
|
| + * distribution.
|
| + * * Neither the name of Google Inc. nor the names of its
|
| + * contributors may be used to endorse or promote products derived from
|
| + * this software without specific prior written permission.
|
| + *
|
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| + *
|
| + */
|
| +
|
| +#include <string.h>
|
| +
|
| +#include <grpc/support/port_platform.h>
|
| +
|
| +#include "src/core/json/json_writer.h"
|
| +
|
| +static void json_writer_output_char(grpc_json_writer *writer, char c) {
|
| + writer->vtable->output_char(writer->userdata, c);
|
| +}
|
| +
|
| +static void json_writer_output_string(grpc_json_writer *writer,
|
| + const char *str) {
|
| + writer->vtable->output_string(writer->userdata, str);
|
| +}
|
| +
|
| +static void json_writer_output_string_with_len(grpc_json_writer *writer,
|
| + const char *str, size_t len) {
|
| + writer->vtable->output_string_with_len(writer->userdata, str, len);
|
| +}
|
| +
|
| +void grpc_json_writer_init(grpc_json_writer *writer, int indent,
|
| + grpc_json_writer_vtable *vtable, void *userdata) {
|
| + memset(writer, 0, sizeof(*writer));
|
| + writer->container_empty = 1;
|
| + writer->indent = indent;
|
| + writer->vtable = vtable;
|
| + writer->userdata = userdata;
|
| +}
|
| +
|
| +static void json_writer_output_indent(grpc_json_writer *writer) {
|
| + static const char spacesstr[] =
|
| + " "
|
| + " "
|
| + " "
|
| + " ";
|
| +
|
| + unsigned spaces = (unsigned)(writer->depth * writer->indent);
|
| +
|
| + if (writer->indent == 0) return;
|
| +
|
| + if (writer->got_key) {
|
| + json_writer_output_char(writer, ' ');
|
| + return;
|
| + }
|
| +
|
| + while (spaces >= (sizeof(spacesstr) - 1)) {
|
| + json_writer_output_string_with_len(writer, spacesstr,
|
| + sizeof(spacesstr) - 1);
|
| + spaces -= (unsigned)(sizeof(spacesstr) - 1);
|
| + }
|
| +
|
| + if (spaces == 0) return;
|
| +
|
| + json_writer_output_string_with_len(
|
| + writer, spacesstr + sizeof(spacesstr) - 1 - spaces, spaces);
|
| +}
|
| +
|
| +static void json_writer_value_end(grpc_json_writer *writer) {
|
| + if (writer->container_empty) {
|
| + writer->container_empty = 0;
|
| + if ((writer->indent == 0) || (writer->depth == 0)) return;
|
| + json_writer_output_char(writer, '\n');
|
| + } else {
|
| + json_writer_output_char(writer, ',');
|
| + if (writer->indent == 0) return;
|
| + json_writer_output_char(writer, '\n');
|
| + }
|
| +}
|
| +
|
| +static void json_writer_escape_utf16(grpc_json_writer *writer, uint16_t utf16) {
|
| + static const char hex[] = "0123456789abcdef";
|
| +
|
| + json_writer_output_string_with_len(writer, "\\u", 2);
|
| + json_writer_output_char(writer, hex[(utf16 >> 12) & 0x0f]);
|
| + json_writer_output_char(writer, hex[(utf16 >> 8) & 0x0f]);
|
| + json_writer_output_char(writer, hex[(utf16 >> 4) & 0x0f]);
|
| + json_writer_output_char(writer, hex[(utf16)&0x0f]);
|
| +}
|
| +
|
| +static void json_writer_escape_string(grpc_json_writer *writer,
|
| + const char *string) {
|
| + json_writer_output_char(writer, '"');
|
| +
|
| + for (;;) {
|
| + uint8_t c = (uint8_t)*string++;
|
| + if (c == 0) {
|
| + break;
|
| + } else if ((c >= 32) && (c <= 126)) {
|
| + if ((c == '\\') || (c == '"')) json_writer_output_char(writer, '\\');
|
| + json_writer_output_char(writer, (char)c);
|
| + } else if ((c < 32) || (c == 127)) {
|
| + switch (c) {
|
| + case '\b':
|
| + json_writer_output_string_with_len(writer, "\\b", 2);
|
| + break;
|
| + case '\f':
|
| + json_writer_output_string_with_len(writer, "\\f", 2);
|
| + break;
|
| + case '\n':
|
| + json_writer_output_string_with_len(writer, "\\n", 2);
|
| + break;
|
| + case '\r':
|
| + json_writer_output_string_with_len(writer, "\\r", 2);
|
| + break;
|
| + case '\t':
|
| + json_writer_output_string_with_len(writer, "\\t", 2);
|
| + break;
|
| + default:
|
| + json_writer_escape_utf16(writer, c);
|
| + break;
|
| + }
|
| + } else {
|
| + uint32_t utf32 = 0;
|
| + int extra = 0;
|
| + int i;
|
| + int valid = 1;
|
| + if ((c & 0xe0) == 0xc0) {
|
| + utf32 = c & 0x1f;
|
| + extra = 1;
|
| + } else if ((c & 0xf0) == 0xe0) {
|
| + utf32 = c & 0x0f;
|
| + extra = 2;
|
| + } else if ((c & 0xf8) == 0xf0) {
|
| + utf32 = c & 0x07;
|
| + extra = 3;
|
| + } else {
|
| + break;
|
| + }
|
| + for (i = 0; i < extra; i++) {
|
| + utf32 <<= 6;
|
| + c = (uint8_t)(*string++);
|
| + /* Breaks out and bail on any invalid UTF-8 sequence, including \0. */
|
| + if ((c & 0xc0) != 0x80) {
|
| + valid = 0;
|
| + break;
|
| + }
|
| + utf32 |= c & 0x3f;
|
| + }
|
| + if (!valid) break;
|
| + /* The range 0xd800 - 0xdfff is reserved by the surrogates ad vitam.
|
| + * Any other range is technically reserved for future usage, so if we
|
| + * don't want the software to break in the future, we have to allow
|
| + * anything else. The first non-unicode character is 0x110000. */
|
| + if (((utf32 >= 0xd800) && (utf32 <= 0xdfff)) || (utf32 >= 0x110000))
|
| + break;
|
| + if (utf32 >= 0x10000) {
|
| + /* If utf32 contains a character that is above 0xffff, it needs to be
|
| + * broken down into a utf-16 surrogate pair. A surrogate pair is first
|
| + * a high surrogate, followed by a low surrogate. Each surrogate holds
|
| + * 10 bits of usable data, thus allowing a total of 20 bits of data.
|
| + * The high surrogate marker is 0xd800, while the low surrogate marker
|
| + * is 0xdc00. The low 10 bits of each will be the usable data.
|
| + *
|
| + * After re-combining the 20 bits of data, one has to add 0x10000 to
|
| + * the resulting value, in order to obtain the original character.
|
| + * This is obviously because the range 0x0000 - 0xffff can be written
|
| + * without any special trick.
|
| + *
|
| + * Since 0x10ffff is the highest allowed character, we're working in
|
| + * the range 0x00000 - 0xfffff after we decrement it by 0x10000.
|
| + * That range is exactly 20 bits.
|
| + */
|
| + utf32 -= 0x10000;
|
| + json_writer_escape_utf16(writer, (uint16_t)(0xd800 | (utf32 >> 10)));
|
| + json_writer_escape_utf16(writer, (uint16_t)(0xdc00 | (utf32 & 0x3ff)));
|
| + } else {
|
| + json_writer_escape_utf16(writer, (uint16_t)utf32);
|
| + }
|
| + }
|
| + }
|
| +
|
| + json_writer_output_char(writer, '"');
|
| +}
|
| +
|
| +void grpc_json_writer_container_begins(grpc_json_writer *writer,
|
| + grpc_json_type type) {
|
| + if (!writer->got_key) json_writer_value_end(writer);
|
| + json_writer_output_indent(writer);
|
| + json_writer_output_char(writer, type == GRPC_JSON_OBJECT ? '{' : '[');
|
| + writer->container_empty = 1;
|
| + writer->got_key = 0;
|
| + writer->depth++;
|
| +}
|
| +
|
| +void grpc_json_writer_container_ends(grpc_json_writer *writer,
|
| + grpc_json_type type) {
|
| + if (writer->indent && !writer->container_empty)
|
| + json_writer_output_char(writer, '\n');
|
| + writer->depth--;
|
| + if (!writer->container_empty) json_writer_output_indent(writer);
|
| + json_writer_output_char(writer, type == GRPC_JSON_OBJECT ? '}' : ']');
|
| + writer->container_empty = 0;
|
| + writer->got_key = 0;
|
| +}
|
| +
|
| +void grpc_json_writer_object_key(grpc_json_writer *writer, const char *string) {
|
| + json_writer_value_end(writer);
|
| + json_writer_output_indent(writer);
|
| + json_writer_escape_string(writer, string);
|
| + json_writer_output_char(writer, ':');
|
| + writer->got_key = 1;
|
| +}
|
| +
|
| +void grpc_json_writer_value_raw(grpc_json_writer *writer, const char *string) {
|
| + if (!writer->got_key) json_writer_value_end(writer);
|
| + json_writer_output_indent(writer);
|
| + json_writer_output_string(writer, string);
|
| + writer->got_key = 0;
|
| +}
|
| +
|
| +void grpc_json_writer_value_raw_with_len(grpc_json_writer *writer,
|
| + const char *string, size_t len) {
|
| + if (!writer->got_key) json_writer_value_end(writer);
|
| + json_writer_output_indent(writer);
|
| + json_writer_output_string_with_len(writer, string, len);
|
| + writer->got_key = 0;
|
| +}
|
| +
|
| +void grpc_json_writer_value_string(grpc_json_writer *writer,
|
| + const char *string) {
|
| + if (!writer->got_key) json_writer_value_end(writer);
|
| + json_writer_output_indent(writer);
|
| + json_writer_escape_string(writer, string);
|
| + writer->got_key = 0;
|
| +}
|
|
|