mirror of
https://github.com/firebase/firebase-ios-sdk
synced 2026-11-09 22:36:01 +05:45
gRPC: replace Objective-C implementation with the new C++ implementation (#2068)
* Revert "Revert "gRPC: replace Objective-C implementation with the new C++ implementation (#1968)" (#2030)" This reverts commitea567dca47. * gRPC: fix bugs found during testing (#2039) All in `GrpcStream`: * make sure there are no pending completions when "finish" operation is enqueued; * always finish gRPC calls; * when connectivity changes, reset not just the calls, but the underlying channel as well. * Revert "Partially revert "Update CHANGELOG for Firestore v0.14.0 (#2025)" (#2031)" This reverts commitb2437b80f6. * Update changelog for v0.15.0. * gRPC: add gRPC wrapper classes to CMake build (#2015) * add a C++ equivalent of `FIRFirestoreVersionString`. This eliminates the only Objective-C dependency of `grpc_connection.mm` and allows making it a pure C++ file; * open-source `binary_to_array.py` script and use it in the build to embed `roots.pem` certificate file from gRPC into the Firestore binary. The embedded char array is then used to load certificate at runtime. * Revert local change -- do not enable sanitizers by default
This commit is contained in:
1 parent
12bdfc8b90
commit
8b1efabd82
61 files changed
+5647
-3298
No files matched your search
Executable
+282
@@ -0,0 +1,282 @@
|
||||
#!/usr/bin/env python2
|
||||
|
||||
# Copyright 2018 Google
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
"""Utility to convert binary data into a C/C++ array.
|
||||
|
||||
Usage: %s --input=input_file.bin [--output_source=output_source.cc]
|
||||
[--output_header=output_header.h] [--cpp_namespace=namespace]
|
||||
[--header_guard=HEADER_GUARD_TEXT] [--array=array_c_identifier]
|
||||
[--array_size=array_size_c_identifier] [--filename=override_filename]
|
||||
[--filename_identifier=filename_c_identifier]
|
||||
|
||||
By default, the output source file will be named the same as the input file,
|
||||
but with .cc as the extension; the output header file will be named the
|
||||
same as the input file but with .h as the extension.
|
||||
|
||||
By default, the data will be in an array named $NAME_data and the size will
|
||||
be in a constant named $NAME_length, and the filename will be stored in
|
||||
$NAME_filename. In all these cases, $NAME is the input filename (sans path and
|
||||
extension) with runs of non-alphanumeric characters changed to underscores. The
|
||||
header guard will be generated from the output header filename in a similar way.
|
||||
|
||||
By default, the data will be placed in the root namespace. If the data is placed
|
||||
in the root namespace, it will be declared as a C array (using extern "C" if
|
||||
compiled in C++ mode).
|
||||
|
||||
The actual size of $NAME_data is $NAME_length + 1, where it contains an extra
|
||||
0x00 at the end. When data is actually text, $NAME_data can be used as a valid C
|
||||
string directly.
|
||||
"""
|
||||
|
||||
from os import path
|
||||
from re import sub
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
|
||||
arg_parser = argparse.ArgumentParser()
|
||||
|
||||
arg_parser.add_argument("input", help="Input file containing binary data to embed")
|
||||
arg_parser.add_argument("--output_source",
|
||||
help="Output source file, defining the array data.")
|
||||
arg_parser.add_argument("--output_header",
|
||||
help="Output header file, declaring the array data.")
|
||||
arg_parser.add_argument("--array", help="Identifier for the array.")
|
||||
arg_parser.add_argument("--array_size", help="Identifier for the array size.")
|
||||
arg_parser.add_argument("--filename", help="Override file name in code.")
|
||||
arg_parser.add_argument("--filename_identifier", help="Where to put the filename.")
|
||||
arg_parser.add_argument("--header_guard",
|
||||
help="Header guard to #define in the output header.")
|
||||
arg_parser.add_argument("--cpp_namespace",
|
||||
help="C++ namespace to use. If blank, will generate a C array.")
|
||||
|
||||
# How many hex bytes to display in a line. Each "0x00, " takes 6 characters, so
|
||||
# a width of 12 lets us fit within 80 characters.
|
||||
WIDTH = 12
|
||||
|
||||
|
||||
def header(header_guard, namespaces, array_name, array_size_name, fileid):
|
||||
"""Return a C/C++ header for the given array.
|
||||
|
||||
Args:
|
||||
header_guard: Name of the HEADER_GUARD to define.
|
||||
namespaces: List of namespaces, outer to inner.
|
||||
array_name: Name of the array.
|
||||
array_size_name: Name of the array size constant.
|
||||
fileid: Name of the identifier containing the file name.
|
||||
|
||||
Returns:
|
||||
A list of strings containing the C/C++ header file, line-by-line.
|
||||
"""
|
||||
|
||||
data = []
|
||||
data.extend([
|
||||
"// Copyright 2018 Google Inc. All Rights Reserved.",
|
||||
"",
|
||||
"#ifndef %s" % header_guard,
|
||||
"#define %s" % header_guard,
|
||||
"",
|
||||
"#include <cstdlib>",
|
||||
""
|
||||
])
|
||||
if namespaces:
|
||||
data.extend([
|
||||
"namespace %s {" % ns for ns in namespaces
|
||||
])
|
||||
else:
|
||||
data.extend([
|
||||
"#if defined(__cplusplus)",
|
||||
"extern \"C\" {",
|
||||
"#endif // defined(__cplusplus)"])
|
||||
|
||||
data.extend([
|
||||
"",
|
||||
"extern const size_t %s;" % array_size_name,
|
||||
"extern const unsigned char %s[];" % array_name,
|
||||
"extern const char %s[];" % fileid,
|
||||
])
|
||||
|
||||
data.extend([
|
||||
""
|
||||
])
|
||||
if namespaces:
|
||||
data.extend([
|
||||
"} // namespace %s" % ns for ns in reversed(namespaces)
|
||||
])
|
||||
else:
|
||||
data.extend([
|
||||
"#if defined(__cplusplus)",
|
||||
"} // extern \"C\"",
|
||||
"#endif // defined(__cplusplus)"
|
||||
])
|
||||
data.extend([
|
||||
"",
|
||||
"#endif // %s" % header_guard,
|
||||
""
|
||||
])
|
||||
return data
|
||||
|
||||
|
||||
def source(namespaces, array_name, array_size_name, fileid, filename,
|
||||
input_bytes):
|
||||
"""Return a C/C++ source file for the given array.
|
||||
|
||||
Args:
|
||||
namespaces: List of namespaces, outer to inner.
|
||||
array_name: Name of the array.
|
||||
array_size_name: Name of the array size constant.
|
||||
fileid: Name of the identifier containing the filename.
|
||||
filename: The original data filename itself.
|
||||
input_bytes: Binary data to put into the array.
|
||||
|
||||
Returns:
|
||||
A string containing the C/C++ source file.
|
||||
"""
|
||||
data = []
|
||||
data.extend([
|
||||
"// Copyright 2016 Google Inc. All Rights Reserved.",
|
||||
"",
|
||||
"#include <stdlib.h>",
|
||||
""
|
||||
])
|
||||
if namespaces:
|
||||
data.extend([
|
||||
"namespace %s {" % ns for ns in namespaces
|
||||
])
|
||||
else:
|
||||
data.extend([
|
||||
"#if defined(__cplusplus)",
|
||||
"extern \"C\" {",
|
||||
"#endif // defined(__cplusplus)"])
|
||||
|
||||
data.extend([
|
||||
"",
|
||||
"extern const size_t %s;" % array_size_name,
|
||||
"extern const char %s[];" % fileid,
|
||||
"extern const unsigned char %s[];" % array_name, "",
|
||||
"const unsigned char %s[] = {" % array_name
|
||||
])
|
||||
length = len(input_bytes)
|
||||
line = ""
|
||||
for idx in range(0, length):
|
||||
if idx % WIDTH == 0:
|
||||
line += " "
|
||||
else:
|
||||
line += " "
|
||||
line += "0x%02x," % input_bytes[idx]
|
||||
if idx % WIDTH == WIDTH - 1:
|
||||
data.append(line)
|
||||
line = ""
|
||||
data.append(line)
|
||||
data.append(" 0x00 // Extra \\0 to make it a C string")
|
||||
|
||||
data.extend([
|
||||
"};",
|
||||
"",
|
||||
"const size_t %s =" % array_size_name,
|
||||
" sizeof(%s) - 1;" % array_name,
|
||||
"",
|
||||
"const char %s[] =" % fileid,
|
||||
" \"%s\";" % filename,
|
||||
"",
|
||||
])
|
||||
|
||||
if namespaces:
|
||||
data.extend([
|
||||
"} // namespace %s" % ns for ns in namespaces
|
||||
][::-1]) # close namespaces in reverse order
|
||||
else:
|
||||
data.extend([
|
||||
"#if defined(__cplusplus)",
|
||||
"} // extern \"C\"",
|
||||
"#endif // defined(__cplusplus)"
|
||||
])
|
||||
data.extend([
|
||||
""
|
||||
])
|
||||
return data
|
||||
|
||||
|
||||
def main():
|
||||
"""Read an binary input file and output to a C/C++ source file as an array.
|
||||
"""
|
||||
|
||||
args = arg_parser.parse_args()
|
||||
|
||||
input_file = args.input
|
||||
input_file_base = os.path.splitext(args.input)[0]
|
||||
|
||||
output_source = args.output_source
|
||||
if not output_source:
|
||||
output_source = input_file_base + ".cc"
|
||||
logging.debug("Using default --output_source='%s'", output_source)
|
||||
|
||||
output_header = args.output_header
|
||||
if not output_header:
|
||||
output_header = input_file_base + ".h"
|
||||
logging.debug("Using default --output_header='%s'", output_header)
|
||||
|
||||
identifier_base = sub("[^0-9a-zA-Z]+", "_", path.basename(input_file_base))
|
||||
array_name = args.array
|
||||
if not array_name:
|
||||
array_name = identifier_base + "_data"
|
||||
logging.debug("Using default --array='%s'", array_name)
|
||||
|
||||
array_size_name = args.array_size
|
||||
if not array_size_name:
|
||||
array_size_name = identifier_base + "_size"
|
||||
logging.debug("Using default --array_size='%s'", array_size_name)
|
||||
|
||||
fileid = args.filename_identifier
|
||||
if not fileid:
|
||||
fileid = identifier_base + "_filename"
|
||||
logging.debug("Using default --filename_identifier='%s'", fileid)
|
||||
|
||||
filename = args.filename
|
||||
if filename is None: # but not if it's the empty string
|
||||
filename = path.basename(input_file)
|
||||
logging.debug("Using default --filename='%s'", filename)
|
||||
|
||||
header_guard = args.header_guard
|
||||
if not header_guard:
|
||||
header_guard = sub("[^0-9a-zA-Z]+", "_", output_header).upper()
|
||||
# Avoid double underscores to stay compliant with the Standard.
|
||||
header_guard = sub("[_]+", "_", header_guard)
|
||||
logging.debug("Using default --header_guard='%s'", header_guard)
|
||||
|
||||
namespace = args.cpp_namespace
|
||||
namespaces = namespace.split("::") if namespace else []
|
||||
|
||||
with open(input_file, "rb") as infile:
|
||||
input_bytes = bytearray(infile.read())
|
||||
logging.debug("Read %d bytes from %s", len(input_bytes), input_file)
|
||||
|
||||
header_text = "\n".join(header(header_guard, namespaces, array_name,
|
||||
array_size_name, fileid))
|
||||
source_text = "\n".join(source(namespaces, array_name, array_size_name,
|
||||
fileid, filename, input_bytes))
|
||||
|
||||
with open(output_header, "w") as hdr:
|
||||
hdr.write(header_text)
|
||||
logging.debug("Wrote header file %s", output_header)
|
||||
|
||||
with open(output_source, "w") as src:
|
||||
src.write(source_text)
|
||||
logging.debug("Wrote source file %s", output_source)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user