1ffe3c632Sopenharmony_ci<?php 2ffe3c632Sopenharmony_ci 3ffe3c632Sopenharmony_ci// Protocol Buffers - Google's data interchange format 4ffe3c632Sopenharmony_ci// Copyright 2008 Google Inc. All rights reserved. 5ffe3c632Sopenharmony_ci// https://developers.google.com/protocol-buffers/ 6ffe3c632Sopenharmony_ci// 7ffe3c632Sopenharmony_ci// Redistribution and use in source and binary forms, with or without 8ffe3c632Sopenharmony_ci// modification, are permitted provided that the following conditions are 9ffe3c632Sopenharmony_ci// met: 10ffe3c632Sopenharmony_ci// 11ffe3c632Sopenharmony_ci// * Redistributions of source code must retain the above copyright 12ffe3c632Sopenharmony_ci// notice, this list of conditions and the following disclaimer. 13ffe3c632Sopenharmony_ci// * Redistributions in binary form must reproduce the above 14ffe3c632Sopenharmony_ci// copyright notice, this list of conditions and the following disclaimer 15ffe3c632Sopenharmony_ci// in the documentation and/or other materials provided with the 16ffe3c632Sopenharmony_ci// distribution. 17ffe3c632Sopenharmony_ci// * Neither the name of Google Inc. nor the names of its 18ffe3c632Sopenharmony_ci// contributors may be used to endorse or promote products derived from 19ffe3c632Sopenharmony_ci// this software without specific prior written permission. 20ffe3c632Sopenharmony_ci// 21ffe3c632Sopenharmony_ci// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22ffe3c632Sopenharmony_ci// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23ffe3c632Sopenharmony_ci// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24ffe3c632Sopenharmony_ci// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25ffe3c632Sopenharmony_ci// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26ffe3c632Sopenharmony_ci// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27ffe3c632Sopenharmony_ci// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28ffe3c632Sopenharmony_ci// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29ffe3c632Sopenharmony_ci// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30ffe3c632Sopenharmony_ci// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31ffe3c632Sopenharmony_ci// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32ffe3c632Sopenharmony_ci 33ffe3c632Sopenharmony_cinamespace Google\Protobuf\Internal; 34ffe3c632Sopenharmony_ci 35ffe3c632Sopenharmony_ciclass GPBJsonWire 36ffe3c632Sopenharmony_ci{ 37ffe3c632Sopenharmony_ci 38ffe3c632Sopenharmony_ci public static function serializeFieldToStream( 39ffe3c632Sopenharmony_ci $value, 40ffe3c632Sopenharmony_ci $field, 41ffe3c632Sopenharmony_ci &$output, $has_field_name = true) 42ffe3c632Sopenharmony_ci { 43ffe3c632Sopenharmony_ci if ($has_field_name) { 44ffe3c632Sopenharmony_ci $output->writeRaw("\"", 1); 45ffe3c632Sopenharmony_ci $field_name = GPBJsonWire::formatFieldName($field); 46ffe3c632Sopenharmony_ci $output->writeRaw($field_name, strlen($field_name)); 47ffe3c632Sopenharmony_ci $output->writeRaw("\":", 2); 48ffe3c632Sopenharmony_ci } 49ffe3c632Sopenharmony_ci return static::serializeFieldValueToStream( 50ffe3c632Sopenharmony_ci $value, 51ffe3c632Sopenharmony_ci $field, 52ffe3c632Sopenharmony_ci $output, 53ffe3c632Sopenharmony_ci !$has_field_name); 54ffe3c632Sopenharmony_ci } 55ffe3c632Sopenharmony_ci 56ffe3c632Sopenharmony_ci public static function serializeFieldValueToStream( 57ffe3c632Sopenharmony_ci $values, 58ffe3c632Sopenharmony_ci $field, 59ffe3c632Sopenharmony_ci &$output, 60ffe3c632Sopenharmony_ci $is_well_known = false) 61ffe3c632Sopenharmony_ci { 62ffe3c632Sopenharmony_ci if ($field->isMap()) { 63ffe3c632Sopenharmony_ci $output->writeRaw("{", 1); 64ffe3c632Sopenharmony_ci $first = true; 65ffe3c632Sopenharmony_ci $map_entry = $field->getMessageType(); 66ffe3c632Sopenharmony_ci $key_field = $map_entry->getFieldByNumber(1); 67ffe3c632Sopenharmony_ci $value_field = $map_entry->getFieldByNumber(2); 68ffe3c632Sopenharmony_ci 69ffe3c632Sopenharmony_ci switch ($key_field->getType()) { 70ffe3c632Sopenharmony_ci case GPBType::STRING: 71ffe3c632Sopenharmony_ci case GPBType::SFIXED64: 72ffe3c632Sopenharmony_ci case GPBType::INT64: 73ffe3c632Sopenharmony_ci case GPBType::SINT64: 74ffe3c632Sopenharmony_ci case GPBType::FIXED64: 75ffe3c632Sopenharmony_ci case GPBType::UINT64: 76ffe3c632Sopenharmony_ci $additional_quote = false; 77ffe3c632Sopenharmony_ci break; 78ffe3c632Sopenharmony_ci default: 79ffe3c632Sopenharmony_ci $additional_quote = true; 80ffe3c632Sopenharmony_ci } 81ffe3c632Sopenharmony_ci 82ffe3c632Sopenharmony_ci foreach ($values as $key => $value) { 83ffe3c632Sopenharmony_ci if ($first) { 84ffe3c632Sopenharmony_ci $first = false; 85ffe3c632Sopenharmony_ci } else { 86ffe3c632Sopenharmony_ci $output->writeRaw(",", 1); 87ffe3c632Sopenharmony_ci } 88ffe3c632Sopenharmony_ci if ($additional_quote) { 89ffe3c632Sopenharmony_ci $output->writeRaw("\"", 1); 90ffe3c632Sopenharmony_ci } 91ffe3c632Sopenharmony_ci if (!static::serializeSingularFieldValueToStream( 92ffe3c632Sopenharmony_ci $key, 93ffe3c632Sopenharmony_ci $key_field, 94ffe3c632Sopenharmony_ci $output, 95ffe3c632Sopenharmony_ci $is_well_known)) { 96ffe3c632Sopenharmony_ci return false; 97ffe3c632Sopenharmony_ci } 98ffe3c632Sopenharmony_ci if ($additional_quote) { 99ffe3c632Sopenharmony_ci $output->writeRaw("\"", 1); 100ffe3c632Sopenharmony_ci } 101ffe3c632Sopenharmony_ci $output->writeRaw(":", 1); 102ffe3c632Sopenharmony_ci if (!static::serializeSingularFieldValueToStream( 103ffe3c632Sopenharmony_ci $value, 104ffe3c632Sopenharmony_ci $value_field, 105ffe3c632Sopenharmony_ci $output, 106ffe3c632Sopenharmony_ci $is_well_known)) { 107ffe3c632Sopenharmony_ci return false; 108ffe3c632Sopenharmony_ci } 109ffe3c632Sopenharmony_ci } 110ffe3c632Sopenharmony_ci $output->writeRaw("}", 1); 111ffe3c632Sopenharmony_ci return true; 112ffe3c632Sopenharmony_ci } elseif ($field->isRepeated()) { 113ffe3c632Sopenharmony_ci $output->writeRaw("[", 1); 114ffe3c632Sopenharmony_ci $first = true; 115ffe3c632Sopenharmony_ci foreach ($values as $value) { 116ffe3c632Sopenharmony_ci if ($first) { 117ffe3c632Sopenharmony_ci $first = false; 118ffe3c632Sopenharmony_ci } else { 119ffe3c632Sopenharmony_ci $output->writeRaw(",", 1); 120ffe3c632Sopenharmony_ci } 121ffe3c632Sopenharmony_ci if (!static::serializeSingularFieldValueToStream( 122ffe3c632Sopenharmony_ci $value, 123ffe3c632Sopenharmony_ci $field, 124ffe3c632Sopenharmony_ci $output, 125ffe3c632Sopenharmony_ci $is_well_known)) { 126ffe3c632Sopenharmony_ci return false; 127ffe3c632Sopenharmony_ci } 128ffe3c632Sopenharmony_ci } 129ffe3c632Sopenharmony_ci $output->writeRaw("]", 1); 130ffe3c632Sopenharmony_ci return true; 131ffe3c632Sopenharmony_ci } else { 132ffe3c632Sopenharmony_ci return static::serializeSingularFieldValueToStream( 133ffe3c632Sopenharmony_ci $values, 134ffe3c632Sopenharmony_ci $field, 135ffe3c632Sopenharmony_ci $output, 136ffe3c632Sopenharmony_ci $is_well_known); 137ffe3c632Sopenharmony_ci } 138ffe3c632Sopenharmony_ci } 139ffe3c632Sopenharmony_ci 140ffe3c632Sopenharmony_ci private static function serializeSingularFieldValueToStream( 141ffe3c632Sopenharmony_ci $value, 142ffe3c632Sopenharmony_ci $field, 143ffe3c632Sopenharmony_ci &$output, $is_well_known = false) 144ffe3c632Sopenharmony_ci { 145ffe3c632Sopenharmony_ci switch ($field->getType()) { 146ffe3c632Sopenharmony_ci case GPBType::SFIXED32: 147ffe3c632Sopenharmony_ci case GPBType::SINT32: 148ffe3c632Sopenharmony_ci case GPBType::INT32: 149ffe3c632Sopenharmony_ci $str_value = strval($value); 150ffe3c632Sopenharmony_ci $output->writeRaw($str_value, strlen($str_value)); 151ffe3c632Sopenharmony_ci break; 152ffe3c632Sopenharmony_ci case GPBType::FIXED32: 153ffe3c632Sopenharmony_ci case GPBType::UINT32: 154ffe3c632Sopenharmony_ci if ($value < 0) { 155ffe3c632Sopenharmony_ci $value = bcadd($value, "4294967296"); 156ffe3c632Sopenharmony_ci } 157ffe3c632Sopenharmony_ci $str_value = strval($value); 158ffe3c632Sopenharmony_ci $output->writeRaw($str_value, strlen($str_value)); 159ffe3c632Sopenharmony_ci break; 160ffe3c632Sopenharmony_ci case GPBType::FIXED64: 161ffe3c632Sopenharmony_ci case GPBType::UINT64: 162ffe3c632Sopenharmony_ci if ($value < 0) { 163ffe3c632Sopenharmony_ci $value = bcadd($value, "18446744073709551616"); 164ffe3c632Sopenharmony_ci } 165ffe3c632Sopenharmony_ci // Intentional fall through. 166ffe3c632Sopenharmony_ci case GPBType::SFIXED64: 167ffe3c632Sopenharmony_ci case GPBType::INT64: 168ffe3c632Sopenharmony_ci case GPBType::SINT64: 169ffe3c632Sopenharmony_ci $output->writeRaw("\"", 1); 170ffe3c632Sopenharmony_ci $str_value = strval($value); 171ffe3c632Sopenharmony_ci $output->writeRaw($str_value, strlen($str_value)); 172ffe3c632Sopenharmony_ci $output->writeRaw("\"", 1); 173ffe3c632Sopenharmony_ci break; 174ffe3c632Sopenharmony_ci case GPBType::FLOAT: 175ffe3c632Sopenharmony_ci if (is_nan($value)) { 176ffe3c632Sopenharmony_ci $str_value = "\"NaN\""; 177ffe3c632Sopenharmony_ci } elseif ($value === INF) { 178ffe3c632Sopenharmony_ci $str_value = "\"Infinity\""; 179ffe3c632Sopenharmony_ci } elseif ($value === -INF) { 180ffe3c632Sopenharmony_ci $str_value = "\"-Infinity\""; 181ffe3c632Sopenharmony_ci } else { 182ffe3c632Sopenharmony_ci $str_value = sprintf("%.8g", $value); 183ffe3c632Sopenharmony_ci } 184ffe3c632Sopenharmony_ci $output->writeRaw($str_value, strlen($str_value)); 185ffe3c632Sopenharmony_ci break; 186ffe3c632Sopenharmony_ci case GPBType::DOUBLE: 187ffe3c632Sopenharmony_ci if (is_nan($value)) { 188ffe3c632Sopenharmony_ci $str_value = "\"NaN\""; 189ffe3c632Sopenharmony_ci } elseif ($value === INF) { 190ffe3c632Sopenharmony_ci $str_value = "\"Infinity\""; 191ffe3c632Sopenharmony_ci } elseif ($value === -INF) { 192ffe3c632Sopenharmony_ci $str_value = "\"-Infinity\""; 193ffe3c632Sopenharmony_ci } else { 194ffe3c632Sopenharmony_ci $str_value = sprintf("%.17g", $value); 195ffe3c632Sopenharmony_ci } 196ffe3c632Sopenharmony_ci $output->writeRaw($str_value, strlen($str_value)); 197ffe3c632Sopenharmony_ci break; 198ffe3c632Sopenharmony_ci case GPBType::ENUM: 199ffe3c632Sopenharmony_ci $enum_desc = $field->getEnumType(); 200ffe3c632Sopenharmony_ci if ($enum_desc->getClass() === "Google\Protobuf\NullValue") { 201ffe3c632Sopenharmony_ci $output->writeRaw("null", 4); 202ffe3c632Sopenharmony_ci break; 203ffe3c632Sopenharmony_ci } 204ffe3c632Sopenharmony_ci $enum_value_desc = $enum_desc->getValueByNumber($value); 205ffe3c632Sopenharmony_ci if (!is_null($enum_value_desc)) { 206ffe3c632Sopenharmony_ci $str_value = $enum_value_desc->getName(); 207ffe3c632Sopenharmony_ci $output->writeRaw("\"", 1); 208ffe3c632Sopenharmony_ci $output->writeRaw($str_value, strlen($str_value)); 209ffe3c632Sopenharmony_ci $output->writeRaw("\"", 1); 210ffe3c632Sopenharmony_ci } else { 211ffe3c632Sopenharmony_ci $str_value = strval($value); 212ffe3c632Sopenharmony_ci $output->writeRaw($str_value, strlen($str_value)); 213ffe3c632Sopenharmony_ci } 214ffe3c632Sopenharmony_ci break; 215ffe3c632Sopenharmony_ci case GPBType::BOOL: 216ffe3c632Sopenharmony_ci if ($value) { 217ffe3c632Sopenharmony_ci $output->writeRaw("true", 4); 218ffe3c632Sopenharmony_ci } else { 219ffe3c632Sopenharmony_ci $output->writeRaw("false", 5); 220ffe3c632Sopenharmony_ci } 221ffe3c632Sopenharmony_ci break; 222ffe3c632Sopenharmony_ci case GPBType::BYTES: 223ffe3c632Sopenharmony_ci $bytes_value = base64_encode($value); 224ffe3c632Sopenharmony_ci $output->writeRaw("\"", 1); 225ffe3c632Sopenharmony_ci $output->writeRaw($bytes_value, strlen($bytes_value)); 226ffe3c632Sopenharmony_ci $output->writeRaw("\"", 1); 227ffe3c632Sopenharmony_ci break; 228ffe3c632Sopenharmony_ci case GPBType::STRING: 229ffe3c632Sopenharmony_ci $value = json_encode($value, JSON_UNESCAPED_UNICODE); 230ffe3c632Sopenharmony_ci $output->writeRaw($value, strlen($value)); 231ffe3c632Sopenharmony_ci break; 232ffe3c632Sopenharmony_ci // case GPBType::GROUP: 233ffe3c632Sopenharmony_ci // echo "GROUP\xA"; 234ffe3c632Sopenharmony_ci // trigger_error("Not implemented.", E_ERROR); 235ffe3c632Sopenharmony_ci // break; 236ffe3c632Sopenharmony_ci case GPBType::MESSAGE: 237ffe3c632Sopenharmony_ci $value->serializeToJsonStream($output); 238ffe3c632Sopenharmony_ci break; 239ffe3c632Sopenharmony_ci default: 240ffe3c632Sopenharmony_ci user_error("Unsupported type."); 241ffe3c632Sopenharmony_ci return false; 242ffe3c632Sopenharmony_ci } 243ffe3c632Sopenharmony_ci return true; 244ffe3c632Sopenharmony_ci } 245ffe3c632Sopenharmony_ci 246ffe3c632Sopenharmony_ci private static function formatFieldName($field) 247ffe3c632Sopenharmony_ci { 248ffe3c632Sopenharmony_ci return $field->getJsonName(); 249ffe3c632Sopenharmony_ci } 250ffe3c632Sopenharmony_ci 251ffe3c632Sopenharmony_ci // Used for escaping control chars in strings. 252ffe3c632Sopenharmony_ci private static $k_control_char_limit = 0x20; 253ffe3c632Sopenharmony_ci 254ffe3c632Sopenharmony_ci private static function jsonNiceEscape($c) 255ffe3c632Sopenharmony_ci { 256ffe3c632Sopenharmony_ci switch ($c) { 257ffe3c632Sopenharmony_ci case '"': return "\\\""; 258ffe3c632Sopenharmony_ci case '\\': return "\\\\"; 259ffe3c632Sopenharmony_ci case '/': return "\\/"; 260ffe3c632Sopenharmony_ci case '\b': return "\\b"; 261ffe3c632Sopenharmony_ci case '\f': return "\\f"; 262ffe3c632Sopenharmony_ci case '\n': return "\\n"; 263ffe3c632Sopenharmony_ci case '\r': return "\\r"; 264ffe3c632Sopenharmony_ci case '\t': return "\\t"; 265ffe3c632Sopenharmony_ci default: return NULL; 266ffe3c632Sopenharmony_ci } 267ffe3c632Sopenharmony_ci } 268ffe3c632Sopenharmony_ci 269ffe3c632Sopenharmony_ci private static function isJsonEscaped($c) 270ffe3c632Sopenharmony_ci { 271ffe3c632Sopenharmony_ci // See RFC 4627. 272ffe3c632Sopenharmony_ci return $c < chr($k_control_char_limit) || $c === "\"" || $c === "\\"; 273ffe3c632Sopenharmony_ci } 274ffe3c632Sopenharmony_ci 275ffe3c632Sopenharmony_ci public static function escapedJson($value) 276ffe3c632Sopenharmony_ci { 277ffe3c632Sopenharmony_ci $escaped_value = ""; 278ffe3c632Sopenharmony_ci $unescaped_run = ""; 279ffe3c632Sopenharmony_ci for ($i = 0; $i < strlen($value); $i++) { 280ffe3c632Sopenharmony_ci $c = $value[$i]; 281ffe3c632Sopenharmony_ci // Handle escaping. 282ffe3c632Sopenharmony_ci if (static::isJsonEscaped($c)) { 283ffe3c632Sopenharmony_ci // Use a "nice" escape, like \n, if one exists for this 284ffe3c632Sopenharmony_ci // character. 285ffe3c632Sopenharmony_ci $escape = static::jsonNiceEscape($c); 286ffe3c632Sopenharmony_ci if (is_null($escape)) { 287ffe3c632Sopenharmony_ci $escape = "\\u00" . bin2hex($c); 288ffe3c632Sopenharmony_ci } 289ffe3c632Sopenharmony_ci if ($unescaped_run !== "") { 290ffe3c632Sopenharmony_ci $escaped_value .= $unescaped_run; 291ffe3c632Sopenharmony_ci $unescaped_run = ""; 292ffe3c632Sopenharmony_ci } 293ffe3c632Sopenharmony_ci $escaped_value .= $escape; 294ffe3c632Sopenharmony_ci } else { 295ffe3c632Sopenharmony_ci if ($unescaped_run === "") { 296ffe3c632Sopenharmony_ci $unescaped_run .= $c; 297ffe3c632Sopenharmony_ci } 298ffe3c632Sopenharmony_ci } 299ffe3c632Sopenharmony_ci } 300ffe3c632Sopenharmony_ci $escaped_value .= $unescaped_run; 301ffe3c632Sopenharmony_ci return $escaped_value; 302ffe3c632Sopenharmony_ci } 303ffe3c632Sopenharmony_ci 304ffe3c632Sopenharmony_ci} 305