aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--BUILD16
-rw-r--r--CMakeLists.txt6
-rw-r--r--Makefile8
-rw-r--r--binding.gyp2
-rw-r--r--build.yaml4
-rw-r--r--config.m42
-rw-r--r--gRPC-Core.podspec6
-rw-r--r--grpc.def9
-rwxr-xr-xgrpc.gemspec4
-rw-r--r--include/grpc/compression.h8
-rw-r--r--include/grpc/grpc.h7
-rw-r--r--include/grpc/impl/codegen/compression_types.h5
-rw-r--r--include/grpc/impl/codegen/grpc_types.h39
-rw-r--r--include/grpc/slice.h9
-rw-r--r--package.xml4
-rw-r--r--src/core/ext/client_channel/client_channel.c24
-rw-r--r--src/core/ext/client_channel/subchannel.c2
-rw-r--r--src/core/ext/client_channel/subchannel.h2
-rw-r--r--src/core/ext/lb_policy/grpclb/grpclb.c2
-rw-r--r--src/core/ext/transport/chttp2/transport/bin_decoder.c10
-rw-r--r--src/core/ext/transport/chttp2/transport/bin_encoder.c3
-rw-r--r--src/core/ext/transport/chttp2/transport/bin_encoder.h3
-rw-r--r--src/core/ext/transport/chttp2/transport/chttp2_plugin.c3
-rw-r--r--src/core/ext/transport/chttp2/transport/chttp2_transport.c14
-rw-r--r--src/core/ext/transport/chttp2/transport/hpack_encoder.c93
-rw-r--r--src/core/ext/transport/chttp2/transport/hpack_encoder.h2
-rw-r--r--src/core/ext/transport/chttp2/transport/hpack_parser.c62
-rw-r--r--src/core/ext/transport/chttp2/transport/hpack_table.c23
-rw-r--r--src/core/ext/transport/chttp2/transport/parsing.c2
-rw-r--r--src/core/lib/channel/channel_stack.c2
-rw-r--r--src/core/lib/channel/channel_stack.h4
-rw-r--r--src/core/lib/channel/compress_filter.c15
-rw-r--r--src/core/lib/channel/http_client_filter.c65
-rw-r--r--src/core/lib/channel/http_server_filter.c56
-rw-r--r--src/core/lib/channel/message_size_filter.c6
-rw-r--r--src/core/lib/compression/algorithm_metadata.h6
-rw-r--r--src/core/lib/compression/compression.c37
-rw-r--r--src/core/lib/iomgr/load_file.c2
-rw-r--r--src/core/lib/security/credentials/google_default/google_default_credentials.c2
-rw-r--r--src/core/lib/security/transport/client_auth_filter.c4
-rw-r--r--src/core/lib/security/transport/security_connector.c2
-rw-r--r--src/core/lib/security/transport/server_auth_filter.c4
-rw-r--r--src/core/lib/security/util/b64.c2
-rw-r--r--src/core/lib/slice/slice.c2
-rw-r--r--src/core/lib/slice/slice_hash_table.c (renamed from src/core/lib/transport/mdstr_hash_table.c)98
-rw-r--r--src/core/lib/slice/slice_hash_table.h (renamed from src/core/lib/transport/mdstr_hash_table.h)52
-rw-r--r--src/core/lib/slice/slice_string_helpers.h3
-rw-r--r--src/core/lib/slice/slice_traits.h44
-rw-r--r--src/core/lib/surface/call.c138
-rw-r--r--src/core/lib/surface/call_details.c6
-rw-r--r--src/core/lib/surface/call_log_batch.c19
-rw-r--r--src/core/lib/surface/channel.c62
-rw-r--r--src/core/lib/surface/channel.h5
-rw-r--r--src/core/lib/surface/lame_client.c9
-rw-r--r--src/core/lib/surface/server.c101
-rw-r--r--src/core/lib/transport/metadata.c427
-rw-r--r--src/core/lib/transport/metadata.h62
-rw-r--r--src/core/lib/transport/method_config.c248
-rw-r--r--src/core/lib/transport/method_config.h74
-rw-r--r--src/core/lib/transport/static_metadata.c509
-rw-r--r--src/core/lib/transport/static_metadata.h204
-rw-r--r--src/core/lib/transport/transport_op_string.c6
-rw-r--r--src/cpp/util/slice_cc.cc2
-rw-r--r--src/python/grpcio/grpc_core_dependencies.py2
-rw-r--r--src/ruby/ext/grpc/rb_grpc_imports.generated.c18
-rw-r--r--src/ruby/ext/grpc/rb_grpc_imports.generated.h31
-rw-r--r--test/core/compression/algorithm_test.c10
-rw-r--r--test/core/end2end/cq_verifier.c21
-rw-r--r--test/core/end2end/cq_verifier.h2
-rw-r--r--test/core/end2end/end2end_test_utils.c22
-rw-r--r--test/core/end2end/end2end_tests.h6
-rw-r--r--test/core/end2end/fixtures/proxy.c10
-rw-r--r--test/core/end2end/fuzzers/hpack.dictionary4
-rw-r--r--test/core/end2end/tests/authority_not_supported.c21
-rw-r--r--test/core/end2end/tests/bad_hostname.c10
-rw-r--r--test/core/end2end/tests/binary_metadata.c77
-rw-r--r--test/core/end2end/tests/call_creds.c29
-rw-r--r--test/core/end2end/tests/cancel_after_accept.c16
-rw-r--r--test/core/end2end/tests/cancel_after_client_done.c11
-rw-r--r--test/core/end2end/tests/cancel_after_invoke.c11
-rw-r--r--test/core/end2end/tests/cancel_before_invoke.c11
-rw-r--r--test/core/end2end/tests/cancel_in_a_vacuum.c5
-rw-r--r--test/core/end2end/tests/cancel_with_status.c13
-rw-r--r--test/core/end2end/tests/compressed_payload.c47
-rw-r--r--test/core/end2end/tests/default_host.c18
-rw-r--r--test/core/end2end/tests/disappearing_server.c18
-rw-r--r--test/core/end2end/tests/empty_batch.c5
-rw-r--r--test/core/end2end/tests/filter_call_init_fails.c13
-rw-r--r--test/core/end2end/tests/filter_causes_close.c14
-rw-r--r--test/core/end2end/tests/filter_latency.c17
-rw-r--r--test/core/end2end/tests/graceful_server_shutdown.c16
-rw-r--r--test/core/end2end/tests/high_initial_seqno.c18
-rw-r--r--test/core/end2end/tests/hpack_size.c36
-rw-r--r--test/core/end2end/tests/idempotent_request.c18
-rw-r--r--test/core/end2end/tests/invoke_large_request.c18
-rw-r--r--test/core/end2end/tests/large_metadata.c32
-rw-r--r--test/core/end2end/tests/load_reporting_hook.c24
-rw-r--r--test/core/end2end/tests/max_concurrent_streams.c45
-rw-r--r--test/core/end2end/tests/max_message_length.c62
-rw-r--r--test/core/end2end/tests/negative_deadline.c11
-rw-r--r--test/core/end2end/tests/network_status_change.c16
-rw-r--r--test/core/end2end/tests/no_logging.c18
-rw-r--r--test/core/end2end/tests/payload.c18
-rw-r--r--test/core/end2end/tests/ping_pong_streaming.c14
-rw-r--r--test/core/end2end/tests/registered_call.c13
-rw-r--r--test/core/end2end/tests/request_with_flags.c11
-rw-r--r--test/core/end2end/tests/request_with_payload.c18
-rw-r--r--test/core/end2end/tests/resource_quota_server.c19
-rw-r--r--test/core/end2end/tests/server_finishes_request.c18
-rw-r--r--test/core/end2end/tests/shutdown_finishes_calls.c13
-rw-r--r--test/core/end2end/tests/simple_cacheable_request.c40
-rw-r--r--test/core/end2end/tests/simple_delayed_request.c18
-rw-r--r--test/core/end2end/tests/simple_metadata.c40
-rw-r--r--test/core/end2end/tests/simple_request.c18
-rw-r--r--test/core/end2end/tests/streaming_error_response.c19
-rw-r--r--test/core/end2end/tests/trailing_metadata.c51
-rwxr-xr-xtools/codegen/core/gen_static_metadata.py113
-rw-r--r--tools/codegen/core/perfect/.gitignore7
-rw-r--r--tools/codegen/core/perfect/lookupa.c240
-rw-r--r--tools/codegen/core/perfect/lookupa.h24
-rw-r--r--tools/codegen/core/perfect/perfect.c1367
-rw-r--r--tools/codegen/core/perfect/perfect.h132
-rw-r--r--tools/codegen/core/perfect/perfhex.c1308
-rw-r--r--tools/codegen/core/perfect/recycle.c87
-rw-r--r--tools/codegen/core/perfect/recycle.h65
-rwxr-xr-xtools/codegen/core/perfect/run.sh7
-rw-r--r--tools/codegen/core/perfect/standard.h57
-rw-r--r--tools/doxygen/Doxyfile.core.internal4
-rw-r--r--tools/run_tests/sources_and_headers.json6
-rw-r--r--vsprojects/vcxproj/grpc/grpc.vcxproj6
-rw-r--r--vsprojects/vcxproj/grpc/grpc.vcxproj.filters12
-rw-r--r--vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj6
-rw-r--r--vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters12
-rw-r--r--vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj6
-rw-r--r--vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters12
135 files changed, 5341 insertions, 1868 deletions
diff --git a/BUILD b/BUILD
index a72859ba97..d300cc632e 100644
--- a/BUILD
+++ b/BUILD
@@ -231,6 +231,7 @@ cc_library(
"src/core/lib/json/json_reader.h",
"src/core/lib/json/json_writer.h",
"src/core/lib/slice/percent_encoding.h",
+ "src/core/lib/slice/slice_hash_table.h",
"src/core/lib/slice/slice_string_helpers.h",
"src/core/lib/surface/api_trace.h",
"src/core/lib/surface/call.h",
@@ -245,7 +246,6 @@ cc_library(
"src/core/lib/surface/server.h",
"src/core/lib/transport/byte_stream.h",
"src/core/lib/transport/connectivity_state.h",
- "src/core/lib/transport/mdstr_hash_table.h",
"src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/method_config.h",
@@ -413,6 +413,7 @@ cc_library(
"src/core/lib/slice/percent_encoding.c",
"src/core/lib/slice/slice.c",
"src/core/lib/slice/slice_buffer.c",
+ "src/core/lib/slice/slice_hash_table.c",
"src/core/lib/slice/slice_intern.c",
"src/core/lib/slice/slice_string_helpers.c",
"src/core/lib/surface/alarm.c",
@@ -435,7 +436,6 @@ cc_library(
"src/core/lib/surface/version.c",
"src/core/lib/transport/byte_stream.c",
"src/core/lib/transport/connectivity_state.c",
- "src/core/lib/transport/mdstr_hash_table.c",
"src/core/lib/transport/metadata.c",
"src/core/lib/transport/metadata_batch.c",
"src/core/lib/transport/method_config.c",
@@ -667,6 +667,7 @@ cc_library(
"src/core/lib/json/json_reader.h",
"src/core/lib/json/json_writer.h",
"src/core/lib/slice/percent_encoding.h",
+ "src/core/lib/slice/slice_hash_table.h",
"src/core/lib/slice/slice_string_helpers.h",
"src/core/lib/surface/api_trace.h",
"src/core/lib/surface/call.h",
@@ -681,7 +682,6 @@ cc_library(
"src/core/lib/surface/server.h",
"src/core/lib/transport/byte_stream.h",
"src/core/lib/transport/connectivity_state.h",
- "src/core/lib/transport/mdstr_hash_table.h",
"src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/method_config.h",
@@ -834,6 +834,7 @@ cc_library(
"src/core/lib/slice/percent_encoding.c",
"src/core/lib/slice/slice.c",
"src/core/lib/slice/slice_buffer.c",
+ "src/core/lib/slice/slice_hash_table.c",
"src/core/lib/slice/slice_intern.c",
"src/core/lib/slice/slice_string_helpers.c",
"src/core/lib/surface/alarm.c",
@@ -856,7 +857,6 @@ cc_library(
"src/core/lib/surface/version.c",
"src/core/lib/transport/byte_stream.c",
"src/core/lib/transport/connectivity_state.c",
- "src/core/lib/transport/mdstr_hash_table.c",
"src/core/lib/transport/metadata.c",
"src/core/lib/transport/metadata_batch.c",
"src/core/lib/transport/method_config.c",
@@ -1058,6 +1058,7 @@ cc_library(
"src/core/lib/json/json_reader.h",
"src/core/lib/json/json_writer.h",
"src/core/lib/slice/percent_encoding.h",
+ "src/core/lib/slice/slice_hash_table.h",
"src/core/lib/slice/slice_string_helpers.h",
"src/core/lib/surface/api_trace.h",
"src/core/lib/surface/call.h",
@@ -1072,7 +1073,6 @@ cc_library(
"src/core/lib/surface/server.h",
"src/core/lib/transport/byte_stream.h",
"src/core/lib/transport/connectivity_state.h",
- "src/core/lib/transport/mdstr_hash_table.h",
"src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/method_config.h",
@@ -1217,6 +1217,7 @@ cc_library(
"src/core/lib/slice/percent_encoding.c",
"src/core/lib/slice/slice.c",
"src/core/lib/slice/slice_buffer.c",
+ "src/core/lib/slice/slice_hash_table.c",
"src/core/lib/slice/slice_intern.c",
"src/core/lib/slice/slice_string_helpers.c",
"src/core/lib/surface/alarm.c",
@@ -1239,7 +1240,6 @@ cc_library(
"src/core/lib/surface/version.c",
"src/core/lib/transport/byte_stream.c",
"src/core/lib/transport/connectivity_state.c",
- "src/core/lib/transport/mdstr_hash_table.c",
"src/core/lib/transport/metadata.c",
"src/core/lib/transport/metadata_batch.c",
"src/core/lib/transport/method_config.c",
@@ -2084,6 +2084,7 @@ objc_library(
"src/core/lib/slice/percent_encoding.c",
"src/core/lib/slice/slice.c",
"src/core/lib/slice/slice_buffer.c",
+ "src/core/lib/slice/slice_hash_table.c",
"src/core/lib/slice/slice_intern.c",
"src/core/lib/slice/slice_string_helpers.c",
"src/core/lib/surface/alarm.c",
@@ -2106,7 +2107,6 @@ objc_library(
"src/core/lib/surface/version.c",
"src/core/lib/transport/byte_stream.c",
"src/core/lib/transport/connectivity_state.c",
- "src/core/lib/transport/mdstr_hash_table.c",
"src/core/lib/transport/metadata.c",
"src/core/lib/transport/metadata_batch.c",
"src/core/lib/transport/method_config.c",
@@ -2317,6 +2317,7 @@ objc_library(
"src/core/lib/json/json_reader.h",
"src/core/lib/json/json_writer.h",
"src/core/lib/slice/percent_encoding.h",
+ "src/core/lib/slice/slice_hash_table.h",
"src/core/lib/slice/slice_string_helpers.h",
"src/core/lib/surface/api_trace.h",
"src/core/lib/surface/call.h",
@@ -2331,7 +2332,6 @@ objc_library(
"src/core/lib/surface/server.h",
"src/core/lib/transport/byte_stream.h",
"src/core/lib/transport/connectivity_state.h",
- "src/core/lib/transport/mdstr_hash_table.h",
"src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/method_config.h",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3b627ecf2d..98bcf22978 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -368,6 +368,7 @@ add_library(grpc
src/core/lib/slice/percent_encoding.c
src/core/lib/slice/slice.c
src/core/lib/slice/slice_buffer.c
+ src/core/lib/slice/slice_hash_table.c
src/core/lib/slice/slice_intern.c
src/core/lib/slice/slice_string_helpers.c
src/core/lib/surface/alarm.c
@@ -390,7 +391,6 @@ add_library(grpc
src/core/lib/surface/version.c
src/core/lib/transport/byte_stream.c
src/core/lib/transport/connectivity_state.c
- src/core/lib/transport/mdstr_hash_table.c
src/core/lib/transport/metadata.c
src/core/lib/transport/metadata_batch.c
src/core/lib/transport/method_config.c
@@ -649,6 +649,7 @@ add_library(grpc_cronet
src/core/lib/slice/percent_encoding.c
src/core/lib/slice/slice.c
src/core/lib/slice/slice_buffer.c
+ src/core/lib/slice/slice_hash_table.c
src/core/lib/slice/slice_intern.c
src/core/lib/slice/slice_string_helpers.c
src/core/lib/surface/alarm.c
@@ -671,7 +672,6 @@ add_library(grpc_cronet
src/core/lib/surface/version.c
src/core/lib/transport/byte_stream.c
src/core/lib/transport/connectivity_state.c
- src/core/lib/transport/mdstr_hash_table.c
src/core/lib/transport/metadata.c
src/core/lib/transport/metadata_batch.c
src/core/lib/transport/method_config.c
@@ -902,6 +902,7 @@ add_library(grpc_unsecure
src/core/lib/slice/percent_encoding.c
src/core/lib/slice/slice.c
src/core/lib/slice/slice_buffer.c
+ src/core/lib/slice/slice_hash_table.c
src/core/lib/slice/slice_intern.c
src/core/lib/slice/slice_string_helpers.c
src/core/lib/surface/alarm.c
@@ -924,7 +925,6 @@ add_library(grpc_unsecure
src/core/lib/surface/version.c
src/core/lib/transport/byte_stream.c
src/core/lib/transport/connectivity_state.c
- src/core/lib/transport/mdstr_hash_table.c
src/core/lib/transport/metadata.c
src/core/lib/transport/metadata_batch.c
src/core/lib/transport/method_config.c
diff --git a/Makefile b/Makefile
index b2328aac28..72021517d9 100644
--- a/Makefile
+++ b/Makefile
@@ -2707,6 +2707,7 @@ LIBGRPC_SRC = \
src/core/lib/slice/percent_encoding.c \
src/core/lib/slice/slice.c \
src/core/lib/slice/slice_buffer.c \
+ src/core/lib/slice/slice_hash_table.c \
src/core/lib/slice/slice_intern.c \
src/core/lib/slice/slice_string_helpers.c \
src/core/lib/surface/alarm.c \
@@ -2729,7 +2730,6 @@ LIBGRPC_SRC = \
src/core/lib/surface/version.c \
src/core/lib/transport/byte_stream.c \
src/core/lib/transport/connectivity_state.c \
- src/core/lib/transport/mdstr_hash_table.c \
src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/method_config.c \
@@ -3006,6 +3006,7 @@ LIBGRPC_CRONET_SRC = \
src/core/lib/slice/percent_encoding.c \
src/core/lib/slice/slice.c \
src/core/lib/slice/slice_buffer.c \
+ src/core/lib/slice/slice_hash_table.c \
src/core/lib/slice/slice_intern.c \
src/core/lib/slice/slice_string_helpers.c \
src/core/lib/surface/alarm.c \
@@ -3028,7 +3029,6 @@ LIBGRPC_CRONET_SRC = \
src/core/lib/surface/version.c \
src/core/lib/transport/byte_stream.c \
src/core/lib/transport/connectivity_state.c \
- src/core/lib/transport/mdstr_hash_table.c \
src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/method_config.c \
@@ -3296,6 +3296,7 @@ LIBGRPC_TEST_UTIL_SRC = \
src/core/lib/slice/percent_encoding.c \
src/core/lib/slice/slice.c \
src/core/lib/slice/slice_buffer.c \
+ src/core/lib/slice/slice_hash_table.c \
src/core/lib/slice/slice_intern.c \
src/core/lib/slice/slice_string_helpers.c \
src/core/lib/surface/alarm.c \
@@ -3318,7 +3319,6 @@ LIBGRPC_TEST_UTIL_SRC = \
src/core/lib/surface/version.c \
src/core/lib/transport/byte_stream.c \
src/core/lib/transport/connectivity_state.c \
- src/core/lib/transport/mdstr_hash_table.c \
src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/method_config.c \
@@ -3515,6 +3515,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/slice/percent_encoding.c \
src/core/lib/slice/slice.c \
src/core/lib/slice/slice_buffer.c \
+ src/core/lib/slice/slice_hash_table.c \
src/core/lib/slice/slice_intern.c \
src/core/lib/slice/slice_string_helpers.c \
src/core/lib/surface/alarm.c \
@@ -3537,7 +3538,6 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/surface/version.c \
src/core/lib/transport/byte_stream.c \
src/core/lib/transport/connectivity_state.c \
- src/core/lib/transport/mdstr_hash_table.c \
src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/method_config.c \
diff --git a/binding.gyp b/binding.gyp
index f6ac14f265..40ed7cc9e6 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -647,6 +647,7 @@
'src/core/lib/slice/percent_encoding.c',
'src/core/lib/slice/slice.c',
'src/core/lib/slice/slice_buffer.c',
+ 'src/core/lib/slice/slice_hash_table.c',
'src/core/lib/slice/slice_intern.c',
'src/core/lib/slice/slice_string_helpers.c',
'src/core/lib/surface/alarm.c',
@@ -669,7 +670,6 @@
'src/core/lib/surface/version.c',
'src/core/lib/transport/byte_stream.c',
'src/core/lib/transport/connectivity_state.c',
- 'src/core/lib/transport/mdstr_hash_table.c',
'src/core/lib/transport/metadata.c',
'src/core/lib/transport/metadata_batch.c',
'src/core/lib/transport/method_config.c',
diff --git a/build.yaml b/build.yaml
index b885028261..6f10509613 100644
--- a/build.yaml
+++ b/build.yaml
@@ -238,6 +238,7 @@ filegroups:
- src/core/lib/json/json_reader.h
- src/core/lib/json/json_writer.h
- src/core/lib/slice/percent_encoding.h
+ - src/core/lib/slice/slice_hash_table.h
- src/core/lib/slice/slice_string_helpers.h
- src/core/lib/surface/api_trace.h
- src/core/lib/surface/call.h
@@ -252,7 +253,6 @@ filegroups:
- src/core/lib/surface/server.h
- src/core/lib/transport/byte_stream.h
- src/core/lib/transport/connectivity_state.h
- - src/core/lib/transport/mdstr_hash_table.h
- src/core/lib/transport/metadata.h
- src/core/lib/transport/metadata_batch.h
- src/core/lib/transport/method_config.h
@@ -344,6 +344,7 @@ filegroups:
- src/core/lib/slice/percent_encoding.c
- src/core/lib/slice/slice.c
- src/core/lib/slice/slice_buffer.c
+ - src/core/lib/slice/slice_hash_table.c
- src/core/lib/slice/slice_intern.c
- src/core/lib/slice/slice_string_helpers.c
- src/core/lib/surface/alarm.c
@@ -366,7 +367,6 @@ filegroups:
- src/core/lib/surface/version.c
- src/core/lib/transport/byte_stream.c
- src/core/lib/transport/connectivity_state.c
- - src/core/lib/transport/mdstr_hash_table.c
- src/core/lib/transport/metadata.c
- src/core/lib/transport/metadata_batch.c
- src/core/lib/transport/method_config.c
diff --git a/config.m4 b/config.m4
index a36601e599..544c6f17f1 100644
--- a/config.m4
+++ b/config.m4
@@ -163,6 +163,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/slice/percent_encoding.c \
src/core/lib/slice/slice.c \
src/core/lib/slice/slice_buffer.c \
+ src/core/lib/slice/slice_hash_table.c \
src/core/lib/slice/slice_intern.c \
src/core/lib/slice/slice_string_helpers.c \
src/core/lib/surface/alarm.c \
@@ -185,7 +186,6 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/surface/version.c \
src/core/lib/transport/byte_stream.c \
src/core/lib/transport/connectivity_state.c \
- src/core/lib/transport/mdstr_hash_table.c \
src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/method_config.c \
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index 5a62ff2a86..0ced98e64f 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -321,6 +321,7 @@ Pod::Spec.new do |s|
'src/core/lib/json/json_reader.h',
'src/core/lib/json/json_writer.h',
'src/core/lib/slice/percent_encoding.h',
+ 'src/core/lib/slice/slice_hash_table.h',
'src/core/lib/slice/slice_string_helpers.h',
'src/core/lib/surface/api_trace.h',
'src/core/lib/surface/call.h',
@@ -335,7 +336,6 @@ Pod::Spec.new do |s|
'src/core/lib/surface/server.h',
'src/core/lib/transport/byte_stream.h',
'src/core/lib/transport/connectivity_state.h',
- 'src/core/lib/transport/mdstr_hash_table.h',
'src/core/lib/transport/metadata.h',
'src/core/lib/transport/metadata_batch.h',
'src/core/lib/transport/method_config.h',
@@ -507,6 +507,7 @@ Pod::Spec.new do |s|
'src/core/lib/slice/percent_encoding.c',
'src/core/lib/slice/slice.c',
'src/core/lib/slice/slice_buffer.c',
+ 'src/core/lib/slice/slice_hash_table.c',
'src/core/lib/slice/slice_intern.c',
'src/core/lib/slice/slice_string_helpers.c',
'src/core/lib/surface/alarm.c',
@@ -529,7 +530,6 @@ Pod::Spec.new do |s|
'src/core/lib/surface/version.c',
'src/core/lib/transport/byte_stream.c',
'src/core/lib/transport/connectivity_state.c',
- 'src/core/lib/transport/mdstr_hash_table.c',
'src/core/lib/transport/metadata.c',
'src/core/lib/transport/metadata_batch.c',
'src/core/lib/transport/method_config.c',
@@ -725,6 +725,7 @@ Pod::Spec.new do |s|
'src/core/lib/json/json_reader.h',
'src/core/lib/json/json_writer.h',
'src/core/lib/slice/percent_encoding.h',
+ 'src/core/lib/slice/slice_hash_table.h',
'src/core/lib/slice/slice_string_helpers.h',
'src/core/lib/surface/api_trace.h',
'src/core/lib/surface/call.h',
@@ -739,7 +740,6 @@ Pod::Spec.new do |s|
'src/core/lib/surface/server.h',
'src/core/lib/transport/byte_stream.h',
'src/core/lib/transport/connectivity_state.h',
- 'src/core/lib/transport/mdstr_hash_table.h',
'src/core/lib/transport/metadata.h',
'src/core/lib/transport/metadata_batch.h',
'src/core/lib/transport/method_config.h',
diff --git a/grpc.def b/grpc.def
index 1028f9ff9e..a4989ada58 100644
--- a/grpc.def
+++ b/grpc.def
@@ -92,8 +92,11 @@ EXPORTS
grpc_server_destroy
grpc_tracer_set_enabled
grpc_header_key_is_legal
+ grpc_header_key_slice_is_legal
grpc_header_nonbin_value_is_legal
+ grpc_header_nonbin_value_slice_is_legal
grpc_is_binary_header
+ grpc_slice_is_binary_header
grpc_call_error_to_string
grpc_resource_quota_create
grpc_resource_quota_ref
@@ -149,9 +152,13 @@ EXPORTS
grpc_slice_sub_no_ref
grpc_slice_split_tail
grpc_slice_split_head
- gpr_empty_slice
+ grpc_empty_slice
grpc_slice_cmp
grpc_slice_str_cmp
+ grpc_slice_buf_cmp
+ grpc_slice_buf_start_eq
+ grpc_slice_rchr
+ grpc_slice_hash
grpc_slice_is_equivalent
grpc_slice_buffer_init
grpc_slice_buffer_destroy
diff --git a/grpc.gemspec b/grpc.gemspec
index cb3e644be3..42196e8d24 100755
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -241,6 +241,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/json/json_reader.h )
s.files += %w( src/core/lib/json/json_writer.h )
s.files += %w( src/core/lib/slice/percent_encoding.h )
+ s.files += %w( src/core/lib/slice/slice_hash_table.h )
s.files += %w( src/core/lib/slice/slice_string_helpers.h )
s.files += %w( src/core/lib/surface/api_trace.h )
s.files += %w( src/core/lib/surface/call.h )
@@ -255,7 +256,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/surface/server.h )
s.files += %w( src/core/lib/transport/byte_stream.h )
s.files += %w( src/core/lib/transport/connectivity_state.h )
- s.files += %w( src/core/lib/transport/mdstr_hash_table.h )
s.files += %w( src/core/lib/transport/metadata.h )
s.files += %w( src/core/lib/transport/metadata_batch.h )
s.files += %w( src/core/lib/transport/method_config.h )
@@ -427,6 +427,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/slice/percent_encoding.c )
s.files += %w( src/core/lib/slice/slice.c )
s.files += %w( src/core/lib/slice/slice_buffer.c )
+ s.files += %w( src/core/lib/slice/slice_hash_table.c )
s.files += %w( src/core/lib/slice/slice_intern.c )
s.files += %w( src/core/lib/slice/slice_string_helpers.c )
s.files += %w( src/core/lib/surface/alarm.c )
@@ -449,7 +450,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/surface/version.c )
s.files += %w( src/core/lib/transport/byte_stream.c )
s.files += %w( src/core/lib/transport/connectivity_state.c )
- s.files += %w( src/core/lib/transport/mdstr_hash_table.c )
s.files += %w( src/core/lib/transport/metadata.c )
s.files += %w( src/core/lib/transport/metadata_batch.c )
s.files += %w( src/core/lib/transport/method_config.c )
diff --git a/include/grpc/compression.h b/include/grpc/compression.h
index 5f285cdcdf..659d6fe758 100644
--- a/include/grpc/compression.h
+++ b/include/grpc/compression.h
@@ -34,11 +34,12 @@
#ifndef GRPC_COMPRESSION_H
#define GRPC_COMPRESSION_H
-#include <stdlib.h>
-
#include <grpc/impl/codegen/port_platform.h>
+#include <stdlib.h>
+
#include <grpc/impl/codegen/compression_types.h>
+#include <grpc/slice.h>
#ifdef __cplusplus
extern "C" {
@@ -48,8 +49,7 @@ extern "C" {
* grpc_compression_algorithm instance, updating \a algorithm. Returns 1 upon
* success, 0 otherwise. */
GRPCAPI int grpc_compression_algorithm_parse(
- const char *name, size_t name_length,
- grpc_compression_algorithm *algorithm);
+ grpc_slice value, grpc_compression_algorithm *algorithm);
/** Updates \a name with the encoding name corresponding to a valid \a
* algorithm. Note that \a name is statically allocated and must *not* be freed.
diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h
index 5e486215e0..a3015340ee 100644
--- a/include/grpc/grpc.h
+++ b/include/grpc/grpc.h
@@ -178,8 +178,8 @@ GRPCAPI void grpc_channel_watch_connectivity_state(
possible values). */
GRPCAPI grpc_call *grpc_channel_create_call(
grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask,
- grpc_completion_queue *completion_queue, const char *method,
- const char *host, gpr_timespec deadline, void *reserved);
+ grpc_completion_queue *completion_queue, grpc_slice method,
+ const grpc_slice *host, gpr_timespec deadline, void *reserved);
/** Ping the channels peer (load balanced channels will select one sub-channel
to ping); if the channel is not connected, posts a failed. */
@@ -397,13 +397,16 @@ GRPCAPI int grpc_tracer_set_enabled(const char *name, int enabled);
/** Check whether a metadata key is legal (will be accepted by core) */
GRPCAPI int grpc_header_key_is_legal(const char *key, size_t length);
+GRPCAPI int grpc_header_key_slice_is_legal(grpc_slice slice);
/** Check whether a non-binary metadata value is legal (will be accepted by
core) */
GRPCAPI int grpc_header_nonbin_value_is_legal(const char *value, size_t length);
+GRPCAPI int grpc_header_nonbin_value_slice_is_legal(grpc_slice slice);
/** Check whether a metadata key corresponds to a binary value */
GRPCAPI int grpc_is_binary_header(const char *key, size_t length);
+GRPCAPI int grpc_slice_is_binary_header(grpc_slice slice);
/** Convert grpc_call_error values to a string */
GRPCAPI const char *grpc_call_error_to_string(grpc_call_error error);
diff --git a/include/grpc/impl/codegen/compression_types.h b/include/grpc/impl/codegen/compression_types.h
index 170d99f431..8810943137 100644
--- a/include/grpc/impl/codegen/compression_types.h
+++ b/include/grpc/impl/codegen/compression_types.h
@@ -41,11 +41,6 @@
extern "C" {
#endif
-/** To be used as initial metadata key for the request of a concrete compression
- * algorithm */
-#define GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY \
- "grpc-internal-encoding-request"
-
/** To be used in channel arguments.
*
* \addtogroup grpc_arg_keys
diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h
index ed5048f32f..1d9402cf33 100644
--- a/include/grpc/impl/codegen/grpc_types.h
+++ b/include/grpc/impl/codegen/grpc_types.h
@@ -292,9 +292,8 @@ typedef enum grpc_call_error {
/** A single metadata element */
typedef struct grpc_metadata {
- const char *key;
- const char *value;
- size_t value_length;
+ grpc_slice key;
+ grpc_slice value;
uint32_t flags;
/** The following fields are reserved for grpc internal use.
@@ -336,10 +335,8 @@ typedef struct {
} grpc_metadata_array;
typedef struct {
- char *method;
- size_t method_capacity;
- char *host;
- size_t host_capacity;
+ grpc_slice method;
+ grpc_slice host;
gpr_timespec deadline;
uint32_t flags;
void *reserved;
@@ -421,7 +418,10 @@ typedef struct grpc_op {
size_t trailing_metadata_count;
grpc_metadata *trailing_metadata;
grpc_status_code status;
- const char *status_details;
+ /* optional: set to NULL if no details need sending, non-NULL if they do
+ * pointer will not be retained past the start_batch call
+ */
+ grpc_slice *status_details;
} send_status_from_server;
/** ownership of the array is with the caller, but ownership of the elements
stays with the call object (ie key, value members are owned by the call
@@ -442,28 +442,7 @@ typedef struct grpc_op {
value, or reuse it in a future op. */
grpc_metadata_array *trailing_metadata;
grpc_status_code *status;
- /** status_details is a buffer owned by the application before the op
- completes and after the op has completed. During the operation
- status_details may be reallocated to a size larger than
- *status_details_capacity, in which case *status_details_capacity will
- be updated with the new array capacity.
-
- Pre-allocating space:
- size_t my_capacity = 8;
- char *my_details = gpr_malloc(my_capacity);
- x.status_details = &my_details;
- x.status_details_capacity = &my_capacity;
-
- Not pre-allocating space:
- size_t my_capacity = 0;
- char *my_details = NULL;
- x.status_details = &my_details;
- x.status_details_capacity = &my_capacity;
-
- After the call:
- gpr_free(my_details); */
- char **status_details;
- size_t *status_details_capacity;
+ grpc_slice *status_details;
} recv_status_on_client;
struct {
/** out argument, set to 1 if the call failed in any way (seen as a
diff --git a/include/grpc/slice.h b/include/grpc/slice.h
index 34632a371a..34c1ee93d6 100644
--- a/include/grpc/slice.h
+++ b/include/grpc/slice.h
@@ -119,13 +119,20 @@ GPRAPI grpc_slice grpc_slice_split_tail(grpc_slice *s, size_t split);
Requires s intialized, split <= s.length */
GPRAPI grpc_slice grpc_slice_split_head(grpc_slice *s, size_t split);
-GPRAPI grpc_slice gpr_empty_slice(void);
+GPRAPI grpc_slice grpc_empty_slice(void);
/* Returns <0 if a < b, ==0 if a == b, >0 if a > b
The order is arbitrary, and is not guaranteed to be stable across different
versions of the API. */
GPRAPI int grpc_slice_cmp(grpc_slice a, grpc_slice b);
GPRAPI int grpc_slice_str_cmp(grpc_slice a, const char *b);
+GPRAPI int grpc_slice_buf_cmp(grpc_slice a, const void *b, size_t blen);
+
+GPRAPI int grpc_slice_buf_start_eq(grpc_slice a, const void *b, size_t blen);
+
+GPRAPI int grpc_slice_rchr(grpc_slice s, char c);
+
+GPRAPI uint32_t grpc_slice_hash(grpc_slice s);
/* Do two slices point at the same memory, with the same length
If a or b is inlined, actually compares data */
diff --git a/package.xml b/package.xml
index 1ecc6832ac..e4397eddea 100644
--- a/package.xml
+++ b/package.xml
@@ -248,6 +248,7 @@
<file baseinstalldir="/" name="src/core/lib/json/json_reader.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/json/json_writer.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/slice/percent_encoding.h" role="src" />
+ <file baseinstalldir="/" name="src/core/lib/slice/slice_hash_table.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/slice/slice_string_helpers.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/api_trace.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/call.h" role="src" />
@@ -262,7 +263,6 @@
<file baseinstalldir="/" name="src/core/lib/surface/server.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/byte_stream.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/connectivity_state.h" role="src" />
- <file baseinstalldir="/" name="src/core/lib/transport/mdstr_hash_table.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/metadata.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/metadata_batch.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/method_config.h" role="src" />
@@ -434,6 +434,7 @@
<file baseinstalldir="/" name="src/core/lib/slice/percent_encoding.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/slice/slice.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/slice/slice_buffer.c" role="src" />
+ <file baseinstalldir="/" name="src/core/lib/slice/slice_hash_table.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/slice/slice_intern.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/slice/slice_string_helpers.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/alarm.c" role="src" />
@@ -456,7 +457,6 @@
<file baseinstalldir="/" name="src/core/lib/surface/version.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/byte_stream.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/connectivity_state.c" role="src" />
- <file baseinstalldir="/" name="src/core/lib/transport/mdstr_hash_table.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/metadata.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/metadata_batch.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/method_config.c" role="src" />
diff --git a/src/core/ext/client_channel/client_channel.c b/src/core/ext/client_channel/client_channel.c
index 8f0c856afe..011a8411aa 100644
--- a/src/core/ext/client_channel/client_channel.c
+++ b/src/core/ext/client_channel/client_channel.c
@@ -96,7 +96,7 @@ static void method_parameters_del(grpc_exec_ctx *exec_ctx, void *p) {
gpr_free(p);
}
-static const grpc_mdstr_hash_table_vtable method_parameters_vtable = {
+static const grpc_slice_hash_table_vtable method_parameters_vtable = {
method_parameters_del, method_parameters_copy, method_parameters_cmp};
static void *method_config_convert_value(
@@ -131,7 +131,7 @@ typedef struct client_channel_channel_data {
char *lb_policy_name;
grpc_lb_policy *lb_policy;
/** maps method names to method_parameters structs */
- grpc_mdstr_hash_table *method_params_table;
+ grpc_slice_hash_table *method_params_table;
/** incoming resolver result - set by resolver.next() */
grpc_channel_args *resolver_result;
/** a list of closures that are all waiting for config to come in */
@@ -232,7 +232,7 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
char *lb_policy_name = NULL;
grpc_lb_policy *lb_policy = NULL;
grpc_lb_policy *old_lb_policy;
- grpc_mdstr_hash_table *method_params_table = NULL;
+ grpc_slice_hash_table *method_params_table = NULL;
grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
bool exit_idle = false;
grpc_error *state_error = GRPC_ERROR_CREATE("No load balancing policy");
@@ -316,7 +316,7 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
old_lb_policy = chand->lb_policy;
chand->lb_policy = lb_policy;
if (chand->method_params_table != NULL) {
- grpc_mdstr_hash_table_unref(exec_ctx, chand->method_params_table);
+ grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
}
chand->method_params_table = method_params_table;
if (lb_policy != NULL) {
@@ -494,7 +494,7 @@ static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
}
gpr_free(chand->lb_policy_name);
if (chand->method_params_table != NULL) {
- grpc_mdstr_hash_table_unref(exec_ctx, chand->method_params_table);
+ grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
}
grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
grpc_pollset_set_destroy(chand->interested_parties);
@@ -529,7 +529,7 @@ typedef struct client_channel_call_data {
// to avoid this without breaking the grpc_deadline_state abstraction.
grpc_deadline_state deadline_state;
- grpc_mdstr *path; // Request path.
+ grpc_slice path; // Request path.
gpr_timespec call_start_time;
gpr_timespec deadline;
wait_for_ready_value wait_for_ready_from_service_config;
@@ -926,10 +926,10 @@ static void read_service_config(grpc_exec_ctx *exec_ctx, void *arg,
if (error == GRPC_ERROR_NONE) {
// Get the method config table from channel data.
gpr_mu_lock(&chand->mu);
- grpc_mdstr_hash_table *method_params_table = NULL;
+ grpc_slice_hash_table *method_params_table = NULL;
if (chand->method_params_table != NULL) {
method_params_table =
- grpc_mdstr_hash_table_ref(chand->method_params_table);
+ grpc_slice_hash_table_ref(chand->method_params_table);
}
gpr_mu_unlock(&chand->mu);
// If the method config table was present, use it.
@@ -958,7 +958,7 @@ static void read_service_config(grpc_exec_ctx *exec_ctx, void *arg,
gpr_mu_unlock(&calld->mu);
}
}
- grpc_mdstr_hash_table_unref(exec_ctx, method_params_table);
+ grpc_slice_hash_table_unref(exec_ctx, method_params_table);
}
}
GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "read_service_config");
@@ -996,8 +996,8 @@ static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
if (chand->lb_policy != NULL) {
// We already have a resolver result, so check for service config.
if (chand->method_params_table != NULL) {
- grpc_mdstr_hash_table *method_params_table =
- grpc_mdstr_hash_table_ref(chand->method_params_table);
+ grpc_slice_hash_table *method_params_table =
+ grpc_slice_hash_table_ref(chand->method_params_table);
gpr_mu_unlock(&chand->mu);
method_parameters *method_params = grpc_method_config_table_get(
exec_ctx, method_params_table, args->path);
@@ -1013,7 +1013,7 @@ static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
method_params->wait_for_ready;
}
}
- grpc_mdstr_hash_table_unref(exec_ctx, method_params_table);
+ grpc_slice_hash_table_unref(exec_ctx, method_params_table);
} else {
gpr_mu_unlock(&chand->mu);
}
diff --git a/src/core/ext/client_channel/subchannel.c b/src/core/ext/client_channel/subchannel.c
index 6ba6254785..063b79cece 100644
--- a/src/core/ext/client_channel/subchannel.c
+++ b/src/core/ext/client_channel/subchannel.c
@@ -703,7 +703,7 @@ grpc_connected_subchannel *grpc_subchannel_get_connected_subchannel(
grpc_error *grpc_connected_subchannel_create_call(
grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con,
- grpc_polling_entity *pollent, grpc_mdstr *path, gpr_timespec start_time,
+ grpc_polling_entity *pollent, grpc_slice path, gpr_timespec start_time,
gpr_timespec deadline, grpc_subchannel_call **call) {
grpc_channel_stack *chanstk = CHANNEL_STACK_FROM_CONNECTION(con);
*call = gpr_malloc(sizeof(grpc_subchannel_call) + chanstk->call_stack_size);
diff --git a/src/core/ext/client_channel/subchannel.h b/src/core/ext/client_channel/subchannel.h
index 10bae620df..e7a5bb4bbd 100644
--- a/src/core/ext/client_channel/subchannel.h
+++ b/src/core/ext/client_channel/subchannel.h
@@ -111,7 +111,7 @@ void grpc_subchannel_call_unref(grpc_exec_ctx *exec_ctx,
/** construct a subchannel call */
grpc_error *grpc_connected_subchannel_create_call(
grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *connected_subchannel,
- grpc_polling_entity *pollent, grpc_mdstr *path, gpr_timespec start_time,
+ grpc_polling_entity *pollent, grpc_slice path, gpr_timespec start_time,
gpr_timespec deadline, grpc_subchannel_call **subchannel_call);
/** process a transport level op */
diff --git a/src/core/ext/lb_policy/grpclb/grpclb.c b/src/core/ext/lb_policy/grpclb/grpclb.c
index 4bca8def39..3e5c039fdd 100644
--- a/src/core/ext/lb_policy/grpclb/grpclb.c
+++ b/src/core/ext/lb_policy/grpclb/grpclb.c
@@ -447,7 +447,7 @@ static grpc_lb_addresses *process_serverlist(
GPR_ARRAY_SIZE(server->load_balance_token);
const size_t lb_token_length =
strnlen(server->load_balance_token, lb_token_max_length);
- grpc_mdstr *lb_token_mdstr = grpc_mdstr_from_buffer(
+ grpc_slice lb_token_mdstr = grpc_mdstr_from_buffer(
(uint8_t *)server->load_balance_token, lb_token_length);
user_data = grpc_mdelem_from_metadata_strings(
exec_ctx, GRPC_MDSTR_LB_TOKEN, lb_token_mdstr);
diff --git a/src/core/ext/transport/chttp2/transport/bin_decoder.c b/src/core/ext/transport/chttp2/transport/bin_decoder.c
index 8db36e4a7f..1a3637a1e3 100644
--- a/src/core/ext/transport/chttp2/transport/bin_decoder.c
+++ b/src/core/ext/transport/chttp2/transport/bin_decoder.c
@@ -157,7 +157,7 @@ grpc_slice grpc_chttp2_base64_decode(grpc_exec_ctx *exec_ctx,
"grpc_chttp2_base64_decode has a length of %d, which is not a "
"multiple of 4.\n",
(int)input_length);
- return gpr_empty_slice();
+ return grpc_empty_slice();
}
if (input_length > 0) {
@@ -182,7 +182,7 @@ grpc_slice grpc_chttp2_base64_decode(grpc_exec_ctx *exec_ctx,
gpr_log(GPR_ERROR, "Base64 decoding failed, input string:\n%s\n", s);
gpr_free(s);
grpc_slice_unref_internal(exec_ctx, output);
- return gpr_empty_slice();
+ return grpc_empty_slice();
}
GPR_ASSERT(ctx.output_cur == GRPC_SLICE_END_PTR(output));
GPR_ASSERT(ctx.input_cur == GRPC_SLICE_END_PTR(input));
@@ -204,7 +204,7 @@ grpc_slice grpc_chttp2_base64_decode_with_length(grpc_exec_ctx *exec_ctx,
"has a tail of 1 byte.\n",
(int)input_length);
grpc_slice_unref_internal(exec_ctx, output);
- return gpr_empty_slice();
+ return grpc_empty_slice();
}
if (output_length > input_length / 4 * 3 + tail_xtra[input_length % 4]) {
@@ -214,7 +214,7 @@ grpc_slice grpc_chttp2_base64_decode_with_length(grpc_exec_ctx *exec_ctx,
(int)output_length,
(int)(input_length / 4 * 3 + tail_xtra[input_length % 4]));
grpc_slice_unref_internal(exec_ctx, output);
- return gpr_empty_slice();
+ return grpc_empty_slice();
}
ctx.input_cur = GRPC_SLICE_START_PTR(input);
@@ -228,7 +228,7 @@ grpc_slice grpc_chttp2_base64_decode_with_length(grpc_exec_ctx *exec_ctx,
gpr_log(GPR_ERROR, "Base64 decoding failed, input string:\n%s\n", s);
gpr_free(s);
grpc_slice_unref_internal(exec_ctx, output);
- return gpr_empty_slice();
+ return grpc_empty_slice();
}
GPR_ASSERT(ctx.output_cur == GRPC_SLICE_END_PTR(output));
GPR_ASSERT(ctx.input_cur <= GRPC_SLICE_END_PTR(input));
diff --git a/src/core/ext/transport/chttp2/transport/bin_encoder.c b/src/core/ext/transport/chttp2/transport/bin_encoder.c
index af25a4352a..e301c073f3 100644
--- a/src/core/ext/transport/chttp2/transport/bin_encoder.c
+++ b/src/core/ext/transport/chttp2/transport/bin_encoder.c
@@ -177,8 +177,7 @@ static void enc_add1(huff_out *out, uint8_t a) {
enc_flush_some(out);
}
-grpc_slice grpc_chttp2_base64_encode_and_huffman_compress_impl(
- grpc_slice input) {
+grpc_slice grpc_chttp2_base64_encode_and_huffman_compress(grpc_slice input) {
size_t input_length = GRPC_SLICE_LENGTH(input);
size_t input_triplets = input_length / 3;
size_t tail_case = input_length % 3;
diff --git a/src/core/ext/transport/chttp2/transport/bin_encoder.h b/src/core/ext/transport/chttp2/transport/bin_encoder.h
index 477559d0e2..0f899c8e34 100644
--- a/src/core/ext/transport/chttp2/transport/bin_encoder.h
+++ b/src/core/ext/transport/chttp2/transport/bin_encoder.h
@@ -49,7 +49,6 @@ grpc_slice grpc_chttp2_huffman_compress(grpc_slice input);
grpc_slice y = grpc_chttp2_huffman_compress(x);
grpc_slice_unref_internal(exec_ctx, x);
return y; */
-grpc_slice grpc_chttp2_base64_encode_and_huffman_compress_impl(
- grpc_slice input);
+grpc_slice grpc_chttp2_base64_encode_and_huffman_compress(grpc_slice input);
#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_BIN_ENCODER_H */
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_plugin.c b/src/core/ext/transport/chttp2/transport/chttp2_plugin.c
index bd87253ed3..59b21e3330 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_plugin.c
+++ b/src/core/ext/transport/chttp2/transport/chttp2_plugin.c
@@ -31,14 +31,11 @@
*
*/
-#include "src/core/ext/transport/chttp2/transport/bin_encoder.h"
#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/transport/metadata.h"
void grpc_chttp2_plugin_init(void) {
- grpc_chttp2_base64_encode_and_huffman_compress =
- grpc_chttp2_base64_encode_and_huffman_compress_impl;
grpc_register_tracer("http", &grpc_http_trace);
grpc_register_tracer("flowctl", &grpc_flowctl_trace);
}
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
index 7baeddc7b8..fac9a08584 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
@@ -876,7 +876,7 @@ void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx,
static bool contains_non_ok_status(grpc_metadata_batch *batch) {
grpc_linked_mdelem *l;
for (l = batch->list.head; l; l = l->next) {
- if (l->md->key == GRPC_MDSTR_GRPC_STATUS &&
+ if (grpc_slice_cmp(l->md->key, GRPC_MDSTR_GRPC_STATUS) == 0 &&
l->md != GRPC_MDELEM_GRPC_STATUS_0) {
return true;
}
@@ -1477,16 +1477,14 @@ void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
char status_string[GPR_LTOA_MIN_BUFSIZE];
gpr_ltoa(status, status_string);
grpc_chttp2_incoming_metadata_buffer_add(
- &s->metadata_buffer[1], grpc_mdelem_from_metadata_strings(
- exec_ctx, GRPC_MDSTR_GRPC_STATUS,
- grpc_mdstr_from_string(status_string)));
+ &s->metadata_buffer[1],
+ grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_STATUS,
+ grpc_slice_from_copied_string(status_string)));
if (slice) {
grpc_chttp2_incoming_metadata_buffer_add(
&s->metadata_buffer[1],
- grpc_mdelem_from_metadata_strings(
- exec_ctx, GRPC_MDSTR_GRPC_MESSAGE,
- grpc_mdstr_from_slice(exec_ctx,
- grpc_slice_ref_internal(*slice))));
+ grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_MESSAGE,
+ grpc_slice_ref_internal(*slice)));
}
s->published_metadata[1] = GRPC_METADATA_SYNTHESIZED_FROM_FAKE;
grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
diff --git a/src/core/ext/transport/chttp2/transport/hpack_encoder.c b/src/core/ext/transport/chttp2/transport/hpack_encoder.c
index 49a8326f62..9b27071c87 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_encoder.c
+++ b/src/core/ext/transport/chttp2/transport/hpack_encoder.c
@@ -64,6 +64,10 @@
/* don't consider adding anything bigger than this to the hpack table */
#define MAX_DECODER_SPACE_USAGE 512
+static grpc_slice_refcount terminal_slice_refcount = {NULL, NULL};
+static const grpc_slice terminal_slice = {&terminal_slice_refcount,
+ .data.refcounted = {0, 0}};
+
extern int grpc_http_trace;
typedef struct {
@@ -186,8 +190,9 @@ static void evict_entry(grpc_chttp2_hpack_compressor *c) {
/* add an element to the decoder table */
static void add_elem(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
grpc_mdelem *elem) {
- uint32_t key_hash = elem->key->hash;
- uint32_t elem_hash = GRPC_MDSTR_KV_HASH(key_hash, elem->value->hash);
+ uint32_t key_hash = grpc_slice_hash(elem->key);
+ uint32_t value_hash = grpc_slice_hash(elem->value);
+ uint32_t elem_hash = GRPC_MDSTR_KV_HASH(key_hash, value_hash);
uint32_t new_index = c->tail_remote_index + c->table_elems + 1;
size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem);
@@ -241,24 +246,34 @@ static void add_elem(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
/* do exactly the same for the key (so we can find by that again too) */
- if (c->entries_keys[HASH_FRAGMENT_2(key_hash)] == elem->key) {
+ if (grpc_slice_cmp(c->entries_keys[HASH_FRAGMENT_2(key_hash)], elem->key) ==
+ 0) {
c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index;
- } else if (c->entries_keys[HASH_FRAGMENT_3(key_hash)] == elem->key) {
+ } else if (grpc_slice_cmp(c->entries_keys[HASH_FRAGMENT_3(key_hash)],
+ elem->key) == 0) {
c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index;
- } else if (c->entries_keys[HASH_FRAGMENT_2(key_hash)] == NULL) {
- c->entries_keys[HASH_FRAGMENT_2(key_hash)] = GRPC_MDSTR_REF(elem->key);
+ } else if (c->entries_keys[HASH_FRAGMENT_2(key_hash)].refcount ==
+ &terminal_slice_refcount) {
+ c->entries_keys[HASH_FRAGMENT_2(key_hash)] =
+ grpc_slice_ref_internal(elem->key);
c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index;
- } else if (c->entries_keys[HASH_FRAGMENT_3(key_hash)] == NULL) {
- c->entries_keys[HASH_FRAGMENT_3(key_hash)] = GRPC_MDSTR_REF(elem->key);
+ } else if (c->entries_keys[HASH_FRAGMENT_3(key_hash)].refcount ==
+ &terminal_slice_refcount) {
+ c->entries_keys[HASH_FRAGMENT_3(key_hash)] =
+ grpc_slice_ref_internal(elem->key);
c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index;
} else if (c->indices_keys[HASH_FRAGMENT_2(key_hash)] <
c->indices_keys[HASH_FRAGMENT_3(key_hash)]) {
- GRPC_MDSTR_UNREF(exec_ctx, c->entries_keys[HASH_FRAGMENT_2(key_hash)]);
- c->entries_keys[HASH_FRAGMENT_2(key_hash)] = GRPC_MDSTR_REF(elem->key);
+ grpc_slice_unref_internal(exec_ctx,
+ c->entries_keys[HASH_FRAGMENT_2(key_hash)]);
+ c->entries_keys[HASH_FRAGMENT_2(key_hash)] =
+ grpc_slice_ref_internal(elem->key);
c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index;
} else {
- GRPC_MDSTR_UNREF(exec_ctx, c->entries_keys[HASH_FRAGMENT_3(key_hash)]);
- c->entries_keys[HASH_FRAGMENT_3(key_hash)] = GRPC_MDSTR_REF(elem->key);
+ grpc_slice_unref_internal(exec_ctx,
+ c->entries_keys[HASH_FRAGMENT_3(key_hash)]);
+ c->entries_keys[HASH_FRAGMENT_3(key_hash)] =
+ grpc_slice_ref_internal(elem->key);
c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index;
}
}
@@ -271,15 +286,13 @@ static void emit_indexed(grpc_chttp2_hpack_compressor *c, uint32_t elem_index,
}
static grpc_slice get_wire_value(grpc_mdelem *elem, uint8_t *huffman_prefix) {
- if (grpc_is_binary_header(
- (const char *)GRPC_SLICE_START_PTR(elem->key->slice),
- GRPC_SLICE_LENGTH(elem->key->slice))) {
+ if (grpc_slice_is_binary_header(elem->key)) {
*huffman_prefix = 0x80;
- return grpc_mdstr_as_base64_encoded_and_huffman_compressed(elem->value);
+ return grpc_chttp2_base64_encode_and_huffman_compress(elem->value);
}
/* TODO(ctiller): opportunistically compress non-binary headers */
*huffman_prefix = 0x00;
- return elem->value->slice;
+ return grpc_slice_ref(elem->value);
}
static void emit_lithdr_incidx(grpc_chttp2_hpack_compressor *c,
@@ -296,7 +309,7 @@ static void emit_lithdr_incidx(grpc_chttp2_hpack_compressor *c,
add_tiny_header_data(st, len_pfx), len_pfx);
GRPC_CHTTP2_WRITE_VARINT((uint32_t)len_val, 1, huffman_prefix,
add_tiny_header_data(st, len_val_len), len_val_len);
- add_header_data(st, grpc_slice_ref_internal(value_slice));
+ add_header_data(st, value_slice);
}
static void emit_lithdr_noidx(grpc_chttp2_hpack_compressor *c,
@@ -313,12 +326,12 @@ static void emit_lithdr_noidx(grpc_chttp2_hpack_compressor *c,
add_tiny_header_data(st, len_pfx), len_pfx);
GRPC_CHTTP2_WRITE_VARINT((uint32_t)len_val, 1, huffman_prefix,
add_tiny_header_data(st, len_val_len), len_val_len);
- add_header_data(st, grpc_slice_ref_internal(value_slice));
+ add_header_data(st, value_slice);
}
static void emit_lithdr_incidx_v(grpc_chttp2_hpack_compressor *c,
grpc_mdelem *elem, framer_state *st) {
- uint32_t len_key = (uint32_t)GRPC_SLICE_LENGTH(elem->key->slice);
+ uint32_t len_key = (uint32_t)GRPC_SLICE_LENGTH(elem->key);
uint8_t huffman_prefix;
grpc_slice value_slice = get_wire_value(elem, &huffman_prefix);
uint32_t len_val = (uint32_t)GRPC_SLICE_LENGTH(value_slice);
@@ -329,15 +342,15 @@ static void emit_lithdr_incidx_v(grpc_chttp2_hpack_compressor *c,
*add_tiny_header_data(st, 1) = 0x40;
GRPC_CHTTP2_WRITE_VARINT(len_key, 1, 0x00,
add_tiny_header_data(st, len_key_len), len_key_len);
- add_header_data(st, grpc_slice_ref_internal(elem->key->slice));
+ add_header_data(st, grpc_slice_ref_internal(elem->key));
GRPC_CHTTP2_WRITE_VARINT(len_val, 1, huffman_prefix,
add_tiny_header_data(st, len_val_len), len_val_len);
- add_header_data(st, grpc_slice_ref_internal(value_slice));
+ add_header_data(st, value_slice);
}
static void emit_lithdr_noidx_v(grpc_chttp2_hpack_compressor *c,
grpc_mdelem *elem, framer_state *st) {
- uint32_t len_key = (uint32_t)GRPC_SLICE_LENGTH(elem->key->slice);
+ uint32_t len_key = (uint32_t)GRPC_SLICE_LENGTH(elem->key);
uint8_t huffman_prefix;
grpc_slice value_slice = get_wire_value(elem, &huffman_prefix);
uint32_t len_val = (uint32_t)GRPC_SLICE_LENGTH(value_slice);
@@ -348,10 +361,10 @@ static void emit_lithdr_noidx_v(grpc_chttp2_hpack_compressor *c,
*add_tiny_header_data(st, 1) = 0x00;
GRPC_CHTTP2_WRITE_VARINT(len_key, 1, 0x00,
add_tiny_header_data(st, len_key_len), len_key_len);
- add_header_data(st, grpc_slice_ref_internal(elem->key->slice));
+ add_header_data(st, grpc_slice_ref_internal(elem->key));
GRPC_CHTTP2_WRITE_VARINT(len_val, 1, huffman_prefix,
add_tiny_header_data(st, len_val_len), len_val_len);
- add_header_data(st, grpc_slice_ref_internal(value_slice));
+ add_header_data(st, value_slice);
}
static void emit_advertise_table_size_change(grpc_chttp2_hpack_compressor *c,
@@ -370,14 +383,15 @@ static uint32_t dynidx(grpc_chttp2_hpack_compressor *c, uint32_t elem_index) {
/* encode an mdelem */
static void hpack_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
grpc_mdelem *elem, framer_state *st) {
- uint32_t key_hash = elem->key->hash;
- uint32_t elem_hash = GRPC_MDSTR_KV_HASH(key_hash, elem->value->hash);
+ uint32_t key_hash = grpc_slice_hash(elem->key);
+ uint32_t value_hash = grpc_slice_hash(elem->value);
+ uint32_t elem_hash = GRPC_MDSTR_KV_HASH(key_hash, value_hash);
size_t decoder_space_usage;
uint32_t indices_key;
int should_add_elem;
- GPR_ASSERT(GRPC_SLICE_LENGTH(elem->key->slice) > 0);
- if (GRPC_SLICE_START_PTR(elem->key->slice)[0] != ':') { /* regular header */
+ GPR_ASSERT(GRPC_SLICE_LENGTH(elem->key) > 0);
+ if (GRPC_SLICE_START_PTR(elem->key)[0] != ':') { /* regular header */
st->seen_regular_header = 1;
} else {
GPR_ASSERT(
@@ -414,7 +428,8 @@ static void hpack_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
/* no hits for the elem... maybe there's a key? */
indices_key = c->indices_keys[HASH_FRAGMENT_2(key_hash)];
- if (c->entries_keys[HASH_FRAGMENT_2(key_hash)] == elem->key &&
+ if (grpc_slice_cmp(c->entries_keys[HASH_FRAGMENT_2(key_hash)], elem->key) ==
+ 0 &&
indices_key > c->tail_remote_index) {
/* HIT: key (first cuckoo hash) */
if (should_add_elem) {
@@ -429,7 +444,8 @@ static void hpack_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
}
indices_key = c->indices_keys[HASH_FRAGMENT_3(key_hash)];
- if (c->entries_keys[HASH_FRAGMENT_3(key_hash)] == elem->key &&
+ if (grpc_slice_cmp(c->entries_keys[HASH_FRAGMENT_3(key_hash)], elem->key) ==
+ 0 &&
indices_key > c->tail_remote_index) {
/* HIT: key (first cuckoo hash) */
if (should_add_elem) {
@@ -466,8 +482,8 @@ static void deadline_enc(grpc_exec_ctx *exec_ctx,
grpc_mdelem *mdelem;
grpc_http2_encode_timeout(
gpr_time_sub(deadline, gpr_now(deadline.clock_type)), timeout_str);
- mdelem = grpc_mdelem_from_metadata_strings(
- exec_ctx, GRPC_MDSTR_GRPC_TIMEOUT, grpc_mdstr_from_string(timeout_str));
+ mdelem = grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_TIMEOUT,
+ grpc_slice_from_copied_string(timeout_str));
hpack_enc(exec_ctx, c, mdelem, st);
GRPC_MDELEM_UNREF(exec_ctx, mdelem);
}
@@ -484,14 +500,21 @@ void grpc_chttp2_hpack_compressor_init(grpc_chttp2_hpack_compressor *c) {
gpr_malloc(sizeof(*c->table_elem_size) * c->cap_table_elems);
memset(c->table_elem_size, 0,
sizeof(*c->table_elem_size) * c->cap_table_elems);
+ for (size_t i = 0; i < GPR_ARRAY_SIZE(c->entries_keys); i++) {
+ c->entries_keys[i] = terminal_slice;
+ }
}
void grpc_chttp2_hpack_compressor_destroy(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_compressor *c) {
int i;
for (i = 0; i < GRPC_CHTTP2_HPACKC_NUM_VALUES; i++) {
- if (c->entries_keys[i]) GRPC_MDSTR_UNREF(exec_ctx, c->entries_keys[i]);
- if (c->entries_elems[i]) GRPC_MDELEM_UNREF(exec_ctx, c->entries_elems[i]);
+ if (c->entries_keys[i].refcount != &terminal_slice_refcount) {
+ grpc_slice_unref_internal(exec_ctx, c->entries_keys[i]);
+ }
+ if (c->entries_elems[i]) {
+ GRPC_MDELEM_UNREF(exec_ctx, c->entries_elems[i]);
+ }
}
gpr_free(c->table_elem_size);
}
diff --git a/src/core/ext/transport/chttp2/transport/hpack_encoder.h b/src/core/ext/transport/chttp2/transport/hpack_encoder.h
index 3a35496ec8..82d61a15ec 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_encoder.h
+++ b/src/core/ext/transport/chttp2/transport/hpack_encoder.h
@@ -74,7 +74,7 @@ typedef struct {
/* entry tables for keys & elems: these tables track values that have been
seen and *may* be in the decompressor table */
- grpc_mdstr *entries_keys[GRPC_CHTTP2_HPACKC_NUM_VALUES];
+ grpc_slice entries_keys[GRPC_CHTTP2_HPACKC_NUM_VALUES];
grpc_mdelem *entries_elems[GRPC_CHTTP2_HPACKC_NUM_VALUES];
uint32_t indices_keys[GRPC_CHTTP2_HPACKC_NUM_VALUES];
uint32_t indices_elems[GRPC_CHTTP2_HPACKC_NUM_VALUES];
diff --git a/src/core/ext/transport/chttp2/transport/hpack_parser.c b/src/core/ext/transport/chttp2/transport/hpack_parser.c
index f4e69df12d..86c65d4b5a 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_parser.c
+++ b/src/core/ext/transport/chttp2/transport/hpack_parser.c
@@ -52,6 +52,7 @@
#include "src/core/ext/transport/chttp2/transport/bin_encoder.h"
#include "src/core/ext/transport/chttp2/transport/http2_errors.h"
#include "src/core/lib/profiling/timers.h"
+#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/support/string.h"
extern int grpc_http_trace;
@@ -681,9 +682,9 @@ static grpc_error *on_hdr(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p,
return GRPC_ERROR_NONE;
}
-static grpc_mdstr *take_string(grpc_chttp2_hpack_parser *p,
- grpc_chttp2_hpack_parser_string *str) {
- grpc_mdstr *s = grpc_mdstr_from_buffer((uint8_t *)str->str, str->length);
+static grpc_slice take_string(grpc_chttp2_hpack_parser *p,
+ grpc_chttp2_hpack_parser_string *str) {
+ grpc_slice s = grpc_slice_from_copied_buffer(str->str, str->length);
str->length = 0;
return s;
}
@@ -815,10 +816,11 @@ static grpc_error *finish_lithdr_incidx(grpc_exec_ctx *exec_ctx,
const uint8_t *end) {
grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
GPR_ASSERT(md != NULL); /* handled in string parsing */
- grpc_error *err = on_hdr(exec_ctx, p, grpc_mdelem_from_metadata_strings(
- exec_ctx, GRPC_MDSTR_REF(md->key),
- take_string(p, &p->value)),
- 1);
+ grpc_error *err =
+ on_hdr(exec_ctx, p,
+ grpc_mdelem_from_slices(exec_ctx, grpc_slice_ref_internal(md->key),
+ take_string(p, &p->value)),
+ 1);
if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err);
return parse_begin(exec_ctx, p, cur, end);
}
@@ -828,10 +830,10 @@ static grpc_error *finish_lithdr_incidx_v(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_parser *p,
const uint8_t *cur,
const uint8_t *end) {
- grpc_error *err = on_hdr(exec_ctx, p, grpc_mdelem_from_metadata_strings(
- exec_ctx, take_string(p, &p->key),
- take_string(p, &p->value)),
- 1);
+ grpc_error *err = on_hdr(
+ exec_ctx, p, grpc_mdelem_from_slices(exec_ctx, take_string(p, &p->key),
+ take_string(p, &p->value)),
+ 1);
if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err);
return parse_begin(exec_ctx, p, cur, end);
}
@@ -883,10 +885,11 @@ static grpc_error *finish_lithdr_notidx(grpc_exec_ctx *exec_ctx,
const uint8_t *end) {
grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
GPR_ASSERT(md != NULL); /* handled in string parsing */
- grpc_error *err = on_hdr(exec_ctx, p, grpc_mdelem_from_metadata_strings(
- exec_ctx, GRPC_MDSTR_REF(md->key),
- take_string(p, &p->value)),
- 0);
+ grpc_error *err =
+ on_hdr(exec_ctx, p,
+ grpc_mdelem_from_slices(exec_ctx, grpc_slice_ref_internal(md->key),
+ take_string(p, &p->value)),
+ 0);
if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err);
return parse_begin(exec_ctx, p, cur, end);
}
@@ -896,10 +899,10 @@ static grpc_error *finish_lithdr_notidx_v(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_parser *p,
const uint8_t *cur,
const uint8_t *end) {
- grpc_error *err = on_hdr(exec_ctx, p, grpc_mdelem_from_metadata_strings(
- exec_ctx, take_string(p, &p->key),
- take_string(p, &p->value)),
- 0);
+ grpc_error *err = on_hdr(
+ exec_ctx, p, grpc_mdelem_from_slices(exec_ctx, take_string(p, &p->key),
+ take_string(p, &p->value)),
+ 0);
if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err);
return parse_begin(exec_ctx, p, cur, end);
}
@@ -951,10 +954,11 @@ static grpc_error *finish_lithdr_nvridx(grpc_exec_ctx *exec_ctx,
const uint8_t *end) {
grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
GPR_ASSERT(md != NULL); /* handled in string parsing */
- grpc_error *err = on_hdr(exec_ctx, p, grpc_mdelem_from_metadata_strings(
- exec_ctx, GRPC_MDSTR_REF(md->key),
- take_string(p, &p->value)),
- 0);
+ grpc_error *err =
+ on_hdr(exec_ctx, p,
+ grpc_mdelem_from_slices(exec_ctx, grpc_slice_ref_internal(md->key),
+ take_string(p, &p->value)),
+ 0);
if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err);
return parse_begin(exec_ctx, p, cur, end);
}
@@ -964,10 +968,10 @@ static grpc_error *finish_lithdr_nvridx_v(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_parser *p,
const uint8_t *cur,
const uint8_t *end) {
- grpc_error *err = on_hdr(exec_ctx, p, grpc_mdelem_from_metadata_strings(
- exec_ctx, take_string(p, &p->key),
- take_string(p, &p->value)),
- 0);
+ grpc_error *err = on_hdr(
+ exec_ctx, p, grpc_mdelem_from_slices(exec_ctx, take_string(p, &p->key),
+ take_string(p, &p->value)),
+ 0);
if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err);
return parse_begin(exec_ctx, p, cur, end);
}
@@ -1502,9 +1506,7 @@ static grpc_error *is_binary_indexed_header(grpc_chttp2_hpack_parser *p,
GRPC_ERROR_INT_INDEX, (intptr_t)p->index),
GRPC_ERROR_INT_SIZE, (intptr_t)p->table.num_ents);
}
- *is = grpc_is_binary_header(
- (const char *)GRPC_SLICE_START_PTR(elem->key->slice),
- GRPC_SLICE_LENGTH(elem->key->slice));
+ *is = grpc_slice_is_binary_header(elem->key);
return GRPC_ERROR_NONE;
}
diff --git a/src/core/ext/transport/chttp2/transport/hpack_table.c b/src/core/ext/transport/chttp2/transport/hpack_table.c
index 26d4036d49..9124e37c45 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_table.c
+++ b/src/core/ext/transport/chttp2/transport/hpack_table.c
@@ -190,8 +190,11 @@ void grpc_chttp2_hptbl_init(grpc_exec_ctx *exec_ctx, grpc_chttp2_hptbl *tbl) {
tbl->ents = gpr_malloc(sizeof(*tbl->ents) * tbl->cap_entries);
memset(tbl->ents, 0, sizeof(*tbl->ents) * tbl->cap_entries);
for (i = 1; i <= GRPC_CHTTP2_LAST_STATIC_ENTRY; i++) {
- tbl->static_ents[i - 1] = grpc_mdelem_from_strings(
- exec_ctx, static_table[i].key, static_table[i].value);
+ tbl->static_ents[i - 1] = grpc_mdelem_from_slices(
+ exec_ctx,
+ grpc_slice_intern(grpc_slice_from_static_string(static_table[i].key)),
+ grpc_slice_intern(
+ grpc_slice_from_static_string(static_table[i].value)));
}
}
@@ -228,8 +231,8 @@ grpc_mdelem *grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl,
/* Evict one element from the table */
static void evict1(grpc_exec_ctx *exec_ctx, grpc_chttp2_hptbl *tbl) {
grpc_mdelem *first_ent = tbl->ents[tbl->first_ent];
- size_t elem_bytes = GRPC_SLICE_LENGTH(first_ent->key->slice) +
- GRPC_SLICE_LENGTH(first_ent->value->slice) +
+ size_t elem_bytes = GRPC_SLICE_LENGTH(first_ent->key) +
+ GRPC_SLICE_LENGTH(first_ent->value) +
GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD;
GPR_ASSERT(elem_bytes <= tbl->mem_used);
tbl->mem_used -= (uint32_t)elem_bytes;
@@ -303,8 +306,8 @@ grpc_error *grpc_chttp2_hptbl_set_current_table_size(grpc_exec_ctx *exec_ctx,
grpc_error *grpc_chttp2_hptbl_add(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hptbl *tbl, grpc_mdelem *md) {
/* determine how many bytes of buffer this entry represents */
- size_t elem_bytes = GRPC_SLICE_LENGTH(md->key->slice) +
- GRPC_SLICE_LENGTH(md->value->slice) +
+ size_t elem_bytes = GRPC_SLICE_LENGTH(md->key) +
+ GRPC_SLICE_LENGTH(md->value) +
GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD;
if (tbl->current_table_bytes > tbl->max_bytes) {
@@ -359,9 +362,9 @@ grpc_chttp2_hptbl_find_result grpc_chttp2_hptbl_find(
/* See if the string is in the static table */
for (i = 0; i < GRPC_CHTTP2_LAST_STATIC_ENTRY; i++) {
grpc_mdelem *ent = tbl->static_ents[i];
- if (md->key != ent->key) continue;
+ if (grpc_slice_cmp(md->key, ent->key) != 0) continue;
r.index = i + 1u;
- r.has_value = md->value == ent->value;
+ r.has_value = grpc_slice_cmp(md->value, ent->value) == 0;
if (r.has_value) return r;
}
@@ -370,9 +373,9 @@ grpc_chttp2_hptbl_find_result grpc_chttp2_hptbl_find(
uint32_t idx =
(uint32_t)(tbl->num_ents - i + GRPC_CHTTP2_LAST_STATIC_ENTRY);
grpc_mdelem *ent = tbl->ents[(tbl->first_ent + i) % tbl->cap_entries];
- if (md->key != ent->key) continue;
+ if (grpc_slice_cmp(md->key, ent->key) != 0) continue;
r.index = idx;
- r.has_value = md->value == ent->value;
+ r.has_value = grpc_slice_cmp(md->value, ent->value) == 0;
if (r.has_value) return r;
}
diff --git a/src/core/ext/transport/chttp2/transport/parsing.c b/src/core/ext/transport/chttp2/transport/parsing.c
index 4fb5dc7bd2..b8ab987104 100644
--- a/src/core/ext/transport/chttp2/transport/parsing.c
+++ b/src/core/ext/transport/chttp2/transport/parsing.c
@@ -200,7 +200,7 @@ grpc_error *grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
return err;
}
if (t->incoming_frame_size == 0) {
- err = parse_frame_slice(exec_ctx, t, gpr_empty_slice(), 1);
+ err = parse_frame_slice(exec_ctx, t, grpc_empty_slice(), 1);
if (err != GRPC_ERROR_NONE) {
return err;
}
diff --git a/src/core/lib/channel/channel_stack.c b/src/core/lib/channel/channel_stack.c
index 285ac178af..0f3957d5ac 100644
--- a/src/core/lib/channel/channel_stack.c
+++ b/src/core/lib/channel/channel_stack.c
@@ -162,7 +162,7 @@ grpc_error *grpc_call_stack_init(
grpc_exec_ctx *exec_ctx, grpc_channel_stack *channel_stack,
int initial_refs, grpc_iomgr_cb_func destroy, void *destroy_arg,
grpc_call_context_element *context, const void *transport_server_data,
- grpc_mdstr *path, gpr_timespec start_time, gpr_timespec deadline,
+ grpc_slice path, gpr_timespec start_time, gpr_timespec deadline,
grpc_call_stack *call_stack) {
grpc_channel_element *channel_elems = CHANNEL_ELEMS_FROM_STACK(channel_stack);
grpc_call_element_args args;
diff --git a/src/core/lib/channel/channel_stack.h b/src/core/lib/channel/channel_stack.h
index 004643d45f..376756533b 100644
--- a/src/core/lib/channel/channel_stack.h
+++ b/src/core/lib/channel/channel_stack.h
@@ -74,7 +74,7 @@ typedef struct {
grpc_call_stack *call_stack;
const void *server_transport_data;
grpc_call_context_element *context;
- grpc_mdstr *path;
+ grpc_slice path;
gpr_timespec start_time;
gpr_timespec deadline;
} grpc_call_element_args;
@@ -231,7 +231,7 @@ grpc_error *grpc_call_stack_init(
grpc_exec_ctx *exec_ctx, grpc_channel_stack *channel_stack,
int initial_refs, grpc_iomgr_cb_func destroy, void *destroy_arg,
grpc_call_context_element *context, const void *transport_server_data,
- grpc_mdstr *path, gpr_timespec start_time, gpr_timespec deadline,
+ grpc_slice path, gpr_timespec start_time, gpr_timespec deadline,
grpc_call_stack *call_stack);
/* Set a pollset or a pollset_set for a call stack: must occur before the first
* op is started */
diff --git a/src/core/lib/channel/compress_filter.c b/src/core/lib/channel/compress_filter.c
index 96188f01c4..96564757b4 100644
--- a/src/core/lib/channel/compress_filter.c
+++ b/src/core/lib/channel/compress_filter.c
@@ -45,6 +45,7 @@
#include "src/core/lib/compression/message_compress.h"
#include "src/core/lib/profiling/timers.h"
#include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/slice/slice_string_helpers.h"
#include "src/core/lib/support/string.h"
#include "src/core/lib/transport/static_metadata.h"
@@ -89,21 +90,23 @@ static grpc_mdelem *compression_md_filter(grpc_exec_ctx *exec_ctx,
call_data *calld = elem->call_data;
channel_data *channeld = elem->channel_data;
- if (md->key == GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST) {
- const char *md_c_str = grpc_mdstr_as_c_string(md->value);
- if (!grpc_compression_algorithm_parse(md_c_str, strlen(md_c_str),
+ if (grpc_slice_cmp(md->key, GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST) == 0) {
+ if (!grpc_compression_algorithm_parse(md->value,
&calld->compression_algorithm)) {
+ char *val = grpc_dump_slice(md->value, GPR_DUMP_ASCII);
gpr_log(GPR_ERROR,
- "Invalid compression algorithm: '%s' (unknown). Ignoring.",
- md_c_str);
+ "Invalid compression algorithm: '%s' (unknown). Ignoring.", val);
+ gpr_free(val);
calld->compression_algorithm = GRPC_COMPRESS_NONE;
}
if (!GPR_BITGET(channeld->enabled_algorithms_bitset,
calld->compression_algorithm)) {
+ char *val = grpc_dump_slice(md->value, GPR_DUMP_ASCII);
gpr_log(GPR_ERROR,
"Invalid compression algorithm: '%s' (previously disabled). "
"Ignoring.",
- md_c_str);
+ val);
+ gpr_free(val);
calld->compression_algorithm = GRPC_COMPRESS_NONE;
}
calld->has_compression_algorithm = 1;
diff --git a/src/core/lib/channel/http_client_filter.c b/src/core/lib/channel/http_client_filter.c
index 27064e0fb8..4b62a35750 100644
--- a/src/core/lib/channel/http_client_filter.c
+++ b/src/core/lib/channel/http_client_filter.c
@@ -38,6 +38,7 @@
#include "src/core/lib/profiling/timers.h"
#include "src/core/lib/slice/percent_encoding.h"
#include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/slice/slice_string_helpers.h"
#include "src/core/lib/support/string.h"
#include "src/core/lib/transport/static_metadata.h"
#include "src/core/lib/transport/transport_impl.h"
@@ -98,34 +99,34 @@ static grpc_mdelem *client_recv_filter(grpc_exec_ctx *exec_ctx, void *user_data,
grpc_call_element *elem = user_data;
if (md == GRPC_MDELEM_STATUS_200) {
return NULL;
- } else if (md->key == GRPC_MDSTR_STATUS) {
+ } else if (grpc_slice_cmp(md->key, GRPC_MDSTR_STATUS) == 0) {
char *message_string;
- gpr_asprintf(&message_string, "Received http2 header with status: %s",
- grpc_mdstr_as_c_string(md->value));
+ char *val = grpc_dump_slice(md->value, GPR_DUMP_ASCII);
+ gpr_asprintf(&message_string, "Received http2 header with status: %s", val);
grpc_slice message = grpc_slice_from_copied_string(message_string);
gpr_free(message_string);
+ gpr_free(val);
grpc_call_element_send_close_with_message(exec_ctx, elem,
GRPC_STATUS_CANCELLED, &message);
return NULL;
- } else if (md->key == GRPC_MDSTR_GRPC_MESSAGE) {
+ } else if (grpc_slice_cmp(md->key, GRPC_MDSTR_GRPC_MESSAGE) == 0) {
grpc_slice pct_decoded_msg =
- grpc_permissive_percent_decode_slice(md->value->slice);
- if (grpc_slice_is_equivalent(pct_decoded_msg, md->value->slice)) {
+ grpc_permissive_percent_decode_slice(md->value);
+ if (grpc_slice_is_equivalent(pct_decoded_msg, md->value)) {
grpc_slice_unref(pct_decoded_msg);
return md;
} else {
- return grpc_mdelem_from_metadata_strings(
- exec_ctx, GRPC_MDSTR_GRPC_MESSAGE,
- grpc_mdstr_from_slice(exec_ctx, pct_decoded_msg));
+ return grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_MESSAGE,
+ pct_decoded_msg);
}
} else if (md == GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC) {
return NULL;
- } else if (md->key == GRPC_MDSTR_CONTENT_TYPE) {
- const char *value_str = grpc_mdstr_as_c_string(md->value);
- if (strncmp(value_str, EXPECTED_CONTENT_TYPE,
- EXPECTED_CONTENT_TYPE_LENGTH) == 0 &&
- (value_str[EXPECTED_CONTENT_TYPE_LENGTH] == '+' ||
- value_str[EXPECTED_CONTENT_TYPE_LENGTH] == ';')) {
+ } else if (grpc_slice_cmp(md->key, GRPC_MDSTR_CONTENT_TYPE) == 0) {
+ if (grpc_slice_buf_start_eq(md->value, EXPECTED_CONTENT_TYPE,
+ EXPECTED_CONTENT_TYPE_LENGTH) &&
+ (GRPC_SLICE_START_PTR(md->value)[EXPECTED_CONTENT_TYPE_LENGTH] == '+' ||
+ GRPC_SLICE_START_PTR(md->value)[EXPECTED_CONTENT_TYPE_LENGTH] ==
+ ';')) {
/* Although the C implementation doesn't (currently) generate them,
any custom +-suffix is explicitly valid. */
/* TODO(klempner): We should consider preallocating common values such
@@ -134,7 +135,9 @@ static grpc_mdelem *client_recv_filter(grpc_exec_ctx *exec_ctx, void *user_data,
} else {
/* TODO(klempner): We're currently allowing this, but we shouldn't
see it without a proxy so log for now. */
- gpr_log(GPR_INFO, "Unexpected content-type '%s'", value_str);
+ char *val = grpc_dump_slice(md->value, GPR_DUMP_ASCII);
+ gpr_log(GPR_INFO, "Unexpected content-type '%s'", val);
+ gpr_free(val);
}
return NULL;
}
@@ -182,11 +185,11 @@ static void send_done(grpc_exec_ctx *exec_ctx, void *elemp, grpc_error *error) {
static grpc_mdelem *client_strip_filter(grpc_exec_ctx *exec_ctx,
void *user_data, grpc_mdelem *md) {
/* eat the things we'd like to set ourselves */
- if (md->key == GRPC_MDSTR_METHOD) return NULL;
- if (md->key == GRPC_MDSTR_SCHEME) return NULL;
- if (md->key == GRPC_MDSTR_TE) return NULL;
- if (md->key == GRPC_MDSTR_CONTENT_TYPE) return NULL;
- if (md->key == GRPC_MDSTR_USER_AGENT) return NULL;
+ if (grpc_slice_cmp(md->key, GRPC_MDSTR_METHOD) == 0) return NULL;
+ if (grpc_slice_cmp(md->key, GRPC_MDSTR_SCHEME) == 0) return NULL;
+ if (grpc_slice_cmp(md->key, GRPC_MDSTR_TE) == 0) return NULL;
+ if (grpc_slice_cmp(md->key, GRPC_MDSTR_CONTENT_TYPE) == 0) return NULL;
+ if (grpc_slice_cmp(md->key, GRPC_MDSTR_USER_AGENT) == 0) return NULL;
return md;
}
@@ -264,10 +267,10 @@ static void hc_mutate_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
if (calld->send_message_blocked == false) {
/* when all the send_message data is available, then create a MDELEM and
append to headers */
- grpc_mdelem *payload_bin = grpc_mdelem_from_metadata_strings(
+ grpc_mdelem *payload_bin = grpc_mdelem_from_slices(
exec_ctx, GRPC_MDSTR_GRPC_PAYLOAD_BIN,
- grpc_mdstr_from_buffer(calld->payload_bytes,
- op->send_message->length));
+ grpc_slice_from_copied_buffer((const char *)calld->payload_bytes,
+ op->send_message->length));
grpc_metadata_batch_add_tail(op->send_initial_metadata,
&calld->payload_bin, payload_bin);
calld->on_complete = op->on_complete;
@@ -369,8 +372,8 @@ static grpc_mdelem *scheme_from_args(const grpc_channel_args *args) {
if (args->args[i].type == GRPC_ARG_STRING &&
strcmp(args->args[i].key, GRPC_ARG_HTTP2_SCHEME) == 0) {
for (j = 0; j < GPR_ARRAY_SIZE(valid_schemes); j++) {
- if (0 == strcmp(grpc_mdstr_as_c_string(valid_schemes[j]->value),
- args->args[i].value.string)) {
+ if (0 == grpc_slice_str_cmp(valid_schemes[j]->value,
+ args->args[i].value.string)) {
return valid_schemes[j];
}
}
@@ -396,13 +399,13 @@ static size_t max_payload_size_from_args(const grpc_channel_args *args) {
return kMaxPayloadSizeForGet;
}
-static grpc_mdstr *user_agent_from_args(const grpc_channel_args *args,
- const char *transport_name) {
+static grpc_slice user_agent_from_args(const grpc_channel_args *args,
+ const char *transport_name) {
gpr_strvec v;
size_t i;
int is_first = 1;
char *tmp;
- grpc_mdstr *result;
+ grpc_slice result;
gpr_strvec_init(&v);
@@ -440,7 +443,7 @@ static grpc_mdstr *user_agent_from_args(const grpc_channel_args *args,
tmp = gpr_strvec_flatten(&v, NULL);
gpr_strvec_destroy(&v);
- result = grpc_mdstr_from_string(tmp);
+ result = grpc_slice_intern(grpc_slice_from_static_string(tmp));
gpr_free(tmp);
return result;
@@ -456,7 +459,7 @@ static void init_channel_elem(grpc_exec_ctx *exec_ctx,
chand->static_scheme = scheme_from_args(args->channel_args);
chand->max_payload_size_for_get =
max_payload_size_from_args(args->channel_args);
- chand->user_agent = grpc_mdelem_from_metadata_strings(
+ chand->user_agent = grpc_mdelem_from_slices(
exec_ctx, GRPC_MDSTR_USER_AGENT,
user_agent_from_args(args->channel_args,
args->optional_transport->vtable->name));
diff --git a/src/core/lib/channel/http_server_filter.c b/src/core/lib/channel/http_server_filter.c
index db39020dca..d8393337cd 100644
--- a/src/core/lib/channel/http_server_filter.c
+++ b/src/core/lib/channel/http_server_filter.c
@@ -39,6 +39,7 @@
#include "src/core/lib/profiling/timers.h"
#include "src/core/lib/slice/percent_encoding.h"
#include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/slice/slice_string_helpers.h"
#include "src/core/lib/transport/static_metadata.h"
#define EXPECTED_CONTENT_TYPE "application/grpc"
@@ -86,16 +87,15 @@ typedef struct channel_data { uint8_t unused; } channel_data;
static grpc_mdelem *server_filter_outgoing_metadata(grpc_exec_ctx *exec_ctx,
void *user_data,
grpc_mdelem *md) {
- if (md->key == GRPC_MDSTR_GRPC_MESSAGE) {
+ if (grpc_slice_cmp(md->key, GRPC_MDSTR_GRPC_MESSAGE) == 0) {
grpc_slice pct_encoded_msg = grpc_percent_encode_slice(
- md->value->slice, grpc_compatible_percent_encoding_unreserved_bytes);
- if (grpc_slice_is_equivalent(pct_encoded_msg, md->value->slice)) {
+ md->value, grpc_compatible_percent_encoding_unreserved_bytes);
+ if (grpc_slice_is_equivalent(pct_encoded_msg, md->value)) {
grpc_slice_unref_internal(exec_ctx, pct_encoded_msg);
return md;
} else {
- return grpc_mdelem_from_metadata_strings(
- exec_ctx, GRPC_MDSTR_GRPC_MESSAGE,
- grpc_mdstr_from_slice(exec_ctx, pct_encoded_msg));
+ return grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_MESSAGE,
+ pct_encoded_msg);
}
} else {
return md;
@@ -123,7 +123,7 @@ static grpc_mdelem *server_filter(grpc_exec_ctx *exec_ctx, void *user_data,
} else if (md == GRPC_MDELEM_METHOD_GET) {
calld->seen_method = 1;
*calld->recv_cacheable_request = true;
- } else if (md->key == GRPC_MDSTR_SCHEME) {
+ } else if (grpc_slice_cmp(md->key, GRPC_MDSTR_SCHEME)) {
calld->seen_scheme = 1;
} else if (md == GRPC_MDELEM_TE_TRAILERS) {
calld->seen_te_trailers = 1;
@@ -131,12 +131,12 @@ static grpc_mdelem *server_filter(grpc_exec_ctx *exec_ctx, void *user_data,
/* TODO(klempner): Track that we've seen all the headers we should
require */
return NULL;
- } else if (md->key == GRPC_MDSTR_CONTENT_TYPE) {
- const char *value_str = grpc_mdstr_as_c_string(md->value);
- if (strncmp(value_str, EXPECTED_CONTENT_TYPE,
- EXPECTED_CONTENT_TYPE_LENGTH) == 0 &&
- (value_str[EXPECTED_CONTENT_TYPE_LENGTH] == '+' ||
- value_str[EXPECTED_CONTENT_TYPE_LENGTH] == ';')) {
+ } else if (grpc_slice_cmp(md->key, GRPC_MDSTR_CONTENT_TYPE)) {
+ if (grpc_slice_buf_start_eq(md->value, EXPECTED_CONTENT_TYPE,
+ EXPECTED_CONTENT_TYPE_LENGTH) &&
+ (GRPC_SLICE_START_PTR(md->value)[EXPECTED_CONTENT_TYPE_LENGTH] == '+' ||
+ GRPC_SLICE_START_PTR(md->value)[EXPECTED_CONTENT_TYPE_LENGTH] ==
+ ';')) {
/* Although the C implementation doesn't (currently) generate them,
any custom +-suffix is explicitly valid. */
/* TODO(klempner): We should consider preallocating common values such
@@ -145,41 +145,47 @@ static grpc_mdelem *server_filter(grpc_exec_ctx *exec_ctx, void *user_data,
} else {
/* TODO(klempner): We're currently allowing this, but we shouldn't
see it without a proxy so log for now. */
- gpr_log(GPR_INFO, "Unexpected content-type '%s'", value_str);
+ char *val = grpc_dump_slice(md->value, GPR_DUMP_ASCII);
+ gpr_log(GPR_INFO, "Unexpected content-type '%s'", val);
+ gpr_free(val);
}
return NULL;
- } else if (md->key == GRPC_MDSTR_TE || md->key == GRPC_MDSTR_METHOD ||
- md->key == GRPC_MDSTR_SCHEME) {
- gpr_log(GPR_ERROR, "Invalid %s: header: '%s'",
- grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value));
+ } else if (grpc_slice_cmp(md->key, GRPC_MDSTR_TE) == 0 ||
+ grpc_slice_cmp(md->key, GRPC_MDSTR_METHOD) == 0 ||
+ grpc_slice_cmp(md->key, GRPC_MDSTR_SCHEME) == 0) {
+ char *key = grpc_dump_slice(md->key, GPR_DUMP_ASCII);
+ char *value = grpc_dump_slice(md->value, GPR_DUMP_ASCII);
+ gpr_log(GPR_ERROR, "Invalid %s: header: '%s'", key, value);
/* swallow it and error everything out. */
/* TODO(klempner): We ought to generate more descriptive error messages
on the wire here. */
+ gpr_free(key);
+ gpr_free(value);
grpc_call_element_send_cancel(exec_ctx, elem);
return NULL;
- } else if (md->key == GRPC_MDSTR_PATH) {
+ } else if (grpc_slice_cmp(md->key, GRPC_MDSTR_PATH) == 0) {
if (calld->seen_path) {
gpr_log(GPR_ERROR, "Received :path twice");
return NULL;
}
calld->seen_path = 1;
return md;
- } else if (md->key == GRPC_MDSTR_AUTHORITY) {
+ } else if (grpc_slice_cmp(md->key, GRPC_MDSTR_AUTHORITY) == 0) {
calld->seen_authority = 1;
return md;
- } else if (md->key == GRPC_MDSTR_HOST) {
+ } else if (grpc_slice_cmp(md->key, GRPC_MDSTR_HOST) == 0) {
/* translate host to :authority since :authority may be
omitted */
- grpc_mdelem *authority = grpc_mdelem_from_metadata_strings(
- exec_ctx, GRPC_MDSTR_AUTHORITY, GRPC_MDSTR_REF(md->value));
+ grpc_mdelem *authority = grpc_mdelem_from_slices(
+ exec_ctx, GRPC_MDSTR_AUTHORITY, grpc_slice_ref(md->value));
calld->seen_authority = 1;
return authority;
- } else if (md->key == GRPC_MDSTR_GRPC_PAYLOAD_BIN) {
+ } else if (grpc_slice_cmp(md->key, GRPC_MDSTR_GRPC_PAYLOAD_BIN) == 0) {
/* Retrieve the payload from the value of the 'grpc-internal-payload-bin'
header field */
calld->seen_payload_bin = 1;
grpc_slice_buffer_add(&calld->read_slice_buffer,
- grpc_slice_ref_internal(md->value->slice));
+ grpc_slice_ref_internal(md->value));
grpc_slice_buffer_stream_init(&calld->read_stream,
&calld->read_slice_buffer, 0);
return NULL;
diff --git a/src/core/lib/channel/message_size_filter.c b/src/core/lib/channel/message_size_filter.c
index 1655d843d5..4f61da825e 100644
--- a/src/core/lib/channel/message_size_filter.c
+++ b/src/core/lib/channel/message_size_filter.c
@@ -68,7 +68,7 @@ static int message_size_limits_cmp(void* value1, void* value2) {
static void free_mem(grpc_exec_ctx* exec_ctx, void* p) { gpr_free(p); }
-static const grpc_mdstr_hash_table_vtable message_size_limits_vtable = {
+static const grpc_slice_hash_table_vtable message_size_limits_vtable = {
free_mem, message_size_limits_copy, message_size_limits_cmp};
static void* method_config_convert_value(
@@ -102,7 +102,7 @@ typedef struct channel_data {
int max_send_size;
int max_recv_size;
// Maps path names to message_size_limits structs.
- grpc_mdstr_hash_table* method_limit_table;
+ grpc_slice_hash_table* method_limit_table;
} channel_data;
// Callback invoked when we receive a message. Here we check the max
@@ -236,7 +236,7 @@ static void init_channel_elem(grpc_exec_ctx* exec_ctx,
static void destroy_channel_elem(grpc_exec_ctx* exec_ctx,
grpc_channel_element* elem) {
channel_data* chand = elem->channel_data;
- grpc_mdstr_hash_table_unref(exec_ctx, chand->method_limit_table);
+ grpc_slice_hash_table_unref(exec_ctx, chand->method_limit_table);
}
const grpc_channel_filter grpc_message_size_filter = {
diff --git a/src/core/lib/compression/algorithm_metadata.h b/src/core/lib/compression/algorithm_metadata.h
index 1f9cc15f23..bc4963059c 100644
--- a/src/core/lib/compression/algorithm_metadata.h
+++ b/src/core/lib/compression/algorithm_metadata.h
@@ -38,7 +38,7 @@
#include "src/core/lib/transport/metadata.h"
/** Return compression algorithm based metadata value */
-grpc_mdstr *grpc_compression_algorithm_mdstr(
+grpc_slice grpc_compression_algorithm_slice(
grpc_compression_algorithm algorithm);
/** Return compression algorithm based metadata element (grpc-encoding: xxx) */
@@ -47,7 +47,7 @@ grpc_mdelem *grpc_compression_encoding_mdelem(
/** Find compression algorithm based on passed in mdstr - returns
* GRPC_COMPRESS_ALGORITHM_COUNT on failure */
-grpc_compression_algorithm grpc_compression_algorithm_from_mdstr(
- grpc_mdstr *str);
+grpc_compression_algorithm grpc_compression_algorithm_from_slice(
+ grpc_slice str);
#endif /* GRPC_CORE_LIB_COMPRESSION_ALGORITHM_METADATA_H */
diff --git a/src/core/lib/compression/compression.c b/src/core/lib/compression/compression.c
index 54efb5e855..d73353f392 100644
--- a/src/core/lib/compression/compression.c
+++ b/src/core/lib/compression/compression.c
@@ -41,30 +41,24 @@
#include "src/core/lib/surface/api_trace.h"
#include "src/core/lib/transport/static_metadata.h"
-int grpc_compression_algorithm_parse(const char *name, size_t name_length,
+int grpc_compression_algorithm_parse(grpc_slice name,
grpc_compression_algorithm *algorithm) {
/* we use strncmp not only because it's safer (even though in this case it
* doesn't matter, given that we are comparing against string literals, but
* because this way we needn't have "name" nil-terminated (useful for slice
* data, for example) */
- GRPC_API_TRACE(
- "grpc_compression_algorithm_parse("
- "name=%*.*s, name_length=%lu, algorithm=%p)",
- 5, ((int)name_length, (int)name_length, name, (unsigned long)name_length,
- algorithm));
- if (name_length == 0) {
- return 0;
- }
- if (strncmp(name, "identity", name_length) == 0) {
+ if (grpc_slice_cmp(name, GRPC_MDSTR_IDENTITY) == 0) {
*algorithm = GRPC_COMPRESS_NONE;
- } else if (strncmp(name, "gzip", name_length) == 0) {
+ return 1;
+ } else if (grpc_slice_cmp(name, GRPC_MDSTR_GZIP) == 0) {
*algorithm = GRPC_COMPRESS_GZIP;
- } else if (strncmp(name, "deflate", name_length) == 0) {
+ return 1;
+ } else if (grpc_slice_cmp(name, GRPC_MDSTR_DEFLATE) == 0) {
*algorithm = GRPC_COMPRESS_DEFLATE;
+ return 1;
} else {
return 0;
}
- return 1;
}
int grpc_compression_algorithm_name(grpc_compression_algorithm algorithm,
@@ -87,15 +81,16 @@ int grpc_compression_algorithm_name(grpc_compression_algorithm algorithm,
return 0;
}
-grpc_compression_algorithm grpc_compression_algorithm_from_mdstr(
- grpc_mdstr *str) {
- if (str == GRPC_MDSTR_IDENTITY) return GRPC_COMPRESS_NONE;
- if (str == GRPC_MDSTR_DEFLATE) return GRPC_COMPRESS_DEFLATE;
- if (str == GRPC_MDSTR_GZIP) return GRPC_COMPRESS_GZIP;
+grpc_compression_algorithm grpc_compression_algorithm_from_slice(
+ grpc_slice str) {
+ if (grpc_slice_cmp(str, GRPC_MDSTR_IDENTITY) == 0) return GRPC_COMPRESS_NONE;
+ if (grpc_slice_cmp(str, GRPC_MDSTR_DEFLATE) == 0)
+ return GRPC_COMPRESS_DEFLATE;
+ if (grpc_slice_cmp(str, GRPC_MDSTR_GZIP) == 0) return GRPC_COMPRESS_GZIP;
return GRPC_COMPRESS_ALGORITHMS_COUNT;
}
-grpc_mdstr *grpc_compression_algorithm_mdstr(
+grpc_slice grpc_compression_algorithm_slice(
grpc_compression_algorithm algorithm) {
switch (algorithm) {
case GRPC_COMPRESS_NONE:
@@ -105,9 +100,9 @@ grpc_mdstr *grpc_compression_algorithm_mdstr(
case GRPC_COMPRESS_GZIP:
return GRPC_MDSTR_GZIP;
case GRPC_COMPRESS_ALGORITHMS_COUNT:
- return NULL;
+ return grpc_empty_slice();
}
- return NULL;
+ return grpc_empty_slice();
}
grpc_mdelem *grpc_compression_encoding_mdelem(
diff --git a/src/core/lib/iomgr/load_file.c b/src/core/lib/iomgr/load_file.c
index 217bc5da59..f40c8b28cc 100644
--- a/src/core/lib/iomgr/load_file.c
+++ b/src/core/lib/iomgr/load_file.c
@@ -47,7 +47,7 @@ grpc_error *grpc_load_file(const char *filename, int add_null_terminator,
grpc_slice *output) {
unsigned char *contents = NULL;
size_t contents_size = 0;
- grpc_slice result = gpr_empty_slice();
+ grpc_slice result = grpc_empty_slice();
FILE *file;
size_t bytes_read = 0;
grpc_error *error = GRPC_ERROR_NONE;
diff --git a/src/core/lib/security/credentials/google_default/google_default_credentials.c b/src/core/lib/security/credentials/google_default/google_default_credentials.c
index 7bed78daf7..65eb02bbb9 100644
--- a/src/core/lib/security/credentials/google_default/google_default_credentials.c
+++ b/src/core/lib/security/credentials/google_default/google_default_credentials.c
@@ -174,7 +174,7 @@ static grpc_error *create_default_creds_from_path(
grpc_auth_json_key key;
grpc_auth_refresh_token token;
grpc_call_credentials *result = NULL;
- grpc_slice creds_data = gpr_empty_slice();
+ grpc_slice creds_data = grpc_empty_slice();
grpc_error *error = GRPC_ERROR_NONE;
if (creds_path == NULL) {
error = GRPC_ERROR_CREATE("creds_path unset");
diff --git a/src/core/lib/security/transport/client_auth_filter.c b/src/core/lib/security/transport/client_auth_filter.c
index ae40bb499c..e9e77182b6 100644
--- a/src/core/lib/security/transport/client_auth_filter.c
+++ b/src/core/lib/security/transport/client_auth_filter.c
@@ -54,8 +54,8 @@
/* We can have a per-call credentials. */
typedef struct {
grpc_call_credentials *creds;
- grpc_mdstr *host;
- grpc_mdstr *method;
+ grpc_slice host;
+ grpc_slice method;
/* pollset{_set} bound to this call; if we need to make external
network requests, they should be done under a pollset added to this
pollset_set so that work can progress when this call wants work to progress
diff --git a/src/core/lib/security/transport/security_connector.c b/src/core/lib/security/transport/security_connector.c
index 7192f228cd..53bccb3efb 100644
--- a/src/core/lib/security/transport/security_connector.c
+++ b/src/core/lib/security/transport/security_connector.c
@@ -649,7 +649,7 @@ static grpc_security_connector_vtable ssl_server_vtable = {
ssl_server_destroy, ssl_server_check_peer};
static grpc_slice compute_default_pem_root_certs_once(void) {
- grpc_slice result = gpr_empty_slice();
+ grpc_slice result = grpc_empty_slice();
/* First try to load the roots from the environment. */
char *default_root_certs_path =
diff --git a/src/core/lib/security/transport/server_auth_filter.c b/src/core/lib/security/transport/server_auth_filter.c
index 7a0069710e..db0d0d6907 100644
--- a/src/core/lib/security/transport/server_auth_filter.c
+++ b/src/core/lib/security/transport/server_auth_filter.c
@@ -68,8 +68,8 @@ static grpc_metadata_array metadata_batch_to_md_array(
for (l = batch->list.head; l != NULL; l = l->next) {
grpc_metadata *usr_md = NULL;
grpc_mdelem *md = l->md;
- grpc_mdstr *key = md->key;
- grpc_mdstr *value = md->value;
+ grpc_slice key = md->key;
+ grpc_slice value = md->value;
if (result.count == result.capacity) {
result.capacity = GPR_MAX(result.capacity + 8, result.capacity * 2);
result.metadata =
diff --git a/src/core/lib/security/util/b64.c b/src/core/lib/security/util/b64.c
index bbd7e335a6..09c8213131 100644
--- a/src/core/lib/security/util/b64.c
+++ b/src/core/lib/security/util/b64.c
@@ -232,5 +232,5 @@ grpc_slice grpc_base64_decode_with_len(grpc_exec_ctx *exec_ctx, const char *b64,
fail:
grpc_slice_unref_internal(exec_ctx, result);
- return gpr_empty_slice();
+ return grpc_empty_slice();
}
diff --git a/src/core/lib/slice/slice.c b/src/core/lib/slice/slice.c
index a85a52b2c6..dc3e6fd93d 100644
--- a/src/core/lib/slice/slice.c
+++ b/src/core/lib/slice/slice.c
@@ -41,7 +41,7 @@
#include "src/core/lib/iomgr/exec_ctx.h"
-grpc_slice gpr_empty_slice(void) {
+grpc_slice grpc_empty_slice(void) {
grpc_slice out;
out.refcount = 0;
out.data.inlined.length = 0;
diff --git a/src/core/lib/transport/mdstr_hash_table.c b/src/core/lib/slice/slice_hash_table.c
index a3f6bde516..7e6f705164 100644
--- a/src/core/lib/transport/mdstr_hash_table.c
+++ b/src/core/lib/slice/slice_hash_table.c
@@ -29,7 +29,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
-#include "src/core/lib/transport/mdstr_hash_table.h"
+#include "src/core/lib/slice/slice_hash_table.h"
#include <stdbool.h>
#include <string.h>
@@ -37,72 +37,88 @@
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
+#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/transport/metadata.h"
-struct grpc_mdstr_hash_table {
+static grpc_slice_refcount terminal_slice_refcount = {NULL, NULL};
+static const grpc_slice terminal_slice = {&terminal_slice_refcount,
+ .data.refcounted = {0, 0}};
+
+struct grpc_slice_hash_table {
gpr_refcount refs;
size_t num_entries;
size_t size;
- grpc_mdstr_hash_table_entry* entries;
+ grpc_slice_hash_table_entry* entries;
};
+static bool is_terminal(grpc_slice slice) {
+ return slice.refcount == &terminal_slice_refcount;
+}
+
// Helper function for insert and get operations that performs quadratic
// probing (https://en.wikipedia.org/wiki/Quadratic_probing).
-static size_t grpc_mdstr_hash_table_find_index(
- const grpc_mdstr_hash_table* table, const grpc_mdstr* key,
- bool find_empty) {
+static size_t grpc_slice_hash_table_find_index(
+ const grpc_slice_hash_table* table, const grpc_slice key, bool find_empty) {
+ size_t hash = grpc_slice_hash(key);
for (size_t i = 0; i < table->size; ++i) {
- const size_t idx = (key->hash + i * i) % table->size;
- if (table->entries[idx].key == NULL) return find_empty ? idx : table->size;
- if (table->entries[idx].key == key) return idx;
+ const size_t idx = (hash + i * i) % table->size;
+ if (is_terminal(table->entries[idx].key)) {
+ return find_empty ? idx : table->size;
+ }
+ if (grpc_slice_cmp(table->entries[idx].key, key) == 0) {
+ return idx;
+ }
}
return table->size; // Not found.
}
-static void grpc_mdstr_hash_table_add(
- grpc_mdstr_hash_table* table, grpc_mdstr* key, void* value,
- const grpc_mdstr_hash_table_vtable* vtable) {
+static void grpc_slice_hash_table_add(
+ grpc_slice_hash_table* table, grpc_slice key, void* value,
+ const grpc_slice_hash_table_vtable* vtable) {
GPR_ASSERT(value != NULL);
const size_t idx =
- grpc_mdstr_hash_table_find_index(table, key, true /* find_empty */);
+ grpc_slice_hash_table_find_index(table, key, true /* find_empty */);
GPR_ASSERT(idx != table->size); // Table should never be full.
- grpc_mdstr_hash_table_entry* entry = &table->entries[idx];
- entry->key = GRPC_MDSTR_REF(key);
+ grpc_slice_hash_table_entry* entry = &table->entries[idx];
+ entry->key = grpc_slice_ref(key);
entry->value = vtable->copy_value(value);
entry->vtable = vtable;
}
-grpc_mdstr_hash_table* grpc_mdstr_hash_table_create(
- size_t num_entries, grpc_mdstr_hash_table_entry* entries) {
- grpc_mdstr_hash_table* table = gpr_malloc(sizeof(*table));
+grpc_slice_hash_table* grpc_slice_hash_table_create(
+ size_t num_entries, grpc_slice_hash_table_entry* entries) {
+ grpc_slice_hash_table* table = gpr_malloc(sizeof(*table));
memset(table, 0, sizeof(*table));
gpr_ref_init(&table->refs, 1);
table->num_entries = num_entries;
// Quadratic probing gets best performance when the table is no more
// than half full.
table->size = num_entries * 2;
- const size_t entry_size = sizeof(grpc_mdstr_hash_table_entry) * table->size;
+ const size_t entry_size = sizeof(grpc_slice_hash_table_entry) * table->size;
table->entries = gpr_malloc(entry_size);
memset(table->entries, 0, entry_size);
for (size_t i = 0; i < num_entries; ++i) {
- grpc_mdstr_hash_table_entry* entry = &entries[i];
- grpc_mdstr_hash_table_add(table, entry->key, entry->value, entry->vtable);
+ table->entries[i].key = terminal_slice;
+ }
+ for (size_t i = 0; i < num_entries; ++i) {
+ grpc_slice_hash_table_entry* entry = &entries[i];
+ grpc_slice_hash_table_add(table, entry->key, entry->value, entry->vtable);
}
return table;
}
-grpc_mdstr_hash_table* grpc_mdstr_hash_table_ref(grpc_mdstr_hash_table* table) {
+grpc_slice_hash_table* grpc_slice_hash_table_ref(grpc_slice_hash_table* table) {
if (table != NULL) gpr_ref(&table->refs);
return table;
}
-int grpc_mdstr_hash_table_unref(grpc_exec_ctx* exec_ctx,
- grpc_mdstr_hash_table* table) {
+int grpc_slice_hash_table_unref(grpc_exec_ctx* exec_ctx,
+ grpc_slice_hash_table* table) {
if (table != NULL && gpr_unref(&table->refs)) {
for (size_t i = 0; i < table->size; ++i) {
- grpc_mdstr_hash_table_entry* entry = &table->entries[i];
- if (entry->key != NULL) {
- GRPC_MDSTR_UNREF(exec_ctx, entry->key);
+ grpc_slice_hash_table_entry* entry = &table->entries[i];
+ if (!is_terminal(entry->key)) {
+ grpc_slice_unref_internal(exec_ctx, entry->key);
entry->vtable->destroy_value(exec_ctx, entry->value);
}
}
@@ -113,29 +129,29 @@ int grpc_mdstr_hash_table_unref(grpc_exec_ctx* exec_ctx,
return 0;
}
-size_t grpc_mdstr_hash_table_num_entries(const grpc_mdstr_hash_table* table) {
+size_t grpc_slice_hash_table_num_entries(const grpc_slice_hash_table* table) {
return table->num_entries;
}
-void* grpc_mdstr_hash_table_get(const grpc_mdstr_hash_table* table,
- const grpc_mdstr* key) {
+void* grpc_slice_hash_table_get(const grpc_slice_hash_table* table,
+ const grpc_slice key) {
const size_t idx =
- grpc_mdstr_hash_table_find_index(table, key, false /* find_empty */);
+ grpc_slice_hash_table_find_index(table, key, false /* find_empty */);
if (idx == table->size) return NULL; // Not found.
return table->entries[idx].value;
}
-int grpc_mdstr_hash_table_cmp(const grpc_mdstr_hash_table* table1,
- const grpc_mdstr_hash_table* table2) {
+int grpc_slice_hash_table_cmp(const grpc_slice_hash_table* table1,
+ const grpc_slice_hash_table* table2) {
// Compare by num_entries.
if (table1->num_entries < table2->num_entries) return -1;
if (table1->num_entries > table2->num_entries) return 1;
for (size_t i = 0; i < table1->num_entries; ++i) {
- grpc_mdstr_hash_table_entry* e1 = &table1->entries[i];
- grpc_mdstr_hash_table_entry* e2 = &table2->entries[i];
+ grpc_slice_hash_table_entry* e1 = &table1->entries[i];
+ grpc_slice_hash_table_entry* e2 = &table2->entries[i];
// Compare keys by hash value.
- if (e1->key->hash < e2->key->hash) return -1;
- if (e1->key->hash > e2->key->hash) return 1;
+ int cmp = grpc_slice_cmp(e1->key, e2->key);
+ if (cmp != 0) return cmp;
// Compare by vtable (pointer equality).
if (e1->vtable < e2->vtable) return -1;
if (e1->vtable > e2->vtable) return 1;
@@ -146,12 +162,12 @@ int grpc_mdstr_hash_table_cmp(const grpc_mdstr_hash_table* table1,
return 0;
}
-void grpc_mdstr_hash_table_iterate(
- const grpc_mdstr_hash_table* table,
- void (*func)(const grpc_mdstr_hash_table_entry* entry, void* user_data),
+void grpc_slice_hash_table_iterate(
+ const grpc_slice_hash_table* table,
+ void (*func)(const grpc_slice_hash_table_entry* entry, void* user_data),
void* user_data) {
for (size_t i = 0; i < table->size; ++i) {
- if (table->entries[i].key != NULL) {
+ if (!is_terminal(table->entries[i].key)) {
func(&table->entries[i], user_data);
}
}
diff --git a/src/core/lib/transport/mdstr_hash_table.h b/src/core/lib/slice/slice_hash_table.h
index 45e5720063..ac04950cc6 100644
--- a/src/core/lib/transport/mdstr_hash_table.h
+++ b/src/core/lib/slice/slice_hash_table.h
@@ -40,54 +40,54 @@
* (https://en.wikipedia.org/wiki/Open_addressing) with quadratic
* probing (https://en.wikipedia.org/wiki/Quadratic_probing).
*
- * The keys are \a grpc_mdstr objects. The values are arbitrary pointers
+ * The keys are \a grpc_slice objects. The values are arbitrary pointers
* with a common vtable.
*
* Hash tables are intentionally immutable, to avoid the need for locking.
*/
-typedef struct grpc_mdstr_hash_table grpc_mdstr_hash_table;
+typedef struct grpc_slice_hash_table grpc_slice_hash_table;
-typedef struct grpc_mdstr_hash_table_vtable {
- void (*destroy_value)(grpc_exec_ctx* exec_ctx, void* value);
- void* (*copy_value)(void* value);
- int (*compare_value)(void* value1, void* value2);
-} grpc_mdstr_hash_table_vtable;
+typedef struct grpc_slice_hash_table_vtable {
+ void (*destroy_value)(grpc_exec_ctx *exec_ctx, void *value);
+ void *(*copy_value)(void *value);
+ int (*compare_value)(void *value1, void *value2);
+} grpc_slice_hash_table_vtable;
-typedef struct grpc_mdstr_hash_table_entry {
- grpc_mdstr* key;
- void* value; /* Must not be NULL. */
- const grpc_mdstr_hash_table_vtable* vtable;
-} grpc_mdstr_hash_table_entry;
+typedef struct grpc_slice_hash_table_entry {
+ grpc_slice key;
+ void *value; /* Must not be NULL. */
+ const grpc_slice_hash_table_vtable *vtable;
+} grpc_slice_hash_table_entry;
/** Creates a new hash table of containing \a entries, which is an array
of length \a num_entries.
Creates its own copy of all keys and values from \a entries. */
-grpc_mdstr_hash_table* grpc_mdstr_hash_table_create(
- size_t num_entries, grpc_mdstr_hash_table_entry* entries);
+grpc_slice_hash_table *grpc_slice_hash_table_create(
+ size_t num_entries, grpc_slice_hash_table_entry *entries);
-grpc_mdstr_hash_table* grpc_mdstr_hash_table_ref(grpc_mdstr_hash_table* table);
+grpc_slice_hash_table *grpc_slice_hash_table_ref(grpc_slice_hash_table *table);
/** Returns 1 when \a table is destroyed. */
-int grpc_mdstr_hash_table_unref(grpc_exec_ctx* exec_ctx,
- grpc_mdstr_hash_table* table);
+int grpc_slice_hash_table_unref(grpc_exec_ctx *exec_ctx,
+ grpc_slice_hash_table *table);
/** Returns the number of entries in \a table. */
-size_t grpc_mdstr_hash_table_num_entries(const grpc_mdstr_hash_table* table);
+size_t grpc_slice_hash_table_num_entries(const grpc_slice_hash_table *table);
/** Returns the value from \a table associated with \a key.
Returns NULL if \a key is not found. */
-void* grpc_mdstr_hash_table_get(const grpc_mdstr_hash_table* table,
- const grpc_mdstr* key);
+void *grpc_slice_hash_table_get(const grpc_slice_hash_table *table,
+ const grpc_slice key);
/** Compares two hash tables.
The sort order is stable but undefined. */
-int grpc_mdstr_hash_table_cmp(const grpc_mdstr_hash_table* table1,
- const grpc_mdstr_hash_table* table2);
+int grpc_slice_hash_table_cmp(const grpc_slice_hash_table *table1,
+ const grpc_slice_hash_table *table2);
/** Iterates over the entries in \a table, calling \a func for each entry. */
-void grpc_mdstr_hash_table_iterate(
- const grpc_mdstr_hash_table* table,
- void (*func)(const grpc_mdstr_hash_table_entry* entry, void* user_data),
- void* user_data);
+void grpc_slice_hash_table_iterate(
+ const grpc_slice_hash_table *table,
+ void (*func)(const grpc_slice_hash_table_entry *entry, void *user_data),
+ void *user_data);
#endif /* GRPC_CORE_LIB_TRANSPORT_MDSTR_HASH_TABLE_H */
diff --git a/src/core/lib/slice/slice_string_helpers.h b/src/core/lib/slice/slice_string_helpers.h
index c6f4e87c7f..4a4deec6e5 100644
--- a/src/core/lib/slice/slice_string_helpers.h
+++ b/src/core/lib/slice/slice_string_helpers.h
@@ -34,6 +34,7 @@
#ifndef GRPC_CORE_LIB_SLICE_SLICE_STRING_HELPERS_H
#define GRPC_CORE_LIB_SLICE_SLICE_STRING_HELPERS_H
+#include <stdbool.h>
#include <stddef.h>
#include <grpc/slice.h>
@@ -53,6 +54,8 @@ char *grpc_dump_slice(grpc_slice slice, uint32_t flags);
* should be a properly initialized instance. */
void grpc_slice_split(grpc_slice str, const char *sep, grpc_slice_buffer *dst);
+bool grpc_parse_slice_to_uint32(grpc_slice str, uint32_t *result);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/core/lib/slice/slice_traits.h b/src/core/lib/slice/slice_traits.h
new file mode 100644
index 0000000000..facbd0dd81
--- /dev/null
+++ b/src/core/lib/slice/slice_traits.h
@@ -0,0 +1,44 @@
+/*
+ *
+ * Copyright 2016, 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.
+ *
+ */
+
+#ifndef SLICE_TRAITS_H
+#define SLICE_TRAITS_H
+
+#include <grpc/slice.h>
+#include <stdbool.h>
+
+bool grpc_slice_is_legal_header(grpc_slice s);
+bool grpc_slice_is_legal_nonbin_header(grpc_slice s);
+bool grpc_slice_is_bin_suffixed(grpc_slice s);
+
+#endif
diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c
index 023b0411c7..38aa99372e 100644
--- a/src/core/lib/surface/call.c
+++ b/src/core/lib/surface/call.c
@@ -92,9 +92,10 @@ typedef enum {
} status_source;
typedef struct {
- uint8_t is_set;
+ bool is_code_set;
+ bool is_details_set;
grpc_status_code code;
- grpc_mdstr *details;
+ grpc_slice details;
} received_status;
typedef struct batch_control {
@@ -196,8 +197,7 @@ struct grpc_call {
union {
struct {
grpc_status_code *status;
- char **status_details;
- size_t *status_details_capacity;
+ grpc_slice *status_details;
} client;
struct {
int *cancelled;
@@ -246,14 +246,15 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
/* Always support no compression */
GPR_BITSET(&call->encodings_accepted_by_peer, GRPC_COMPRESS_NONE);
call->is_client = args->server_transport_data == NULL;
- grpc_mdstr *path = NULL;
+ grpc_slice path = grpc_empty_slice();
if (call->is_client) {
GPR_ASSERT(args->add_initial_metadata_count <
MAX_SEND_EXTRA_METADATA_COUNT);
for (i = 0; i < args->add_initial_metadata_count; i++) {
call->send_extra_metadata[i].md = args->add_initial_metadata[i];
- if (args->add_initial_metadata[i]->key == GRPC_MDSTR_PATH) {
- path = GRPC_MDSTR_REF(args->add_initial_metadata[i]->value);
+ if (grpc_slice_cmp(args->add_initial_metadata[i]->key, GRPC_MDSTR_PATH) ==
+ 0) {
+ path = grpc_slice_ref_internal(args->add_initial_metadata[i]->value);
}
}
call->send_extra_metadata_count = (int)args->add_initial_metadata_count;
@@ -342,7 +343,7 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
exec_ctx, CALL_STACK_FROM_CALL(call), &call->pollent);
}
- if (path != NULL) GRPC_MDSTR_UNREF(exec_ctx, path);
+ grpc_slice_unref_internal(exec_ctx, path);
GPR_TIMER_END("grpc_call_create", 0);
return error;
@@ -383,7 +384,7 @@ static void get_final_status(grpc_call *call,
void *set_value_user_data) {
int i;
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
- if (call->status[i].is_set) {
+ if (call->status[i].is_code_set) {
set_value(call->status[i].code, set_value_user_data);
return;
}
@@ -411,8 +412,8 @@ static void destroy_call(grpc_exec_ctx *exec_ctx, void *call,
}
gpr_mu_destroy(&c->mu);
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
- if (c->status[i].details) {
- GRPC_MDSTR_UNREF(exec_ctx, c->status[i].details);
+ if (c->status[i].is_details_set) {
+ grpc_slice_unref_internal(exec_ctx, c->status[i].details);
}
}
for (ii = 0; ii < c->send_extra_metadata_count; ii++) {
@@ -440,18 +441,19 @@ static void destroy_call(grpc_exec_ctx *exec_ctx, void *call,
static void set_status_code(grpc_call *call, status_source source,
uint32_t status) {
- if (call->status[source].is_set) return;
+ if (call->status[source].is_code_set) return;
- call->status[source].is_set = 1;
+ call->status[source].is_code_set = true;
call->status[source].code = (grpc_status_code)status;
}
static void set_status_details(grpc_exec_ctx *exec_ctx, grpc_call *call,
- status_source source, grpc_mdstr *status) {
- if (call->status[source].details != NULL) {
- GRPC_MDSTR_UNREF(exec_ctx, status);
+ status_source source, grpc_slice status) {
+ if (call->status[source].is_details_set) {
+ grpc_slice_unref_internal(exec_ctx, status);
} else {
call->status[source].details = status;
+ call->status[source].is_details_set = true;
}
}
@@ -461,7 +463,8 @@ static void set_status_from_error(grpc_exec_ctx *exec_ctx, grpc_call *call,
const char *msg;
grpc_error_get_status(error, &status, &msg);
set_status_code(call, source, (uint32_t)status);
- set_status_details(exec_ctx, call, source, grpc_mdstr_from_string(msg));
+ set_status_details(exec_ctx, call, source,
+ grpc_slice_from_copied_string(msg));
}
static void set_incoming_compression_algorithm(
@@ -511,7 +514,7 @@ static void set_encodings_accepted_by_peer(grpc_exec_ctx *exec_ctx,
return;
}
- accept_encoding_slice = mdel->value->slice;
+ accept_encoding_slice = mdel->value;
grpc_slice_buffer_init(&accept_encoding_parts);
grpc_slice_split(accept_encoding_slice, ",", &accept_encoding_parts);
@@ -520,15 +523,13 @@ static void set_encodings_accepted_by_peer(grpc_exec_ctx *exec_ctx,
/* Always support no compression */
GPR_BITSET(&call->encodings_accepted_by_peer, GRPC_COMPRESS_NONE);
for (i = 0; i < accept_encoding_parts.count; i++) {
- const grpc_slice *accept_encoding_entry_slice =
- &accept_encoding_parts.slices[i];
- if (grpc_compression_algorithm_parse(
- (const char *)GRPC_SLICE_START_PTR(*accept_encoding_entry_slice),
- GRPC_SLICE_LENGTH(*accept_encoding_entry_slice), &algorithm)) {
+ grpc_slice accept_encoding_entry_slice = accept_encoding_parts.slices[i];
+ if (grpc_compression_algorithm_parse(accept_encoding_entry_slice,
+ &algorithm)) {
GPR_BITSET(&call->encodings_accepted_by_peer, algorithm);
} else {
char *accept_encoding_entry_str =
- grpc_dump_slice(*accept_encoding_entry_slice, GPR_DUMP_ASCII);
+ grpc_dump_slice(accept_encoding_entry_slice, GPR_DUMP_ASCII);
gpr_log(GPR_ERROR,
"Invalid entry in accept encoding metadata: '%s'. Ignoring.",
accept_encoding_entry_str);
@@ -551,21 +552,12 @@ uint32_t grpc_call_test_only_get_encodings_accepted_by_peer(grpc_call *call) {
return encodings_accepted_by_peer;
}
-static void get_final_details(grpc_call *call, char **out_details,
- size_t *out_details_capacity) {
+static void get_final_details(grpc_call *call, grpc_slice *out_details) {
int i;
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
- if (call->status[i].is_set) {
- if (call->status[i].details) {
- grpc_slice details = call->status[i].details->slice;
- size_t len = GRPC_SLICE_LENGTH(details);
- if (len + 1 > *out_details_capacity) {
- *out_details_capacity =
- GPR_MAX(len + 1, *out_details_capacity * 3 / 2);
- *out_details = gpr_realloc(*out_details, *out_details_capacity);
- }
- memcpy(*out_details, GRPC_SLICE_START_PTR(details), len);
- (*out_details)[len] = 0;
+ if (call->status[i].is_code_set) {
+ if (call->status[i].is_details_set) {
+ *out_details = grpc_slice_ref(call->status[i].details);
} else {
goto no_details;
}
@@ -574,11 +566,7 @@ static void get_final_details(grpc_call *call, char **out_details,
}
no_details:
- if (0 == *out_details_capacity) {
- *out_details_capacity = 8;
- *out_details = gpr_malloc(*out_details_capacity);
- }
- **out_details = 0;
+ *out_details = grpc_empty_slice();
}
static grpc_linked_mdelem *linked_from_md(grpc_metadata *md) {
@@ -607,19 +595,17 @@ static int prepare_application_metadata(
get_md_elem(metadata, additional_metadata, i, count);
grpc_linked_mdelem *l = (grpc_linked_mdelem *)&md->internal_data;
GPR_ASSERT(sizeof(grpc_linked_mdelem) == sizeof(md->internal_data));
- l->md = grpc_mdelem_from_string_and_buffer(
- exec_ctx, md->key, (const uint8_t *)md->value, md->value_length);
- if (!grpc_header_key_is_legal(grpc_mdstr_as_c_string(l->md->key),
- GRPC_MDSTR_LENGTH(l->md->key))) {
- gpr_log(GPR_ERROR, "attempt to send invalid metadata key: %s",
- grpc_mdstr_as_c_string(l->md->key));
+ l->md = grpc_mdelem_from_slices(exec_ctx, md->key, md->value);
+ if (!grpc_header_key_slice_is_legal(l->md->key)) {
+ char *str = grpc_dump_slice(md->key, GPR_DUMP_ASCII);
+ gpr_log(GPR_ERROR, "attempt to send invalid metadata key: %s", str);
+ gpr_free(str);
break;
- } else if (!grpc_is_binary_header(grpc_mdstr_as_c_string(l->md->key),
- GRPC_MDSTR_LENGTH(l->md->key)) &&
- !grpc_header_nonbin_value_is_legal(
- grpc_mdstr_as_c_string(l->md->value),
- GRPC_MDSTR_LENGTH(l->md->value))) {
- gpr_log(GPR_ERROR, "attempt to send invalid metadata value");
+ } else if (!grpc_slice_is_binary_header(l->md->key) &&
+ !grpc_header_nonbin_value_slice_is_legal(l->md->value)) {
+ char *str = grpc_dump_slice(md->value, GPR_DUMP_HEX | GPR_DUMP_ASCII);
+ gpr_log(GPR_ERROR, "attempt to send invalid metadata value: %s", str);
+ gpr_free(str);
break;
}
}
@@ -903,9 +889,7 @@ static uint32_t decode_status(grpc_mdelem *md) {
if (user_data != NULL) {
status = ((uint32_t)(intptr_t)user_data) - STATUS_OFFSET;
} else {
- if (!gpr_parse_bytes_to_uint32(grpc_mdstr_as_c_string(md->value),
- GRPC_SLICE_LENGTH(md->value->slice),
- &status)) {
+ if (!grpc_parse_slice_to_uint32(md->value, &status)) {
status = GRPC_STATUS_UNKNOWN; /* could not parse status code */
}
grpc_mdelem_set_user_data(md, destroy_status,
@@ -916,13 +900,14 @@ static uint32_t decode_status(grpc_mdelem *md) {
static grpc_compression_algorithm decode_compression(grpc_mdelem *md) {
grpc_compression_algorithm algorithm =
- grpc_compression_algorithm_from_mdstr(md->value);
+ grpc_compression_algorithm_from_slice(md->value);
if (algorithm == GRPC_COMPRESS_ALGORITHMS_COUNT) {
- const char *md_c_str = grpc_mdstr_as_c_string(md->value);
+ char *md_c_str = grpc_dump_slice(md->value, GPR_DUMP_ASCII);
gpr_log(GPR_ERROR,
"Invalid incoming compression algorithm: '%s'. Interpreting "
"incoming data as uncompressed.",
md_c_str);
+ gpr_free(md_c_str);
return GRPC_COMPRESS_NONE;
}
return algorithm;
@@ -930,15 +915,15 @@ static grpc_compression_algorithm decode_compression(grpc_mdelem *md) {
static grpc_mdelem *recv_common_filter(grpc_exec_ctx *exec_ctx, grpc_call *call,
grpc_mdelem *elem) {
- if (elem->key == GRPC_MDSTR_GRPC_STATUS) {
+ if (grpc_slice_cmp(elem->key, GRPC_MDSTR_GRPC_STATUS) == 0) {
GPR_TIMER_BEGIN("status", 0);
set_status_code(call, STATUS_FROM_WIRE, decode_status(elem));
GPR_TIMER_END("status", 0);
return NULL;
- } else if (elem->key == GRPC_MDSTR_GRPC_MESSAGE) {
+ } else if (grpc_slice_cmp(elem->key, GRPC_MDSTR_GRPC_MESSAGE) == 0) {
GPR_TIMER_BEGIN("status-details", 0);
set_status_details(exec_ctx, call, STATUS_FROM_WIRE,
- GRPC_MDSTR_REF(elem->value));
+ grpc_slice_ref_internal(elem->value));
GPR_TIMER_END("status-details", 0);
return NULL;
}
@@ -957,9 +942,8 @@ static grpc_mdelem *publish_app_metadata(grpc_call *call, grpc_mdelem *elem,
gpr_realloc(dest->metadata, sizeof(grpc_metadata) * dest->capacity);
}
mdusr = &dest->metadata[dest->count++];
- mdusr->key = grpc_mdstr_as_c_string(elem->key);
- mdusr->value = grpc_mdstr_as_c_string(elem->value);
- mdusr->value_length = GRPC_SLICE_LENGTH(elem->value->slice);
+ mdusr->key = grpc_slice_ref(elem->key);
+ mdusr->value = grpc_slice_ref(elem->value);
GPR_TIMER_END("publish_app_metadata", 0);
return elem;
}
@@ -970,12 +954,12 @@ static grpc_mdelem *recv_initial_filter(grpc_exec_ctx *exec_ctx, void *args,
elem = recv_common_filter(exec_ctx, call, elem);
if (elem == NULL) {
return NULL;
- } else if (elem->key == GRPC_MDSTR_GRPC_ENCODING) {
+ } else if (grpc_slice_cmp(elem->key, GRPC_MDSTR_GRPC_ENCODING) == 0) {
GPR_TIMER_BEGIN("incoming_compression_algorithm", 0);
set_incoming_compression_algorithm(call, decode_compression(elem));
GPR_TIMER_END("incoming_compression_algorithm", 0);
return NULL;
- } else if (elem->key == GRPC_MDSTR_GRPC_ACCEPT_ENCODING) {
+ } else if (grpc_slice_cmp(elem->key, GRPC_MDSTR_GRPC_ACCEPT_ENCODING) == 0) {
GPR_TIMER_BEGIN("encodings_accepted_by_peer", 0);
set_encodings_accepted_by_peer(exec_ctx, call, elem);
GPR_TIMER_END("encodings_accepted_by_peer", 0);
@@ -1324,8 +1308,7 @@ static void finish_batch(grpc_exec_ctx *exec_ctx, void *bctlp,
if (call->is_client) {
get_final_status(call, set_status_value_directly,
call->final_op.client.status);
- get_final_details(call, call->final_op.client.status_details,
- call->final_op.client.status_details_capacity);
+ get_final_details(call, call->final_op.client.status_details);
} else {
get_final_status(call, set_cancelled_value,
call->final_op.server.cancelled);
@@ -1423,13 +1406,10 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
const grpc_compression_algorithm calgo =
compression_algorithm_for_level_locked(
call, effective_compression_level);
- char *calgo_name = NULL;
- grpc_compression_algorithm_name(calgo, &calgo_name);
// the following will be picked up by the compress filter and used as
// the call's compression algorithm.
- compression_md.key = GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY;
- compression_md.value = calgo_name;
- compression_md.value_length = strlen(calgo_name);
+ compression_md.key = GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST;
+ compression_md.value = grpc_compression_algorithm_slice(calgo);
additional_metadata_count++;
}
@@ -1523,14 +1503,14 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
call->send_extra_metadata[0].md = grpc_channel_get_reffed_status_elem(
exec_ctx, call->channel, op->data.send_status_from_server.status);
if (op->data.send_status_from_server.status_details != NULL) {
- call->send_extra_metadata[1].md = grpc_mdelem_from_metadata_strings(
+ call->send_extra_metadata[1].md = grpc_mdelem_from_slices(
exec_ctx, GRPC_MDSTR_GRPC_MESSAGE,
- grpc_mdstr_from_string(
- op->data.send_status_from_server.status_details));
+ grpc_slice_ref_internal(
+ *op->data.send_status_from_server.status_details));
call->send_extra_metadata_count++;
set_status_details(
exec_ctx, call, STATUS_FROM_API_OVERRIDE,
- GRPC_MDSTR_REF(call->send_extra_metadata[1].md->value));
+ grpc_slice_ref_internal(call->send_extra_metadata[1].md->value));
}
if (op->data.send_status_from_server.status != GRPC_STATUS_OK) {
set_status_code(call, STATUS_FROM_API_OVERRIDE,
@@ -1607,8 +1587,6 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
call->final_op.client.status = op->data.recv_status_on_client.status;
call->final_op.client.status_details =
op->data.recv_status_on_client.status_details;
- call->final_op.client.status_details_capacity =
- op->data.recv_status_on_client.status_details_capacity;
bctl->recv_final_op = 1;
stream_op->recv_trailing_metadata =
&call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
diff --git a/src/core/lib/surface/call_details.c b/src/core/lib/surface/call_details.c
index fe73da3f55..5efa3b0141 100644
--- a/src/core/lib/surface/call_details.c
+++ b/src/core/lib/surface/call_details.c
@@ -41,10 +41,12 @@
void grpc_call_details_init(grpc_call_details* cd) {
GRPC_API_TRACE("grpc_call_details_init(cd=%p)", 1, (cd));
memset(cd, 0, sizeof(*cd));
+ cd->method = grpc_empty_slice();
+ cd->host = grpc_empty_slice();
}
void grpc_call_details_destroy(grpc_call_details* cd) {
GRPC_API_TRACE("grpc_call_details_destroy(cd=%p)", 1, (cd));
- gpr_free(cd->method);
- gpr_free(cd->host);
+ grpc_slice_unref(cd->method);
+ grpc_slice_unref(cd->host);
}
diff --git a/src/core/lib/surface/call_log_batch.c b/src/core/lib/surface/call_log_batch.c
index 31c074f15d..8f6438bc3b 100644
--- a/src/core/lib/surface/call_log_batch.c
+++ b/src/core/lib/surface/call_log_batch.c
@@ -35,17 +35,18 @@
#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
+#include "src/core/lib/slice/slice_string_helpers.h"
#include "src/core/lib/support/string.h"
static void add_metadata(gpr_strvec *b, const grpc_metadata *md, size_t count) {
size_t i;
for (i = 0; i < count; i++) {
gpr_strvec_add(b, gpr_strdup("\nkey="));
- gpr_strvec_add(b, gpr_strdup(md[i].key));
+ gpr_strvec_add(b, grpc_dump_slice(md[i].key, GPR_DUMP_ASCII));
gpr_strvec_add(b, gpr_strdup(" value="));
- gpr_strvec_add(b, gpr_dump(md[i].value, md[i].value_length,
- GPR_DUMP_HEX | GPR_DUMP_ASCII));
+ gpr_strvec_add(b,
+ grpc_dump_slice(md[i].value, GPR_DUMP_HEX | GPR_DUMP_ASCII));
}
}
@@ -70,10 +71,16 @@ char *grpc_op_string(const grpc_op *op) {
gpr_strvec_add(&b, gpr_strdup("SEND_CLOSE_FROM_CLIENT"));
break;
case GRPC_OP_SEND_STATUS_FROM_SERVER:
- gpr_asprintf(&tmp, "SEND_STATUS_FROM_SERVER status=%d details=%s",
- op->data.send_status_from_server.status,
- op->data.send_status_from_server.status_details);
+ gpr_asprintf(&tmp, "SEND_STATUS_FROM_SERVER status=%d details=",
+ op->data.send_status_from_server.status);
gpr_strvec_add(&b, tmp);
+ if (op->data.send_status_from_server.status_details != NULL) {
+ gpr_strvec_add(&b, grpc_dump_slice(
+ *op->data.send_status_from_server.status_details,
+ GPR_DUMP_ASCII));
+ } else {
+ gpr_strvec_add(&b, gpr_strdup("(null)"));
+ }
add_metadata(&b, op->data.send_status_from_server.trailing_metadata,
op->data.send_status_from_server.trailing_metadata_count);
break;
diff --git a/src/core/lib/surface/channel.c b/src/core/lib/surface/channel.c
index 7e87f05531..986142a692 100644
--- a/src/core/lib/surface/channel.c
+++ b/src/core/lib/surface/channel.c
@@ -123,8 +123,9 @@ grpc_channel *grpc_channel_create(grpc_exec_ctx *exec_ctx, const char *target,
/* setting this takes precedence over anything else */
GRPC_MDELEM_UNREF(exec_ctx, channel->default_authority);
}
- channel->default_authority = grpc_mdelem_from_strings(
- exec_ctx, ":authority", args->args[i].value.string);
+ channel->default_authority = grpc_mdelem_from_slices(
+ exec_ctx, GRPC_MDSTR_AUTHORITY,
+ grpc_slice_from_copied_string(args->args[i].value.string));
}
} else if (0 ==
strcmp(args->args[i].key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG)) {
@@ -138,8 +139,9 @@ grpc_channel *grpc_channel_create(grpc_exec_ctx *exec_ctx, const char *target,
"%s ignored: default host already set some other way",
GRPC_SSL_TARGET_NAME_OVERRIDE_ARG);
} else {
- channel->default_authority = grpc_mdelem_from_strings(
- exec_ctx, ":authority", args->args[i].value.string);
+ channel->default_authority = grpc_mdelem_from_slices(
+ exec_ctx, GRPC_MDSTR_AUTHORITY,
+ grpc_slice_from_copied_string(args->args[i].value.string));
}
}
} else if (0 == strcmp(args->args[i].key,
@@ -224,27 +226,17 @@ grpc_call *grpc_channel_create_call(grpc_channel *channel,
grpc_call *parent_call,
uint32_t propagation_mask,
grpc_completion_queue *cq,
- const char *method, const char *host,
+ grpc_slice method, const grpc_slice *host,
gpr_timespec deadline, void *reserved) {
- GRPC_API_TRACE(
- "grpc_channel_create_call("
- "channel=%p, parent_call=%p, propagation_mask=%x, cq=%p, method=%s, "
- "host=%s, "
- "deadline=gpr_timespec { tv_sec: %" PRId64
- ", tv_nsec: %d, clock_type: %d }, "
- "reserved=%p)",
- 10,
- (channel, parent_call, (unsigned)propagation_mask, cq, method, host,
- deadline.tv_sec, deadline.tv_nsec, (int)deadline.clock_type, reserved));
GPR_ASSERT(!reserved);
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_call *call = grpc_channel_create_call_internal(
&exec_ctx, channel, parent_call, propagation_mask, cq, NULL,
- grpc_mdelem_from_metadata_strings(&exec_ctx, GRPC_MDSTR_PATH,
- grpc_mdstr_from_string(method)),
- host ? grpc_mdelem_from_metadata_strings(&exec_ctx, GRPC_MDSTR_AUTHORITY,
- grpc_mdstr_from_string(host))
- : NULL,
+ grpc_mdelem_from_slices(&exec_ctx, GRPC_MDSTR_PATH,
+ grpc_slice_ref(method)),
+ host != NULL ? grpc_mdelem_from_slices(&exec_ctx, GRPC_MDSTR_AUTHORITY,
+ grpc_slice_ref(*host))
+ : NULL,
deadline);
grpc_exec_ctx_finish(&exec_ctx);
return call;
@@ -252,17 +244,16 @@ grpc_call *grpc_channel_create_call(grpc_channel *channel,
grpc_call *grpc_channel_create_pollset_set_call(
grpc_exec_ctx *exec_ctx, grpc_channel *channel, grpc_call *parent_call,
- uint32_t propagation_mask, grpc_pollset_set *pollset_set,
- const char *method, const char *host, gpr_timespec deadline,
- void *reserved) {
+ uint32_t propagation_mask, grpc_pollset_set *pollset_set, grpc_slice method,
+ const grpc_slice *host, gpr_timespec deadline, void *reserved) {
GPR_ASSERT(!reserved);
return grpc_channel_create_call_internal(
exec_ctx, channel, parent_call, propagation_mask, NULL, pollset_set,
- grpc_mdelem_from_metadata_strings(exec_ctx, GRPC_MDSTR_PATH,
- grpc_mdstr_from_string(method)),
- host ? grpc_mdelem_from_metadata_strings(exec_ctx, GRPC_MDSTR_AUTHORITY,
- grpc_mdstr_from_string(host))
- : NULL,
+ grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_PATH,
+ grpc_slice_ref(method)),
+ host != NULL ? grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_AUTHORITY,
+ grpc_slice_ref(*host))
+ : NULL,
deadline);
}
@@ -274,11 +265,14 @@ void *grpc_channel_register_call(grpc_channel *channel, const char *method,
4, (channel, method, host, reserved));
GPR_ASSERT(!reserved);
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
- rc->path = grpc_mdelem_from_metadata_strings(&exec_ctx, GRPC_MDSTR_PATH,
- grpc_mdstr_from_string(method));
+
+ rc->path = grpc_mdelem_from_slices(
+ &exec_ctx, GRPC_MDSTR_PATH,
+ grpc_slice_intern(grpc_slice_from_copied_string(method)));
rc->authority =
- host ? grpc_mdelem_from_metadata_strings(&exec_ctx, GRPC_MDSTR_AUTHORITY,
- grpc_mdstr_from_string(host))
+ host ? grpc_mdelem_from_slices(
+ &exec_ctx, GRPC_MDSTR_AUTHORITY,
+ grpc_slice_intern(grpc_slice_from_copied_string(host)))
: NULL;
gpr_mu_lock(&channel->registered_call_mu);
rc->next = channel->registered_calls;
@@ -385,6 +379,6 @@ grpc_mdelem *grpc_channel_get_reffed_status_elem(grpc_exec_ctx *exec_ctx,
return GRPC_MDELEM_GRPC_STATUS_2;
}
gpr_ltoa(i, tmp);
- return grpc_mdelem_from_metadata_strings(exec_ctx, GRPC_MDSTR_GRPC_STATUS,
- grpc_mdstr_from_string(tmp));
+ return grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_STATUS,
+ grpc_slice_from_copied_string(tmp));
}
diff --git a/src/core/lib/surface/channel.h b/src/core/lib/surface/channel.h
index 2ebadb7a15..cbe48cd6a0 100644
--- a/src/core/lib/surface/channel.h
+++ b/src/core/lib/surface/channel.h
@@ -52,9 +52,8 @@ grpc_channel *grpc_channel_create(grpc_exec_ctx *exec_ctx, const char *target,
value of \a propagation_mask (see propagation_bits.h for possible values) */
grpc_call *grpc_channel_create_pollset_set_call(
grpc_exec_ctx *exec_ctx, grpc_channel *channel, grpc_call *parent_call,
- uint32_t propagation_mask, grpc_pollset_set *pollset_set,
- const char *method, const char *host, gpr_timespec deadline,
- void *reserved);
+ uint32_t propagation_mask, grpc_pollset_set *pollset_set, grpc_slice method,
+ const grpc_slice *host, gpr_timespec deadline, void *reserved);
/** Get a (borrowed) pointer to this channels underlying channel stack */
grpc_channel_stack *grpc_channel_get_channel_stack(grpc_channel *channel);
diff --git a/src/core/lib/surface/lame_client.c b/src/core/lib/surface/lame_client.c
index d606f70c2f..a43969be57 100644
--- a/src/core/lib/surface/lame_client.c
+++ b/src/core/lib/surface/lame_client.c
@@ -44,6 +44,7 @@
#include "src/core/lib/surface/api_trace.h"
#include "src/core/lib/surface/call.h"
#include "src/core/lib/surface/channel.h"
+#include "src/core/lib/transport/static_metadata.h"
typedef struct {
grpc_linked_mdelem status;
@@ -61,9 +62,11 @@ static void fill_metadata(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
channel_data *chand = elem->channel_data;
char tmp[GPR_LTOA_MIN_BUFSIZE];
gpr_ltoa(chand->error_code, tmp);
- calld->status.md = grpc_mdelem_from_strings(exec_ctx, "grpc-status", tmp);
- calld->details.md =
- grpc_mdelem_from_strings(exec_ctx, "grpc-message", chand->error_message);
+ calld->status.md = grpc_mdelem_from_slices(
+ exec_ctx, GRPC_MDSTR_GRPC_STATUS, grpc_slice_from_copied_string(tmp));
+ calld->details.md = grpc_mdelem_from_slices(
+ exec_ctx, GRPC_MDSTR_GRPC_MESSAGE,
+ grpc_slice_from_copied_string(chand->error_message));
calld->status.prev = calld->details.next = NULL;
calld->status.next = &calld->details;
calld->details.prev = &calld->status;
diff --git a/src/core/lib/surface/server.c b/src/core/lib/surface/server.c
index 03e0913a91..3973630c85 100644
--- a/src/core/lib/surface/server.c
+++ b/src/core/lib/surface/server.c
@@ -98,8 +98,9 @@ typedef struct requested_call {
typedef struct channel_registered_method {
registered_method *server_registered_method;
uint32_t flags;
- grpc_mdstr *method;
- grpc_mdstr *host;
+ bool has_host;
+ grpc_slice method;
+ grpc_slice host;
} channel_registered_method;
struct channel_data {
@@ -144,8 +145,10 @@ struct call_data {
/** the current state of a call - see call_state */
call_state state;
- grpc_mdstr *path;
- grpc_mdstr *host;
+ bool path_set;
+ bool host_set;
+ grpc_slice path;
+ grpc_slice host;
gpr_timespec deadline;
grpc_completion_queue *cq_new;
@@ -460,17 +463,6 @@ static void destroy_channel(grpc_exec_ctx *exec_ctx, channel_data *chand,
op);
}
-static void cpstr(char **dest, size_t *capacity, grpc_mdstr *value) {
- grpc_slice slice = value->slice;
- size_t len = GRPC_SLICE_LENGTH(slice);
-
- if (len + 1 > *capacity) {
- *capacity = GPR_MAX(len + 1, *capacity * 2);
- *dest = gpr_realloc(*dest, *capacity);
- }
- memcpy(*dest, grpc_mdstr_as_c_string(value), len + 1);
-}
-
static void done_request_event(grpc_exec_ctx *exec_ctx, void *req,
grpc_cq_completion *c) {
requested_call *rc = req;
@@ -499,12 +491,10 @@ static void publish_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
GPR_SWAP(grpc_metadata_array, *rc->initial_metadata, calld->initial_metadata);
switch (rc->type) {
case BATCH_CALL:
- GPR_ASSERT(calld->host != NULL);
- GPR_ASSERT(calld->path != NULL);
- cpstr(&rc->data.batch.details->host,
- &rc->data.batch.details->host_capacity, calld->host);
- cpstr(&rc->data.batch.details->method,
- &rc->data.batch.details->method_capacity, calld->path);
+ GPR_ASSERT(calld->host_set);
+ GPR_ASSERT(calld->path_set);
+ rc->data.batch.details->host = grpc_slice_ref_internal(calld->host);
+ rc->data.batch.details->method = grpc_slice_ref_internal(calld->path);
rc->data.batch.details->deadline = calld->deadline;
rc->data.batch.details->flags =
(calld->recv_idempotent_request
@@ -624,35 +614,39 @@ static void start_new_rpc(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
uint32_t hash;
channel_registered_method *rm;
- if (chand->registered_methods && calld->path && calld->host) {
+ if (chand->registered_methods && calld->path_set && calld->host_set) {
/* TODO(ctiller): unify these two searches */
/* check for an exact match with host */
- hash = GRPC_MDSTR_KV_HASH(calld->host->hash, calld->path->hash);
+ hash = GRPC_MDSTR_KV_HASH(grpc_slice_hash(calld->host),
+ grpc_slice_hash(calld->path));
for (i = 0; i <= chand->registered_method_max_probes; i++) {
rm = &chand->registered_methods[(hash + i) %
chand->registered_method_slots];
if (!rm) break;
- if (rm->host != calld->host) continue;
- if (rm->method != calld->path) continue;
+ if (!rm->has_host) continue;
+ if (grpc_slice_cmp(rm->host, calld->host) != 0) continue;
+ if (grpc_slice_cmp(rm->method, calld->path) != 0) continue;
if ((rm->flags & GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST) &&
- !calld->recv_idempotent_request)
+ !calld->recv_idempotent_request) {
continue;
+ }
finish_start_new_rpc(exec_ctx, server, elem,
&rm->server_registered_method->request_matcher,
rm->server_registered_method->payload_handling);
return;
}
/* check for a wildcard method definition (no host set) */
- hash = GRPC_MDSTR_KV_HASH(0, calld->path->hash);
+ hash = GRPC_MDSTR_KV_HASH(0, grpc_slice_hash(calld->path));
for (i = 0; i <= chand->registered_method_max_probes; i++) {
rm = &chand->registered_methods[(hash + i) %
chand->registered_method_slots];
if (!rm) break;
- if (rm->host != NULL) continue;
- if (rm->method != calld->path) continue;
+ if (rm->has_host) continue;
+ if (grpc_slice_cmp(rm->method, calld->path) != 0) continue;
if ((rm->flags & GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST) &&
- !calld->recv_idempotent_request)
+ !calld->recv_idempotent_request) {
continue;
+ }
finish_start_new_rpc(exec_ctx, server, elem,
&rm->server_registered_method->request_matcher,
rm->server_registered_method->payload_handling);
@@ -745,14 +739,14 @@ static grpc_mdelem *server_filter(grpc_exec_ctx *exec_ctx, void *user_data,
grpc_mdelem *md) {
grpc_call_element *elem = user_data;
call_data *calld = elem->call_data;
- if (md->key == GRPC_MDSTR_PATH) {
- if (calld->path == NULL) {
- calld->path = GRPC_MDSTR_REF(md->value);
+ if (grpc_slice_cmp(md->key, GRPC_MDSTR_PATH) == 0) {
+ if (!calld->path_set) {
+ calld->path = grpc_slice_ref(md->value);
}
return NULL;
- } else if (md->key == GRPC_MDSTR_AUTHORITY) {
- if (calld->host == NULL) {
- calld->host = GRPC_MDSTR_REF(md->value);
+ } else if (grpc_slice_cmp(md->key, GRPC_MDSTR_AUTHORITY) == 0) {
+ if (!calld->host_set) {
+ calld->host = grpc_slice_ref(md->value);
}
return NULL;
}
@@ -772,7 +766,7 @@ static void server_on_recv_initial_metadata(grpc_exec_ctx *exec_ctx, void *ptr,
if (0 != gpr_time_cmp(op_deadline, gpr_inf_future(op_deadline.clock_type))) {
calld->deadline = op_deadline;
}
- if (calld->host && calld->path) {
+ if (calld->host_set && calld->path_set) {
/* do nothing */
} else {
GRPC_ERROR_UNREF(error);
@@ -904,11 +898,11 @@ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
GPR_ASSERT(calld->state != PENDING);
- if (calld->host) {
- GRPC_MDSTR_UNREF(exec_ctx, calld->host);
+ if (calld->host_set) {
+ grpc_slice_unref_internal(exec_ctx, calld->host);
}
- if (calld->path) {
- GRPC_MDSTR_UNREF(exec_ctx, calld->path);
+ if (calld->path_set) {
+ grpc_slice_unref_internal(exec_ctx, calld->path);
}
grpc_metadata_array_destroy(&calld->initial_metadata);
@@ -938,11 +932,9 @@ static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
channel_data *chand = elem->channel_data;
if (chand->registered_methods) {
for (i = 0; i < chand->registered_method_slots; i++) {
- if (chand->registered_methods[i].method) {
- GRPC_MDSTR_UNREF(exec_ctx, chand->registered_methods[i].method);
- }
- if (chand->registered_methods[i].host) {
- GRPC_MDSTR_UNREF(exec_ctx, chand->registered_methods[i].host);
+ grpc_slice_unref_internal(exec_ctx, chand->registered_methods[i].method);
+ if (chand->registered_methods[i].has_host) {
+ grpc_slice_unref_internal(exec_ctx, chand->registered_methods[i].host);
}
}
gpr_free(chand->registered_methods);
@@ -1140,8 +1132,6 @@ void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *s,
channel_registered_method *crm;
grpc_channel *channel;
channel_data *chand;
- grpc_mdstr *host;
- grpc_mdstr *method;
uint32_t hash;
size_t slots;
uint32_t probes;
@@ -1180,9 +1170,18 @@ void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *s,
chand->registered_methods = gpr_malloc(alloc);
memset(chand->registered_methods, 0, alloc);
for (rm = s->registered_methods; rm; rm = rm->next) {
- host = rm->host ? grpc_mdstr_from_string(rm->host) : NULL;
- method = grpc_mdstr_from_string(rm->method);
- hash = GRPC_MDSTR_KV_HASH(host ? host->hash : 0, method->hash);
+ grpc_slice host;
+ bool has_host;
+ grpc_slice method;
+ if (rm->host != NULL) {
+ host = grpc_slice_intern(grpc_slice_from_copied_string(rm->host));
+ has_host = true;
+ } else {
+ has_host = false;
+ }
+ method = grpc_slice_intern(grpc_slice_from_copied_string(rm->method));
+ hash = GRPC_MDSTR_KV_HASH(has_host ? grpc_slice_hash(host) : 0,
+ grpc_slice_hash(method));
for (probes = 0; chand->registered_methods[(hash + probes) % slots]
.server_registered_method != NULL;
probes++)
diff --git a/src/core/lib/transport/metadata.c b/src/core/lib/transport/metadata.c
index 54c39df6a7..cedf9170b7 100644
--- a/src/core/lib/transport/metadata.c
+++ b/src/core/lib/transport/metadata.c
@@ -52,8 +52,6 @@
#include "src/core/lib/support/string.h"
#include "src/core/lib/transport/static_metadata.h"
-grpc_slice (*grpc_chttp2_base64_encode_and_huffman_compress)(grpc_slice input);
-
/* There are two kinds of mdelem and mdstr instances.
* Static instances are declared in static_metadata.{h,c} and
* are initialized by grpc_mdctx_global_init().
@@ -63,9 +61,6 @@ grpc_slice (*grpc_chttp2_base64_encode_and_huffman_compress)(grpc_slice input);
* used to determine which kind of element a pointer refers to.
*/
-#define INITIAL_STRTAB_CAPACITY 4
-#define INITIAL_MDTAB_CAPACITY 4
-
#ifdef GRPC_METADATA_REFCOUNT_DEBUG
#define DEBUG_ARGS , const char *file, int line
#define FWD_DEBUG_ARGS , file, line
@@ -76,37 +71,20 @@ grpc_slice (*grpc_chttp2_base64_encode_and_huffman_compress)(grpc_slice input);
#define REF_MD_LOCKED(shard, s) ref_md_locked((shard), (s))
#endif
-#define TABLE_IDX(hash, log2_shards, capacity) \
- (((hash) >> (log2_shards)) % (capacity))
-#define SHARD_IDX(hash, log2_shards) ((hash) & ((1 << (log2_shards)) - 1))
-
-typedef void (*destroy_user_data_func)(void *user_data);
-
-#define SIZE_IN_DECODER_TABLE_NOT_SET -1
-/* Shadow structure for grpc_mdstr for non-static values */
-typedef struct internal_string {
- /* must be byte compatible with grpc_mdstr */
- grpc_slice slice;
- uint32_t hash;
+#define INITIAL_SHARD_CAPACITY 8
+#define LOG2_SHARD_COUNT 4
+#define SHARD_COUNT ((size_t)(1 << LOG2_SHARD_COUNT))
- /* private only data */
- gpr_atm refcnt;
+#define TABLE_IDX(hash, capacity) (((hash) >> (LOG2_SHARD_COUNT)) % (capacity))
+#define SHARD_IDX(hash) ((hash) & ((1 << (LOG2_SHARD_COUNT)) - 1))
- uint8_t has_base64_and_huffman_encoded;
- grpc_slice_refcount refcount;
-
- grpc_slice base64_and_huffman;
-
- gpr_atm size_in_decoder_table;
-
- struct internal_string *bucket_next;
-} internal_string;
+typedef void (*destroy_user_data_func)(void *user_data);
/* Shadow structure for grpc_mdelem for non-static elements */
typedef struct internal_metadata {
/* must be byte compatible with grpc_mdelem */
- internal_string *key;
- internal_string *value;
+ grpc_slice key;
+ grpc_slice value;
/* private only data */
gpr_atm refcnt;
@@ -118,13 +96,6 @@ typedef struct internal_metadata {
struct internal_metadata *bucket_next;
} internal_metadata;
-typedef struct strtab_shard {
- gpr_mu mu;
- internal_string **strs;
- size_t count;
- size_t capacity;
-} strtab_shard;
-
typedef struct mdtab_shard {
gpr_mu mu;
internal_metadata **elems;
@@ -136,23 +107,16 @@ typedef struct mdtab_shard {
gpr_atm free_estimate;
} mdtab_shard;
-#define LOG2_STRTAB_SHARD_COUNT 5
-#define LOG2_MDTAB_SHARD_COUNT 4
-#define STRTAB_SHARD_COUNT ((size_t)(1 << LOG2_STRTAB_SHARD_COUNT))
-#define MDTAB_SHARD_COUNT ((size_t)(1 << LOG2_MDTAB_SHARD_COUNT))
-
/* hash seed: decided at initialization time */
static uint32_t g_hash_seed;
static int g_forced_hash_seed = 0;
/* linearly probed hash tables for static element lookup */
-static grpc_mdstr *g_static_strtab[GRPC_STATIC_MDSTR_COUNT * 2];
static grpc_mdelem *g_static_mdtab[GRPC_STATIC_MDELEM_COUNT * 2];
static size_t g_static_strtab_maxprobe;
static size_t g_static_mdtab_maxprobe;
-static strtab_shard g_strtab_shard[STRTAB_SHARD_COUNT];
-static mdtab_shard g_mdtab_shard[MDTAB_SHARD_COUNT];
+static mdtab_shard g_shards[SHARD_COUNT];
static void gc_mdtab(grpc_exec_ctx *exec_ctx, mdtab_shard *shard);
@@ -162,17 +126,18 @@ void grpc_test_only_set_metadata_hash_seed(uint32_t seed) {
}
void grpc_mdctx_global_init(void) {
- size_t i, j;
+ size_t i;
if (!g_forced_hash_seed) {
g_hash_seed = (uint32_t)gpr_now(GPR_CLOCK_REALTIME).tv_nsec;
}
g_static_strtab_maxprobe = 0;
g_static_mdtab_maxprobe = 0;
+#if 0
/* build static tables */
memset(g_static_mdtab, 0, sizeof(g_static_mdtab));
memset(g_static_strtab, 0, sizeof(g_static_strtab));
for (i = 0; i < GRPC_STATIC_MDSTR_COUNT; i++) {
- grpc_mdstr *elem = &grpc_static_mdstr_table[i];
+ grpc_slice elem = &grpc_static_mdstr_table[i];
const char *str = grpc_static_metadata_strings[i];
uint32_t hash = gpr_murmur_hash3(str, strlen(str), g_hash_seed);
*(grpc_slice *)&elem->slice = grpc_slice_from_static_string(str);
@@ -190,13 +155,13 @@ void grpc_mdctx_global_init(void) {
}
for (i = 0; i < GRPC_STATIC_MDELEM_COUNT; i++) {
grpc_mdelem *elem = &grpc_static_mdelem_table[i];
- grpc_mdstr *key =
+ grpc_slice key =
&grpc_static_mdstr_table[grpc_static_metadata_elem_indices[2 * i + 0]];
- grpc_mdstr *value =
+ grpc_slice value =
&grpc_static_mdstr_table[grpc_static_metadata_elem_indices[2 * i + 1]];
uint32_t hash = GRPC_MDSTR_KV_HASH(key->hash, value->hash);
- *(grpc_mdstr **)&elem->key = key;
- *(grpc_mdstr **)&elem->value = value;
+ *(grpc_slice *)&elem->key = key;
+ *(grpc_slice *)&elem->value = value;
for (j = 0;; j++) {
size_t idx = (hash + j) % GPR_ARRAY_SIZE(g_static_mdtab);
if (g_static_mdtab[idx] == NULL) {
@@ -208,21 +173,14 @@ void grpc_mdctx_global_init(void) {
g_static_mdtab_maxprobe = j;
}
}
+#endif
/* initialize shards */
- for (i = 0; i < STRTAB_SHARD_COUNT; i++) {
- strtab_shard *shard = &g_strtab_shard[i];
- gpr_mu_init(&shard->mu);
- shard->count = 0;
- shard->capacity = INITIAL_STRTAB_CAPACITY;
- shard->strs = gpr_malloc(sizeof(*shard->strs) * shard->capacity);
- memset(shard->strs, 0, sizeof(*shard->strs) * shard->capacity);
- }
- for (i = 0; i < MDTAB_SHARD_COUNT; i++) {
- mdtab_shard *shard = &g_mdtab_shard[i];
+ for (i = 0; i < SHARD_COUNT; i++) {
+ mdtab_shard *shard = &g_shards[i];
gpr_mu_init(&shard->mu);
shard->count = 0;
gpr_atm_no_barrier_store(&shard->free_estimate, 0);
- shard->capacity = INITIAL_MDTAB_CAPACITY;
+ shard->capacity = INITIAL_SHARD_CAPACITY;
shard->elems = gpr_malloc(sizeof(*shard->elems) * shard->capacity);
memset(shard->elems, 0, sizeof(*shard->elems) * shard->capacity);
}
@@ -230,8 +188,8 @@ void grpc_mdctx_global_init(void) {
void grpc_mdctx_global_shutdown(grpc_exec_ctx *exec_ctx) {
size_t i;
- for (i = 0; i < MDTAB_SHARD_COUNT; i++) {
- mdtab_shard *shard = &g_mdtab_shard[i];
+ for (i = 0; i < SHARD_COUNT; i++) {
+ mdtab_shard *shard = &g_shards[i];
gpr_mu_destroy(&shard->mu);
gc_mdtab(exec_ctx, shard);
/* TODO(ctiller): GPR_ASSERT(shard->count == 0); */
@@ -244,30 +202,6 @@ void grpc_mdctx_global_shutdown(grpc_exec_ctx *exec_ctx) {
}
gpr_free(shard->elems);
}
- for (i = 0; i < STRTAB_SHARD_COUNT; i++) {
- strtab_shard *shard = &g_strtab_shard[i];
- gpr_mu_destroy(&shard->mu);
- /* TODO(ctiller): GPR_ASSERT(shard->count == 0); */
- if (shard->count != 0) {
- gpr_log(GPR_DEBUG, "WARNING: %" PRIuPTR " metadata strings were leaked",
- shard->count);
- for (size_t j = 0; j < shard->capacity; j++) {
- for (internal_string *s = shard->strs[j]; s; s = s->bucket_next) {
- gpr_log(GPR_DEBUG, "LEAKED: %s",
- grpc_mdstr_as_c_string((grpc_mdstr *)s));
- }
- }
- if (grpc_iomgr_abort_on_leaks()) {
- abort();
- }
- }
- gpr_free(shard->strs);
- }
-}
-
-static int is_mdstr_static(grpc_mdstr *s) {
- return s >= &grpc_static_mdstr_table[0] &&
- s < &grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT];
}
static int is_mdelem_static(grpc_mdelem *e) {
@@ -282,170 +216,14 @@ static void ref_md_locked(mdtab_shard *shard,
"ELM REF:%p:%zu->%zu: '%s' = '%s'", (void *)md,
gpr_atm_no_barrier_load(&md->refcnt),
gpr_atm_no_barrier_load(&md->refcnt) + 1,
- grpc_mdstr_as_c_string((grpc_mdstr *)md->key),
- grpc_mdstr_as_c_string((grpc_mdstr *)md->value));
+ grpc_mdstr_as_c_string((grpc_slice)md->key),
+ grpc_mdstr_as_c_string((grpc_slice)md->value));
#endif
if (0 == gpr_atm_no_barrier_fetch_add(&md->refcnt, 1)) {
gpr_atm_no_barrier_fetch_add(&shard->free_estimate, -1);
}
}
-static void grow_strtab(strtab_shard *shard) {
- size_t capacity = shard->capacity * 2;
- size_t i;
- internal_string **strtab;
- internal_string *s, *next;
-
- GPR_TIMER_BEGIN("grow_strtab", 0);
-
- strtab = gpr_malloc(sizeof(internal_string *) * capacity);
- memset(strtab, 0, sizeof(internal_string *) * capacity);
-
- for (i = 0; i < shard->capacity; i++) {
- for (s = shard->strs[i]; s; s = next) {
- size_t idx = TABLE_IDX(s->hash, LOG2_STRTAB_SHARD_COUNT, capacity);
- next = s->bucket_next;
- s->bucket_next = strtab[idx];
- strtab[idx] = s;
- }
- }
-
- gpr_free(shard->strs);
- shard->strs = strtab;
- shard->capacity = capacity;
-
- GPR_TIMER_END("grow_strtab", 0);
-}
-
-static void internal_destroy_string(grpc_exec_ctx *exec_ctx,
- strtab_shard *shard, internal_string *is) {
- internal_string **prev_next;
- internal_string *cur;
- GPR_TIMER_BEGIN("internal_destroy_string", 0);
- if (is->has_base64_and_huffman_encoded) {
- grpc_slice_unref_internal(exec_ctx, is->base64_and_huffman);
- }
- for (prev_next = &shard->strs[TABLE_IDX(is->hash, LOG2_STRTAB_SHARD_COUNT,
- shard->capacity)],
- cur = *prev_next;
- cur != is; prev_next = &cur->bucket_next, cur = cur->bucket_next)
- ;
- *prev_next = cur->bucket_next;
- shard->count--;
- gpr_free(is);
- GPR_TIMER_END("internal_destroy_string", 0);
-}
-
-static void slice_ref(void *p) {
- internal_string *is =
- (internal_string *)((char *)p - offsetof(internal_string, refcount));
- GRPC_MDSTR_REF((grpc_mdstr *)(is));
-}
-
-static void slice_unref(grpc_exec_ctx *exec_ctx, void *p) {
- internal_string *is =
- (internal_string *)((char *)p - offsetof(internal_string, refcount));
- GRPC_MDSTR_UNREF(exec_ctx, (grpc_mdstr *)(is));
-}
-
-grpc_mdstr *grpc_mdstr_from_string(const char *str) {
- return grpc_mdstr_from_buffer((const uint8_t *)str, strlen(str));
-}
-
-grpc_mdstr *grpc_mdstr_from_slice(grpc_exec_ctx *exec_ctx, grpc_slice slice) {
- grpc_mdstr *result = grpc_mdstr_from_buffer(GRPC_SLICE_START_PTR(slice),
- GRPC_SLICE_LENGTH(slice));
- grpc_slice_unref_internal(exec_ctx, slice);
- return result;
-}
-
-grpc_mdstr *grpc_mdstr_from_buffer(const uint8_t *buf, size_t length) {
- uint32_t hash = gpr_murmur_hash3(buf, length, g_hash_seed);
- internal_string *s;
- strtab_shard *shard =
- &g_strtab_shard[SHARD_IDX(hash, LOG2_STRTAB_SHARD_COUNT)];
- size_t i;
- size_t idx;
-
- GPR_TIMER_BEGIN("grpc_mdstr_from_buffer", 0);
-
- /* search for a static string */
- for (i = 0; i <= g_static_strtab_maxprobe; i++) {
- grpc_mdstr *ss;
- idx = (hash + i) % GPR_ARRAY_SIZE(g_static_strtab);
- ss = g_static_strtab[idx];
- if (ss == NULL) break;
- if (ss->hash == hash && GRPC_SLICE_LENGTH(ss->slice) == length &&
- (length == 0 ||
- 0 == memcmp(buf, GRPC_SLICE_START_PTR(ss->slice), length))) {
- GPR_TIMER_END("grpc_mdstr_from_buffer", 0);
- return ss;
- }
- }
-
- gpr_mu_lock(&shard->mu);
-
- /* search for an existing string */
- idx = TABLE_IDX(hash, LOG2_STRTAB_SHARD_COUNT, shard->capacity);
- for (s = shard->strs[idx]; s; s = s->bucket_next) {
- if (s->hash == hash && GRPC_SLICE_LENGTH(s->slice) == length &&
- 0 == memcmp(buf, GRPC_SLICE_START_PTR(s->slice), length)) {
- if (gpr_atm_full_fetch_add(&s->refcnt, 1) == 0) {
- /* If we get here, we've added a ref to something that was about to
- * die - drop it immediately.
- * The *only* possible path here (given the shard mutex) should be to
- * drop from one ref back to zero - assert that with a CAS */
- GPR_ASSERT(gpr_atm_rel_cas(&s->refcnt, 1, 0));
- /* and treat this as if we were never here... sshhh */
- } else {
- gpr_mu_unlock(&shard->mu);
- GPR_TIMER_END("grpc_mdstr_from_buffer", 0);
- return (grpc_mdstr *)s;
- }
- }
- }
-
- /* not found: create a new string */
- if (length + 1 < GRPC_SLICE_INLINED_SIZE) {
- /* string data goes directly into the slice */
- s = gpr_malloc(sizeof(internal_string));
- gpr_atm_rel_store(&s->refcnt, 1);
- s->slice.refcount = NULL;
- memcpy(s->slice.data.inlined.bytes, buf, length);
- s->slice.data.inlined.bytes[length] = 0;
- s->slice.data.inlined.length = (uint8_t)length;
- } else {
- /* string data goes after the internal_string header, and we +1 for null
- terminator */
- s = gpr_malloc(sizeof(internal_string) + length + 1);
- gpr_atm_rel_store(&s->refcnt, 1);
- s->refcount.ref = slice_ref;
- s->refcount.unref = slice_unref;
- s->slice.refcount = &s->refcount;
- s->slice.data.refcounted.bytes = (uint8_t *)(s + 1);
- s->slice.data.refcounted.length = length;
- memcpy(s->slice.data.refcounted.bytes, buf, length);
- /* add a null terminator for cheap c string conversion when desired */
- s->slice.data.refcounted.bytes[length] = 0;
- }
- s->has_base64_and_huffman_encoded = 0;
- s->hash = hash;
- s->size_in_decoder_table = SIZE_IN_DECODER_TABLE_NOT_SET;
- s->bucket_next = shard->strs[idx];
- shard->strs[idx] = s;
-
- shard->count++;
-
- if (shard->count > shard->capacity * 2) {
- grow_strtab(shard);
- }
-
- gpr_mu_unlock(&shard->mu);
- GPR_TIMER_END("grpc_mdstr_from_buffer", 0);
-
- return (grpc_mdstr *)s;
-}
-
static void gc_mdtab(grpc_exec_ctx *exec_ctx, mdtab_shard *shard) {
size_t i;
internal_metadata **prev_next;
@@ -459,8 +237,8 @@ static void gc_mdtab(grpc_exec_ctx *exec_ctx, mdtab_shard *shard) {
void *user_data = (void *)gpr_atm_no_barrier_load(&md->user_data);
next = md->bucket_next;
if (gpr_atm_acq_load(&md->refcnt) == 0) {
- GRPC_MDSTR_UNREF(exec_ctx, (grpc_mdstr *)md->key);
- GRPC_MDSTR_UNREF(exec_ctx, (grpc_mdstr *)md->value);
+ grpc_slice_unref_internal(exec_ctx, md->key);
+ grpc_slice_unref_internal(exec_ctx, md->value);
if (md->user_data) {
((destroy_user_data_func)gpr_atm_no_barrier_load(
&md->destroy_user_data))(user_data);
@@ -493,9 +271,10 @@ static void grow_mdtab(mdtab_shard *shard) {
for (i = 0; i < shard->capacity; i++) {
for (md = shard->elems[i]; md; md = next) {
size_t idx;
- hash = GRPC_MDSTR_KV_HASH(md->key->hash, md->value->hash);
+ hash = GRPC_MDSTR_KV_HASH(grpc_slice_hash(md->key),
+ grpc_slice_hash(md->value));
next = md->bucket_next;
- idx = TABLE_IDX(hash, LOG2_MDTAB_SHARD_COUNT, capacity);
+ idx = TABLE_IDX(hash, capacity);
md->bucket_next = mdtab[idx];
mdtab[idx] = md;
}
@@ -517,26 +296,26 @@ static void rehash_mdtab(grpc_exec_ctx *exec_ctx, mdtab_shard *shard) {
}
}
-grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_exec_ctx *exec_ctx,
- grpc_mdstr *mkey,
- grpc_mdstr *mvalue) {
- internal_string *key = (internal_string *)mkey;
- internal_string *value = (internal_string *)mvalue;
- uint32_t hash = GRPC_MDSTR_KV_HASH(mkey->hash, mvalue->hash);
+grpc_mdelem *grpc_mdelem_from_slices(grpc_exec_ctx *exec_ctx, grpc_slice key,
+ grpc_slice value) {
+ uint32_t hash =
+ GRPC_MDSTR_KV_HASH(grpc_slice_hash(key), grpc_slice_hash(value));
internal_metadata *md;
- mdtab_shard *shard = &g_mdtab_shard[SHARD_IDX(hash, LOG2_MDTAB_SHARD_COUNT)];
+ mdtab_shard *shard = &g_shards[SHARD_IDX(hash)];
size_t i;
size_t idx;
GPR_TIMER_BEGIN("grpc_mdelem_from_metadata_strings", 0);
- if (is_mdstr_static(mkey) && is_mdstr_static(mvalue)) {
+ if (grpc_is_static_metadata_string(key) &&
+ grpc_is_static_metadata_string(value)) {
for (i = 0; i <= g_static_mdtab_maxprobe; i++) {
grpc_mdelem *smd;
idx = (hash + i) % GPR_ARRAY_SIZE(g_static_mdtab);
smd = g_static_mdtab[idx];
if (smd == NULL) break;
- if (smd->key == mkey && smd->value == mvalue) {
+ if (grpc_slice_cmp(key, smd->key) == 0 &&
+ grpc_slice_cmp(value, smd->value) == 0) {
GPR_TIMER_END("grpc_mdelem_from_metadata_strings", 0);
return smd;
}
@@ -545,14 +324,15 @@ grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_exec_ctx *exec_ctx,
gpr_mu_lock(&shard->mu);
- idx = TABLE_IDX(hash, LOG2_MDTAB_SHARD_COUNT, shard->capacity);
+ idx = TABLE_IDX(hash, shard->capacity);
/* search for an existing pair */
for (md = shard->elems[idx]; md; md = md->bucket_next) {
- if (md->key == key && md->value == value) {
+ if (grpc_slice_cmp(key, md->key) == 0 &&
+ grpc_slice_cmp(value, md->value) == 0) {
REF_MD_LOCKED(shard, md);
- GRPC_MDSTR_UNREF(exec_ctx, (grpc_mdstr *)key);
- GRPC_MDSTR_UNREF(exec_ctx, (grpc_mdstr *)value);
gpr_mu_unlock(&shard->mu);
+ grpc_slice_unref_internal(exec_ctx, key);
+ grpc_slice_unref_internal(exec_ctx, value);
GPR_TIMER_END("grpc_mdelem_from_metadata_strings", 0);
return (grpc_mdelem *)md;
}
@@ -571,8 +351,8 @@ grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_exec_ctx *exec_ctx,
#ifdef GRPC_METADATA_REFCOUNT_DEBUG
gpr_log(GPR_DEBUG, "ELM NEW:%p:%zu: '%s' = '%s'", (void *)md,
gpr_atm_no_barrier_load(&md->refcnt),
- grpc_mdstr_as_c_string((grpc_mdstr *)md->key),
- grpc_mdstr_as_c_string((grpc_mdstr *)md->value));
+ grpc_mdstr_as_c_string((grpc_slice)md->key),
+ grpc_mdstr_as_c_string((grpc_slice)md->value));
#endif
shard->count++;
@@ -587,58 +367,19 @@ grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_exec_ctx *exec_ctx,
return (grpc_mdelem *)md;
}
-grpc_mdelem *grpc_mdelem_from_strings(grpc_exec_ctx *exec_ctx, const char *key,
- const char *value) {
- return grpc_mdelem_from_metadata_strings(
- exec_ctx, grpc_mdstr_from_string(key), grpc_mdstr_from_string(value));
-}
-
-grpc_mdelem *grpc_mdelem_from_slices(grpc_exec_ctx *exec_ctx, grpc_slice key,
- grpc_slice value) {
- return grpc_mdelem_from_metadata_strings(
- exec_ctx, grpc_mdstr_from_slice(exec_ctx, key),
- grpc_mdstr_from_slice(exec_ctx, value));
-}
-
-grpc_mdelem *grpc_mdelem_from_string_and_buffer(grpc_exec_ctx *exec_ctx,
- const char *key,
- const uint8_t *value,
- size_t value_length) {
- return grpc_mdelem_from_metadata_strings(
- exec_ctx, grpc_mdstr_from_string(key),
- grpc_mdstr_from_buffer(value, value_length));
-}
-
static size_t get_base64_encoded_size(size_t raw_length) {
static const uint8_t tail_xtra[3] = {0, 2, 3};
return raw_length / 3 * 4 + tail_xtra[raw_length % 3];
}
size_t grpc_mdelem_get_size_in_hpack_table(grpc_mdelem *elem) {
- size_t overhead_and_key = 32 + GRPC_SLICE_LENGTH(elem->key->slice);
- size_t value_len = GRPC_SLICE_LENGTH(elem->value->slice);
- if (is_mdstr_static(elem->value)) {
- if (grpc_is_binary_header(
- (const char *)GRPC_SLICE_START_PTR(elem->key->slice),
- GRPC_SLICE_LENGTH(elem->key->slice))) {
- return overhead_and_key + get_base64_encoded_size(value_len);
- } else {
- return overhead_and_key + value_len;
- }
+ size_t overhead_and_key = 32 + GRPC_SLICE_LENGTH(elem->key);
+ size_t value_len = GRPC_SLICE_LENGTH(elem->value);
+ if (grpc_is_binary_header((const char *)GRPC_SLICE_START_PTR(elem->key),
+ GRPC_SLICE_LENGTH(elem->key))) {
+ return overhead_and_key + get_base64_encoded_size(value_len);
} else {
- internal_string *is = (internal_string *)elem->value;
- gpr_atm current_size = gpr_atm_acq_load(&is->size_in_decoder_table);
- if (current_size == SIZE_IN_DECODER_TABLE_NOT_SET) {
- if (grpc_is_binary_header(
- (const char *)GRPC_SLICE_START_PTR(elem->key->slice),
- GRPC_SLICE_LENGTH(elem->key->slice))) {
- current_size = (gpr_atm)get_base64_encoded_size(value_len);
- } else {
- current_size = (gpr_atm)value_len;
- }
- gpr_atm_rel_store(&is->size_in_decoder_table, current_size);
- }
- return overhead_and_key + (size_t)current_size;
+ return overhead_and_key + value_len;
}
}
@@ -650,8 +391,8 @@ grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *gmd DEBUG_ARGS) {
"ELM REF:%p:%zu->%zu: '%s' = '%s'", (void *)md,
gpr_atm_no_barrier_load(&md->refcnt),
gpr_atm_no_barrier_load(&md->refcnt) + 1,
- grpc_mdstr_as_c_string((grpc_mdstr *)md->key),
- grpc_mdstr_as_c_string((grpc_mdstr *)md->value));
+ grpc_mdstr_as_c_string((grpc_slice)md->key),
+ grpc_mdstr_as_c_string((grpc_slice)md->value));
#endif
/* we can assume the ref count is >= 1 as the application is calling
this function - meaning that no adjustment to mdtab_free is necessary,
@@ -671,57 +412,21 @@ void grpc_mdelem_unref(grpc_exec_ctx *exec_ctx, grpc_mdelem *gmd DEBUG_ARGS) {
"ELM UNREF:%p:%zu->%zu: '%s' = '%s'", (void *)md,
gpr_atm_no_barrier_load(&md->refcnt),
gpr_atm_no_barrier_load(&md->refcnt) - 1,
- grpc_mdstr_as_c_string((grpc_mdstr *)md->key),
- grpc_mdstr_as_c_string((grpc_mdstr *)md->value));
+ grpc_mdstr_as_c_string((grpc_slice)md->key),
+ grpc_mdstr_as_c_string((grpc_slice)md->value));
#endif
- uint32_t hash = GRPC_MDSTR_KV_HASH(md->key->hash, md->value->hash);
+ uint32_t hash =
+ GRPC_MDSTR_KV_HASH(grpc_slice_hash(md->key), grpc_slice_hash(md->value));
const gpr_atm prev_refcount = gpr_atm_full_fetch_add(&md->refcnt, -1);
GPR_ASSERT(prev_refcount >= 1);
if (1 == prev_refcount) {
/* once the refcount hits zero, some other thread can come along and
free md at any time: it's unsafe from this point on to access it */
- mdtab_shard *shard =
- &g_mdtab_shard[SHARD_IDX(hash, LOG2_MDTAB_SHARD_COUNT)];
+ mdtab_shard *shard = &g_shards[SHARD_IDX(hash)];
gpr_atm_no_barrier_fetch_add(&shard->free_estimate, 1);
}
}
-const char *grpc_mdstr_as_c_string(const grpc_mdstr *s) {
- return (const char *)GRPC_SLICE_START_PTR(s->slice);
-}
-
-size_t grpc_mdstr_length(const grpc_mdstr *s) { return GRPC_MDSTR_LENGTH(s); }
-
-grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *gs DEBUG_ARGS) {
- internal_string *s = (internal_string *)gs;
- if (is_mdstr_static(gs)) return gs;
-#ifdef GRPC_METADATA_REFCOUNT_DEBUG
- gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "STR REF:%p:%zu->%zu: '%s'",
- (void *)s, gpr_atm_no_barrier_load(&s->refcnt),
- gpr_atm_no_barrier_load(&s->refcnt) + 1, grpc_mdstr_as_c_string(gs));
-#endif
- GPR_ASSERT(gpr_atm_full_fetch_add(&s->refcnt, 1) > 0);
- return gs;
-}
-
-void grpc_mdstr_unref(grpc_exec_ctx *exec_ctx, grpc_mdstr *gs DEBUG_ARGS) {
- internal_string *s = (internal_string *)gs;
- if (is_mdstr_static(gs)) return;
-#ifdef GRPC_METADATA_REFCOUNT_DEBUG
- gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "STR UNREF:%p:%zu->%zu: '%s'",
- (void *)s, gpr_atm_no_barrier_load(&s->refcnt),
- gpr_atm_no_barrier_load(&s->refcnt) - 1, grpc_mdstr_as_c_string(gs));
-#endif
- if (1 == gpr_atm_full_fetch_add(&s->refcnt, -1)) {
- strtab_shard *shard =
- &g_strtab_shard[SHARD_IDX(s->hash, LOG2_STRTAB_SHARD_COUNT)];
- gpr_mu_lock(&shard->mu);
- GPR_ASSERT(0 == gpr_atm_no_barrier_load(&s->refcnt));
- internal_destroy_string(exec_ctx, shard, s);
- gpr_mu_unlock(&shard->mu);
- }
-}
-
void *grpc_mdelem_get_user_data(grpc_mdelem *md, void (*destroy_func)(void *)) {
internal_metadata *im = (internal_metadata *)md;
void *result;
@@ -755,19 +460,3 @@ void *grpc_mdelem_set_user_data(grpc_mdelem *md, void (*destroy_func)(void *),
gpr_mu_unlock(&im->mu_user_data);
return user_data;
}
-
-grpc_slice grpc_mdstr_as_base64_encoded_and_huffman_compressed(grpc_mdstr *gs) {
- internal_string *s = (internal_string *)gs;
- grpc_slice slice;
- strtab_shard *shard =
- &g_strtab_shard[SHARD_IDX(s->hash, LOG2_STRTAB_SHARD_COUNT)];
- gpr_mu_lock(&shard->mu);
- if (!s->has_base64_and_huffman_encoded) {
- s->base64_and_huffman =
- grpc_chttp2_base64_encode_and_huffman_compress(s->slice);
- s->has_base64_and_huffman_encoded = 1;
- }
- slice = s->base64_and_huffman;
- gpr_mu_unlock(&shard->mu);
- return slice;
-}
diff --git a/src/core/lib/transport/metadata.h b/src/core/lib/transport/metadata.h
index 991eee96f1..50c8e1fa91 100644
--- a/src/core/lib/transport/metadata.h
+++ b/src/core/lib/transport/metadata.h
@@ -74,51 +74,19 @@ extern "C" {
declared here - in which case those functions are effectively no-ops. */
/* Forward declarations */
-typedef struct grpc_mdstr grpc_mdstr;
typedef struct grpc_mdelem grpc_mdelem;
-/* if changing this, make identical changes in internal_string in metadata.c */
-struct grpc_mdstr {
- const grpc_slice slice;
- const uint32_t hash;
- /* there is a private part to this in metadata.c */
-};
-
/* if changing this, make identical changes in internal_metadata in
metadata.c */
struct grpc_mdelem {
- grpc_mdstr *const key;
- grpc_mdstr *const value;
+ const grpc_slice key;
+ const grpc_slice value;
/* there is a private part to this in metadata.c */
};
-void grpc_test_only_set_metadata_hash_seed(uint32_t seed);
-
-/* Constructors for grpc_mdstr instances; take a variety of data types that
- clients may have handy */
-grpc_mdstr *grpc_mdstr_from_string(const char *str);
-/* Unrefs the slice. */
-grpc_mdstr *grpc_mdstr_from_slice(grpc_exec_ctx *exec_ctx, grpc_slice slice);
-grpc_mdstr *grpc_mdstr_from_buffer(const uint8_t *str, size_t length);
-
-/* Returns a borrowed slice from the mdstr with its contents base64 encoded
- and huffman compressed */
-grpc_slice grpc_mdstr_as_base64_encoded_and_huffman_compressed(grpc_mdstr *str);
-
-/* Constructors for grpc_mdelem instances; take a variety of data types that
- clients may have handy */
-grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_exec_ctx *exec_ctx,
- grpc_mdstr *key,
- grpc_mdstr *value);
-grpc_mdelem *grpc_mdelem_from_strings(grpc_exec_ctx *exec_ctx, const char *key,
- const char *value);
/* Unrefs the slices. */
grpc_mdelem *grpc_mdelem_from_slices(grpc_exec_ctx *exec_ctx, grpc_slice key,
grpc_slice value);
-grpc_mdelem *grpc_mdelem_from_string_and_buffer(grpc_exec_ctx *exec_ctx,
- const char *key,
- const uint8_t *value,
- size_t value_length);
size_t grpc_mdelem_get_size_in_hpack_table(grpc_mdelem *elem);
@@ -132,52 +100,28 @@ void *grpc_mdelem_set_user_data(grpc_mdelem *md, void (*destroy_func)(void *),
/* Reference counting */
//#define GRPC_METADATA_REFCOUNT_DEBUG
#ifdef GRPC_METADATA_REFCOUNT_DEBUG
-#define GRPC_MDSTR_REF(s) grpc_mdstr_ref((s), __FILE__, __LINE__)
-#define GRPC_MDSTR_UNREF(exec_ctx, s) \
- grpc_mdstr_unref((exec_ctx), (s), __FILE__, __LINE__)
#define GRPC_MDELEM_REF(s) grpc_mdelem_ref((s), __FILE__, __LINE__)
#define GRPC_MDELEM_UNREF(exec_ctx, s) \
grpc_mdelem_unref((exec_ctx), (s), __FILE__, __LINE__)
-grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *s, const char *file, int line);
-void grpc_mdstr_unref(grpc_exec_ctx *exec_ctx, grpc_mdstr *s, const char *file,
- int line);
grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *md, const char *file, int line);
void grpc_mdelem_unref(grpc_exec_ctx *exec_ctx, grpc_mdelem *md,
const char *file, int line);
#else
-#define GRPC_MDSTR_REF(s) grpc_mdstr_ref((s))
-#define GRPC_MDSTR_UNREF(exec_ctx, s) grpc_mdstr_unref((exec_ctx), (s))
#define GRPC_MDELEM_REF(s) grpc_mdelem_ref((s))
#define GRPC_MDELEM_UNREF(exec_ctx, s) grpc_mdelem_unref((exec_ctx), (s))
-grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *s);
-void grpc_mdstr_unref(grpc_exec_ctx *exec_ctx, grpc_mdstr *s);
grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *md);
void grpc_mdelem_unref(grpc_exec_ctx *exec_ctx, grpc_mdelem *md);
#endif
-/* Recover a char* from a grpc_mdstr. The returned string is null terminated.
- Does not promise that the returned string has no embedded nulls however. */
-const char *grpc_mdstr_as_c_string(const grpc_mdstr *s);
-
-#define GRPC_MDSTR_LENGTH(s) (GRPC_SLICE_LENGTH(s->slice))
-
/* We add 32 bytes of padding as per RFC-7540 section 6.5.2. */
#define GRPC_MDELEM_LENGTH(e) \
- (GRPC_MDSTR_LENGTH((e)->key) + GRPC_MDSTR_LENGTH((e)->value) + 32)
-
-int grpc_mdstr_is_legal_header(grpc_mdstr *s);
-int grpc_mdstr_is_legal_nonbin_header(grpc_mdstr *s);
-int grpc_mdstr_is_bin_suffixed(grpc_mdstr *s);
+ (GRPC_SLICE_LENGTH((e)->key) + GRPC_SLICE_LENGTH((e)->value) + 32)
#define GRPC_MDSTR_KV_HASH(k_hash, v_hash) (GPR_ROTL((k_hash), 2) ^ (v_hash))
void grpc_mdctx_global_init(void);
void grpc_mdctx_global_shutdown(grpc_exec_ctx *exec_ctx);
-/* Implementation provided by chttp2_transport */
-extern grpc_slice (*grpc_chttp2_base64_encode_and_huffman_compress)(
- grpc_slice input);
-
#ifdef __cplusplus
}
#endif
diff --git a/src/core/lib/transport/method_config.c b/src/core/lib/transport/method_config.c
index 25fb54b37d..75317d426d 100644
--- a/src/core/lib/transport/method_config.c
+++ b/src/core/lib/transport/method_config.c
@@ -39,8 +39,10 @@
#include <grpc/support/string_util.h>
#include <grpc/support/time.h>
-#include "src/core/lib/transport/mdstr_hash_table.h"
+#include "src/core/lib/slice/slice_hash_table.h"
+#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/transport/metadata.h"
+#include "src/core/lib/transport/static_metadata.h"
//
// grpc_method_config
@@ -48,252 +50,224 @@
// bool vtable
-static void* bool_copy(void* valuep) {
- bool value = *(bool*)valuep;
- bool* new_value = gpr_malloc(sizeof(bool));
+static void *bool_copy(void *valuep) {
+ bool value = *(bool *)valuep;
+ bool *new_value = gpr_malloc(sizeof(bool));
*new_value = value;
return new_value;
}
-static int bool_cmp(void* v1, void* v2) {
- bool b1 = *(bool*)v1;
- bool b2 = *(bool*)v2;
+static int bool_cmp(void *v1, void *v2) {
+ bool b1 = *(bool *)v1;
+ bool b2 = *(bool *)v2;
if (!b1 && b2) return -1;
if (b1 && !b2) return 1;
return 0;
}
-static void free_mem(grpc_exec_ctx* exec_ctx, void* p) { gpr_free(p); }
+static void free_mem(grpc_exec_ctx *exec_ctx, void *p) { gpr_free(p); }
-static grpc_mdstr_hash_table_vtable bool_vtable = {free_mem, bool_copy,
+static grpc_slice_hash_table_vtable bool_vtable = {free_mem, bool_copy,
bool_cmp};
// timespec vtable
-static void* timespec_copy(void* valuep) {
- gpr_timespec value = *(gpr_timespec*)valuep;
- gpr_timespec* new_value = gpr_malloc(sizeof(gpr_timespec));
+static void *timespec_copy(void *valuep) {
+ gpr_timespec value = *(gpr_timespec *)valuep;
+ gpr_timespec *new_value = gpr_malloc(sizeof(gpr_timespec));
*new_value = value;
return new_value;
}
-static int timespec_cmp(void* v1, void* v2) {
- return gpr_time_cmp(*(gpr_timespec*)v1, *(gpr_timespec*)v2);
+static int timespec_cmp(void *v1, void *v2) {
+ return gpr_time_cmp(*(gpr_timespec *)v1, *(gpr_timespec *)v2);
}
-static grpc_mdstr_hash_table_vtable timespec_vtable = {free_mem, timespec_copy,
+static grpc_slice_hash_table_vtable timespec_vtable = {free_mem, timespec_copy,
timespec_cmp};
// int32 vtable
-static void* int32_copy(void* valuep) {
- int32_t value = *(int32_t*)valuep;
- int32_t* new_value = gpr_malloc(sizeof(int32_t));
+static void *int32_copy(void *valuep) {
+ int32_t value = *(int32_t *)valuep;
+ int32_t *new_value = gpr_malloc(sizeof(int32_t));
*new_value = value;
return new_value;
}
-static int int32_cmp(void* v1, void* v2) {
- int32_t i1 = *(int32_t*)v1;
- int32_t i2 = *(int32_t*)v2;
+static int int32_cmp(void *v1, void *v2) {
+ int32_t i1 = *(int32_t *)v1;
+ int32_t i2 = *(int32_t *)v2;
if (i1 < i2) return -1;
if (i1 > i2) return 1;
return 0;
}
-static grpc_mdstr_hash_table_vtable int32_vtable = {free_mem, int32_copy,
+static grpc_slice_hash_table_vtable int32_vtable = {free_mem, int32_copy,
int32_cmp};
-// Hash table keys.
-#define GRPC_METHOD_CONFIG_WAIT_FOR_READY "grpc.wait_for_ready" // bool
-#define GRPC_METHOD_CONFIG_TIMEOUT "grpc.timeout" // gpr_timespec
-#define GRPC_METHOD_CONFIG_MAX_REQUEST_MESSAGE_BYTES \
- "grpc.max_request_message_bytes" // int32
-#define GRPC_METHOD_CONFIG_MAX_RESPONSE_MESSAGE_BYTES \
- "grpc.max_response_message_bytes" // int32
-
struct grpc_method_config {
- grpc_mdstr_hash_table* table;
- grpc_mdstr* wait_for_ready_key;
- grpc_mdstr* timeout_key;
- grpc_mdstr* max_request_message_bytes_key;
- grpc_mdstr* max_response_message_bytes_key;
+ grpc_slice_hash_table *table;
};
-grpc_method_config* grpc_method_config_create(
- bool* wait_for_ready, gpr_timespec* timeout,
- int32_t* max_request_message_bytes, int32_t* max_response_message_bytes) {
- grpc_method_config* method_config = gpr_malloc(sizeof(grpc_method_config));
+grpc_method_config *grpc_method_config_create(
+ bool *wait_for_ready, gpr_timespec *timeout,
+ int32_t *max_request_message_bytes, int32_t *max_response_message_bytes) {
+ grpc_method_config *method_config = gpr_malloc(sizeof(grpc_method_config));
memset(method_config, 0, sizeof(grpc_method_config));
- method_config->wait_for_ready_key =
- grpc_mdstr_from_string(GRPC_METHOD_CONFIG_WAIT_FOR_READY);
- method_config->timeout_key =
- grpc_mdstr_from_string(GRPC_METHOD_CONFIG_TIMEOUT);
- method_config->max_request_message_bytes_key =
- grpc_mdstr_from_string(GRPC_METHOD_CONFIG_MAX_REQUEST_MESSAGE_BYTES);
- method_config->max_response_message_bytes_key =
- grpc_mdstr_from_string(GRPC_METHOD_CONFIG_MAX_RESPONSE_MESSAGE_BYTES);
- grpc_mdstr_hash_table_entry entries[4];
+ grpc_slice_hash_table_entry entries[4];
size_t num_entries = 0;
if (wait_for_ready != NULL) {
- entries[num_entries].key = method_config->wait_for_ready_key;
+ entries[num_entries].key = GRPC_MDSTR_GRPC_DOT_WAIT_FOR_READY;
entries[num_entries].value = wait_for_ready;
entries[num_entries].vtable = &bool_vtable;
++num_entries;
}
if (timeout != NULL) {
- entries[num_entries].key = method_config->timeout_key;
+ entries[num_entries].key = GRPC_MDSTR_GRPC_DOT_TIMEOUT;
entries[num_entries].value = timeout;
entries[num_entries].vtable = &timespec_vtable;
++num_entries;
}
if (max_request_message_bytes != NULL) {
- entries[num_entries].key = method_config->max_request_message_bytes_key;
+ entries[num_entries].key = GRPC_MDSTR_GRPC_DOT_MAX_REQUEST_MESSAGE_BYTES;
entries[num_entries].value = max_request_message_bytes;
entries[num_entries].vtable = &int32_vtable;
++num_entries;
}
if (max_response_message_bytes != NULL) {
- entries[num_entries].key = method_config->max_response_message_bytes_key;
+ entries[num_entries].key = GRPC_MDSTR_GRPC_DOT_MAX_RESPONSE_MESSAGE_BYTES;
entries[num_entries].value = max_response_message_bytes;
entries[num_entries].vtable = &int32_vtable;
++num_entries;
}
- method_config->table = grpc_mdstr_hash_table_create(num_entries, entries);
+ method_config->table = grpc_slice_hash_table_create(num_entries, entries);
return method_config;
}
-grpc_method_config* grpc_method_config_ref(grpc_method_config* method_config) {
- grpc_mdstr_hash_table_ref(method_config->table);
+grpc_method_config *grpc_method_config_ref(grpc_method_config *method_config) {
+ grpc_slice_hash_table_ref(method_config->table);
return method_config;
}
-void grpc_method_config_unref(grpc_exec_ctx* exec_ctx,
- grpc_method_config* method_config) {
- if (grpc_mdstr_hash_table_unref(exec_ctx, method_config->table)) {
- GRPC_MDSTR_UNREF(exec_ctx, method_config->wait_for_ready_key);
- GRPC_MDSTR_UNREF(exec_ctx, method_config->timeout_key);
- GRPC_MDSTR_UNREF(exec_ctx, method_config->max_request_message_bytes_key);
- GRPC_MDSTR_UNREF(exec_ctx, method_config->max_response_message_bytes_key);
+void grpc_method_config_unref(grpc_exec_ctx *exec_ctx,
+ grpc_method_config *method_config) {
+ if (grpc_slice_hash_table_unref(exec_ctx, method_config->table)) {
gpr_free(method_config);
}
}
-int grpc_method_config_cmp(const grpc_method_config* method_config1,
- const grpc_method_config* method_config2) {
- return grpc_mdstr_hash_table_cmp(method_config1->table,
+int grpc_method_config_cmp(const grpc_method_config *method_config1,
+ const grpc_method_config *method_config2) {
+ return grpc_slice_hash_table_cmp(method_config1->table,
method_config2->table);
}
-const bool* grpc_method_config_get_wait_for_ready(
- const grpc_method_config* method_config) {
- return grpc_mdstr_hash_table_get(method_config->table,
- method_config->wait_for_ready_key);
+const bool *grpc_method_config_get_wait_for_ready(
+ const grpc_method_config *method_config) {
+ return grpc_slice_hash_table_get(method_config->table,
+ GRPC_MDSTR_GRPC_DOT_WAIT_FOR_READY);
}
-const gpr_timespec* grpc_method_config_get_timeout(
- const grpc_method_config* method_config) {
- return grpc_mdstr_hash_table_get(method_config->table,
- method_config->timeout_key);
+const gpr_timespec *grpc_method_config_get_timeout(
+ const grpc_method_config *method_config) {
+ return grpc_slice_hash_table_get(method_config->table,
+ GRPC_MDSTR_GRPC_DOT_TIMEOUT);
}
-const int32_t* grpc_method_config_get_max_request_message_bytes(
- const grpc_method_config* method_config) {
- return grpc_mdstr_hash_table_get(
- method_config->table, method_config->max_request_message_bytes_key);
+const int32_t *grpc_method_config_get_max_request_message_bytes(
+ const grpc_method_config *method_config) {
+ return grpc_slice_hash_table_get(
+ method_config->table, GRPC_MDSTR_GRPC_DOT_MAX_REQUEST_MESSAGE_BYTES);
}
-const int32_t* grpc_method_config_get_max_response_message_bytes(
- const grpc_method_config* method_config) {
- return grpc_mdstr_hash_table_get(
- method_config->table, method_config->max_response_message_bytes_key);
+const int32_t *grpc_method_config_get_max_response_message_bytes(
+ const grpc_method_config *method_config) {
+ return grpc_slice_hash_table_get(
+ method_config->table, GRPC_MDSTR_GRPC_DOT_MAX_RESPONSE_MESSAGE_BYTES);
}
//
// grpc_method_config_table
//
-static void method_config_unref(grpc_exec_ctx* exec_ctx, void* valuep) {
+static void method_config_unref(grpc_exec_ctx *exec_ctx, void *valuep) {
grpc_method_config_unref(exec_ctx, valuep);
}
-static void* method_config_ref(void* valuep) {
+static void *method_config_ref(void *valuep) {
return grpc_method_config_ref(valuep);
}
-static int method_config_cmp(void* valuep1, void* valuep2) {
+static int method_config_cmp(void *valuep1, void *valuep2) {
return grpc_method_config_cmp(valuep1, valuep2);
}
-static const grpc_mdstr_hash_table_vtable method_config_table_vtable = {
+static const grpc_slice_hash_table_vtable method_config_table_vtable = {
method_config_unref, method_config_ref, method_config_cmp};
-grpc_method_config_table* grpc_method_config_table_create(
- size_t num_entries, grpc_method_config_table_entry* entries) {
- grpc_mdstr_hash_table_entry* hash_table_entries =
- gpr_malloc(sizeof(grpc_mdstr_hash_table_entry) * num_entries);
+grpc_method_config_table *grpc_method_config_table_create(
+ size_t num_entries, grpc_method_config_table_entry *entries) {
+ grpc_slice_hash_table_entry *hash_table_entries =
+ gpr_malloc(sizeof(grpc_slice_hash_table_entry) * num_entries);
for (size_t i = 0; i < num_entries; ++i) {
hash_table_entries[i].key = entries[i].method_name;
hash_table_entries[i].value = entries[i].method_config;
hash_table_entries[i].vtable = &method_config_table_vtable;
}
- grpc_method_config_table* method_config_table =
- grpc_mdstr_hash_table_create(num_entries, hash_table_entries);
+ grpc_method_config_table *method_config_table =
+ grpc_slice_hash_table_create(num_entries, hash_table_entries);
gpr_free(hash_table_entries);
return method_config_table;
}
-grpc_method_config_table* grpc_method_config_table_ref(
- grpc_method_config_table* table) {
- return grpc_mdstr_hash_table_ref(table);
+grpc_method_config_table *grpc_method_config_table_ref(
+ grpc_method_config_table *table) {
+ return grpc_slice_hash_table_ref(table);
}
-void grpc_method_config_table_unref(grpc_exec_ctx* exec_ctx,
- grpc_method_config_table* table) {
- grpc_mdstr_hash_table_unref(exec_ctx, table);
+void grpc_method_config_table_unref(grpc_exec_ctx *exec_ctx,
+ grpc_method_config_table *table) {
+ grpc_slice_hash_table_unref(exec_ctx, table);
}
-int grpc_method_config_table_cmp(const grpc_method_config_table* table1,
- const grpc_method_config_table* table2) {
- return grpc_mdstr_hash_table_cmp(table1, table2);
+int grpc_method_config_table_cmp(const grpc_method_config_table *table1,
+ const grpc_method_config_table *table2) {
+ return grpc_slice_hash_table_cmp(table1, table2);
}
-void* grpc_method_config_table_get(grpc_exec_ctx* exec_ctx,
- const grpc_mdstr_hash_table* table,
- const grpc_mdstr* path) {
- void* value = grpc_mdstr_hash_table_get(table, path);
+void *grpc_method_config_table_get(grpc_exec_ctx *exec_ctx,
+ const grpc_slice_hash_table *table,
+ const grpc_slice path) {
+ void *value = grpc_slice_hash_table_get(table, path);
// If we didn't find a match for the path, try looking for a wildcard
// entry (i.e., change "/service/method" to "/service/*").
if (value == NULL) {
- const char* path_str = grpc_mdstr_as_c_string(path);
- const char* sep = strrchr(path_str, '/') + 1;
- const size_t len = (size_t)(sep - path_str);
- char* buf = gpr_malloc(len + 2); // '*' and NUL
- memcpy(buf, path_str, len);
- buf[len] = '*';
- buf[len + 1] = '\0';
- grpc_mdstr* wildcard_path = grpc_mdstr_from_string(buf);
- gpr_free(buf);
- value = grpc_mdstr_hash_table_get(table, wildcard_path);
- GRPC_MDSTR_UNREF(exec_ctx, wildcard_path);
+ int sep_pos = grpc_slice_rchr(path, '/') + 1;
+ grpc_slice search = grpc_slice_malloc((size_t)(sep_pos + 1));
+ memcpy(GRPC_SLICE_START_PTR(search), GRPC_SLICE_START_PTR(path),
+ (size_t)sep_pos);
+ GRPC_SLICE_START_PTR(search)[sep_pos] = '*';
+ value = grpc_slice_hash_table_get(table, search);
+ grpc_slice_unref_internal(exec_ctx, search);
}
return value;
}
-static void* copy_arg(void* p) { return grpc_method_config_table_ref(p); }
+static void *copy_arg(void *p) { return grpc_method_config_table_ref(p); }
-static void destroy_arg(grpc_exec_ctx* exec_ctx, void* p) {
+static void destroy_arg(grpc_exec_ctx *exec_ctx, void *p) {
grpc_method_config_table_unref(exec_ctx, p);
}
-static int cmp_arg(void* p1, void* p2) {
+static int cmp_arg(void *p1, void *p2) {
return grpc_method_config_table_cmp(p1, p2);
}
static grpc_arg_pointer_vtable arg_vtable = {copy_arg, destroy_arg, cmp_arg};
grpc_arg grpc_method_config_table_create_channel_arg(
- grpc_method_config_table* table) {
+ grpc_method_config_table *table) {
grpc_arg arg;
arg.type = GRPC_ARG_POINTER;
arg.key = GRPC_ARG_SERVICE_CONFIG;
@@ -304,41 +278,41 @@ grpc_arg grpc_method_config_table_create_channel_arg(
// State used by convert_entry() below.
typedef struct conversion_state {
- void* (*convert_value)(const grpc_method_config* method_config);
- const grpc_mdstr_hash_table_vtable* vtable;
+ void *(*convert_value)(const grpc_method_config *method_config);
+ const grpc_slice_hash_table_vtable *vtable;
size_t num_entries;
- grpc_mdstr_hash_table_entry* entries;
+ grpc_slice_hash_table_entry *entries;
} conversion_state;
-// A function to be passed to grpc_mdstr_hash_table_iterate() to create
+// A function to be passed to grpc_slice_hash_table_iterate() to create
// a copy of the entries.
-static void convert_entry(const grpc_mdstr_hash_table_entry* entry,
- void* user_data) {
- conversion_state* state = user_data;
- state->entries[state->num_entries].key = GRPC_MDSTR_REF(entry->key);
+static void convert_entry(const grpc_slice_hash_table_entry *entry,
+ void *user_data) {
+ conversion_state *state = user_data;
+ state->entries[state->num_entries].key = grpc_slice_ref_internal(entry->key);
state->entries[state->num_entries].value = state->convert_value(entry->value);
state->entries[state->num_entries].vtable = state->vtable;
++state->num_entries;
}
-grpc_mdstr_hash_table* grpc_method_config_table_convert(
- grpc_exec_ctx* exec_ctx, const grpc_method_config_table* table,
- void* (*convert_value)(const grpc_method_config* method_config),
- const grpc_mdstr_hash_table_vtable* vtable) {
+grpc_slice_hash_table *grpc_method_config_table_convert(
+ grpc_exec_ctx *exec_ctx, const grpc_method_config_table *table,
+ void *(*convert_value)(const grpc_method_config *method_config),
+ const grpc_slice_hash_table_vtable *vtable) {
// Create an array of the entries in the table with converted values.
conversion_state state;
state.convert_value = convert_value;
state.vtable = vtable;
state.num_entries = 0;
- state.entries = gpr_malloc(sizeof(grpc_mdstr_hash_table_entry) *
- grpc_mdstr_hash_table_num_entries(table));
- grpc_mdstr_hash_table_iterate(table, convert_entry, &state);
+ state.entries = gpr_malloc(sizeof(grpc_slice_hash_table_entry) *
+ grpc_slice_hash_table_num_entries(table));
+ grpc_slice_hash_table_iterate(table, convert_entry, &state);
// Create a new table based on the array we just constructed.
- grpc_mdstr_hash_table* new_table =
- grpc_mdstr_hash_table_create(state.num_entries, state.entries);
+ grpc_slice_hash_table *new_table =
+ grpc_slice_hash_table_create(state.num_entries, state.entries);
// Clean up the array.
for (size_t i = 0; i < state.num_entries; ++i) {
- GRPC_MDSTR_UNREF(exec_ctx, state.entries[i].key);
+ grpc_slice_unref_internal(exec_ctx, state.entries[i].key);
vtable->destroy_value(exec_ctx, state.entries[i].value);
}
gpr_free(state.entries);
diff --git a/src/core/lib/transport/method_config.h b/src/core/lib/transport/method_config.h
index d17a493fd4..3e266a6ecd 100644
--- a/src/core/lib/transport/method_config.h
+++ b/src/core/lib/transport/method_config.h
@@ -37,7 +37,7 @@
#include <grpc/impl/codegen/gpr_types.h>
#include <grpc/impl/codegen/grpc_types.h>
-#include "src/core/lib/transport/mdstr_hash_table.h"
+#include "src/core/lib/slice/slice_hash_table.h"
#include "src/core/lib/transport/metadata.h"
/// Per-method configuration.
@@ -55,70 +55,70 @@ typedef struct grpc_method_config grpc_method_config;
/// \a max_request_message_bytes and \a max_response_message_bytes
/// indicate the maximum sizes of the request (checked when sending) and
/// response (checked when receiving) messages.
-grpc_method_config* grpc_method_config_create(
- bool* wait_for_ready, gpr_timespec* timeout,
- int32_t* max_request_message_bytes, int32_t* max_response_message_bytes);
+grpc_method_config *grpc_method_config_create(
+ bool *wait_for_ready, gpr_timespec *timeout,
+ int32_t *max_request_message_bytes, int32_t *max_response_message_bytes);
-grpc_method_config* grpc_method_config_ref(grpc_method_config* method_config);
-void grpc_method_config_unref(grpc_exec_ctx* exec_ctx,
- grpc_method_config* method_config);
+grpc_method_config *grpc_method_config_ref(grpc_method_config *method_config);
+void grpc_method_config_unref(grpc_exec_ctx *exec_ctx,
+ grpc_method_config *method_config);
/// Compares two grpc_method_configs.
/// The sort order is stable but undefined.
-int grpc_method_config_cmp(const grpc_method_config* method_config1,
- const grpc_method_config* method_config2);
+int grpc_method_config_cmp(const grpc_method_config *method_config1,
+ const grpc_method_config *method_config2);
/// These methods return NULL if the requested field is unset.
/// The caller does NOT take ownership of the result.
-const bool* grpc_method_config_get_wait_for_ready(
- const grpc_method_config* method_config);
-const gpr_timespec* grpc_method_config_get_timeout(
- const grpc_method_config* method_config);
-const int32_t* grpc_method_config_get_max_request_message_bytes(
- const grpc_method_config* method_config);
-const int32_t* grpc_method_config_get_max_response_message_bytes(
- const grpc_method_config* method_config);
+const bool *grpc_method_config_get_wait_for_ready(
+ const grpc_method_config *method_config);
+const gpr_timespec *grpc_method_config_get_timeout(
+ const grpc_method_config *method_config);
+const int32_t *grpc_method_config_get_max_request_message_bytes(
+ const grpc_method_config *method_config);
+const int32_t *grpc_method_config_get_max_response_message_bytes(
+ const grpc_method_config *method_config);
/// A table of method configs.
-typedef grpc_mdstr_hash_table grpc_method_config_table;
+typedef grpc_slice_hash_table grpc_method_config_table;
typedef struct grpc_method_config_table_entry {
/// The name is of one of the following forms:
/// service/method -- specifies exact service and method name
/// service/* -- matches all methods for the specified service
- grpc_mdstr* method_name;
- grpc_method_config* method_config;
+ grpc_slice method_name;
+ grpc_method_config *method_config;
} grpc_method_config_table_entry;
/// Takes new references to all keys and values in \a entries.
-grpc_method_config_table* grpc_method_config_table_create(
- size_t num_entries, grpc_method_config_table_entry* entries);
+grpc_method_config_table *grpc_method_config_table_create(
+ size_t num_entries, grpc_method_config_table_entry *entries);
-grpc_method_config_table* grpc_method_config_table_ref(
- grpc_method_config_table* table);
-void grpc_method_config_table_unref(grpc_exec_ctx* exec_ctx,
- grpc_method_config_table* table);
+grpc_method_config_table *grpc_method_config_table_ref(
+ grpc_method_config_table *table);
+void grpc_method_config_table_unref(grpc_exec_ctx *exec_ctx,
+ grpc_method_config_table *table);
/// Compares two grpc_method_config_tables.
/// The sort order is stable but undefined.
-int grpc_method_config_table_cmp(const grpc_method_config_table* table1,
- const grpc_method_config_table* table2);
+int grpc_method_config_table_cmp(const grpc_method_config_table *table1,
+ const grpc_method_config_table *table2);
/// Gets the method config for the specified \a path, which should be of
/// the form "/service/method".
/// Returns NULL if the method has no config.
/// Caller does NOT own a reference to the result.
///
-/// Note: This returns a void* instead of a grpc_method_config* so that
+/// Note: This returns a void *instead of a grpc_method_config *so that
/// it can also be used for tables constructed via
/// grpc_method_config_table_convert().
-void* grpc_method_config_table_get(grpc_exec_ctx* exec_ctx,
- const grpc_mdstr_hash_table* table,
- const grpc_mdstr* path);
+void *grpc_method_config_table_get(grpc_exec_ctx *exec_ctx,
+ const grpc_slice_hash_table *table,
+ const grpc_slice path);
/// Returns a channel arg containing \a table.
grpc_arg grpc_method_config_table_create_channel_arg(
- grpc_method_config_table* table);
+ grpc_method_config_table *table);
/// Generates a new table from \a table whose values are converted to a
/// new form via the \a convert_value function. The new table will use
@@ -131,9 +131,9 @@ grpc_arg grpc_method_config_table_create_channel_arg(
/// will return a new instance of the struct containing the values from
/// the grpc_method_config, and \a vtable provides the methods for
/// operating on the struct type.
-grpc_mdstr_hash_table* grpc_method_config_table_convert(
- grpc_exec_ctx* exec_ctx, const grpc_method_config_table* table,
- void* (*convert_value)(const grpc_method_config* method_config),
- const grpc_mdstr_hash_table_vtable* vtable);
+grpc_slice_hash_table *grpc_method_config_table_convert(
+ grpc_exec_ctx *exec_ctx, const grpc_method_config_table *table,
+ void *(*convert_value)(const grpc_method_config *method_config),
+ const grpc_slice_hash_table_vtable *vtable);
#endif /* GRPC_CORE_LIB_TRANSPORT_METHOD_CONFIG_H */
diff --git a/src/core/lib/transport/static_metadata.c b/src/core/lib/transport/static_metadata.c
index 8b22592b45..e24f3fa55e 100644
--- a/src/core/lib/transport/static_metadata.c
+++ b/src/core/lib/transport/static_metadata.c
@@ -41,7 +41,356 @@
#include "src/core/lib/transport/static_metadata.h"
-grpc_mdstr grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT];
+static uint8_t g_raw_bytes[] = {
+ 48, 49, 50, 50, 48, 48, 50, 48, 52, 50, 48, 54, 51, 48, 52,
+ 52, 48, 48, 52, 48, 52, 53, 48, 48, 97, 99, 99, 101, 112, 116,
+ 97, 99, 99, 101, 112, 116, 45, 99, 104, 97, 114, 115, 101, 116, 97,
+ 99, 99, 101, 112, 116, 45, 101, 110, 99, 111, 100, 105, 110, 103, 97,
+ 99, 99, 101, 112, 116, 45, 108, 97, 110, 103, 117, 97, 103, 101, 97,
+ 99, 99, 101, 112, 116, 45, 114, 97, 110, 103, 101, 115, 97, 99, 99,
+ 101, 115, 115, 45, 99, 111, 110, 116, 114, 111, 108, 45, 97, 108, 108,
+ 111, 119, 45, 111, 114, 105, 103, 105, 110, 97, 103, 101, 97, 108, 108,
+ 111, 119, 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 47, 103,
+ 114, 112, 99, 58, 97, 117, 116, 104, 111, 114, 105, 116, 121, 97, 117,
+ 116, 104, 111, 114, 105, 122, 97, 116, 105, 111, 110, 99, 97, 99, 104,
+ 101, 45, 99, 111, 110, 116, 114, 111, 108, 99, 111, 110, 116, 101, 110,
+ 116, 45, 100, 105, 115, 112, 111, 115, 105, 116, 105, 111, 110, 99, 111,
+ 110, 116, 101, 110, 116, 45, 101, 110, 99, 111, 100, 105, 110, 103, 99,
+ 111, 110, 116, 101, 110, 116, 45, 108, 97, 110, 103, 117, 97, 103, 101,
+ 99, 111, 110, 116, 101, 110, 116, 45, 108, 101, 110, 103, 116, 104, 99,
+ 111, 110, 116, 101, 110, 116, 45, 108, 111, 99, 97, 116, 105, 111, 110,
+ 99, 111, 110, 116, 101, 110, 116, 45, 114, 97, 110, 103, 101, 99, 111,
+ 110, 116, 101, 110, 116, 45, 116, 121, 112, 101, 99, 111, 111, 107, 105,
+ 101, 100, 97, 116, 101, 100, 101, 102, 108, 97, 116, 101, 100, 101, 102,
+ 108, 97, 116, 101, 44, 103, 122, 105, 112, 101, 116, 97, 103, 101, 120,
+ 112, 101, 99, 116, 101, 120, 112, 105, 114, 101, 115, 102, 114, 111, 109,
+ 71, 69, 84, 103, 114, 112, 99, 103, 114, 112, 99, 45, 97, 99, 99,
+ 101, 112, 116, 45, 101, 110, 99, 111, 100, 105, 110, 103, 103, 114, 112,
+ 99, 46, 109, 97, 120, 95, 114, 101, 113, 117, 101, 115, 116, 95, 109,
+ 101, 115, 115, 97, 103, 101, 95, 98, 121, 116, 101, 115, 103, 114, 112,
+ 99, 46, 109, 97, 120, 95, 114, 101, 115, 112, 111, 110, 115, 101, 95,
+ 109, 101, 115, 115, 97, 103, 101, 95, 98, 121, 116, 101, 115, 103, 114,
+ 112, 99, 46, 116, 105, 109, 101, 111, 117, 116, 103, 114, 112, 99, 46,
+ 119, 97, 105, 116, 95, 102, 111, 114, 95, 114, 101, 97, 100, 121, 103,
+ 114, 112, 99, 45, 101, 110, 99, 111, 100, 105, 110, 103, 103, 114, 112,
+ 99, 45, 105, 110, 116, 101, 114, 110, 97, 108, 45, 101, 110, 99, 111,
+ 100, 105, 110, 103, 45, 114, 101, 113, 117, 101, 115, 116, 103, 114, 112,
+ 99, 45, 109, 101, 115, 115, 97, 103, 101, 103, 114, 112, 99, 45, 112,
+ 97, 121, 108, 111, 97, 100, 45, 98, 105, 110, 103, 114, 112, 99, 45,
+ 115, 116, 97, 116, 115, 45, 98, 105, 110, 103, 114, 112, 99, 45, 115,
+ 116, 97, 116, 117, 115, 103, 114, 112, 99, 45, 116, 105, 109, 101, 111,
+ 117, 116, 103, 114, 112, 99, 45, 116, 114, 97, 99, 105, 110, 103, 45,
+ 98, 105, 110, 103, 122, 105, 112, 103, 122, 105, 112, 44, 32, 100, 101,
+ 102, 108, 97, 116, 101, 104, 111, 115, 116, 104, 116, 116, 112, 104, 116,
+ 116, 112, 115, 105, 100, 101, 110, 116, 105, 116, 121, 105, 100, 101, 110,
+ 116, 105, 116, 121, 44, 100, 101, 102, 108, 97, 116, 101, 105, 100, 101,
+ 110, 116, 105, 116, 121, 44, 100, 101, 102, 108, 97, 116, 101, 44, 103,
+ 122, 105, 112, 105, 100, 101, 110, 116, 105, 116, 121, 44, 103, 122, 105,
+ 112, 105, 102, 45, 109, 97, 116, 99, 104, 105, 102, 45, 109, 111, 100,
+ 105, 102, 105, 101, 100, 45, 115, 105, 110, 99, 101, 105, 102, 45, 110,
+ 111, 110, 101, 45, 109, 97, 116, 99, 104, 105, 102, 45, 114, 97, 110,
+ 103, 101, 105, 102, 45, 117, 110, 109, 111, 100, 105, 102, 105, 101, 100,
+ 45, 115, 105, 110, 99, 101, 108, 97, 115, 116, 45, 109, 111, 100, 105,
+ 102, 105, 101, 100, 108, 98, 45, 99, 111, 115, 116, 45, 98, 105, 110,
+ 108, 98, 45, 116, 111, 107, 101, 110, 108, 105, 110, 107, 108, 111, 99,
+ 97, 116, 105, 111, 110, 109, 97, 120, 45, 102, 111, 114, 119, 97, 114,
+ 100, 115, 58, 109, 101, 116, 104, 111, 100, 58, 112, 97, 116, 104, 80,
+ 79, 83, 84, 112, 114, 111, 120, 121, 45, 97, 117, 116, 104, 101, 110,
+ 116, 105, 99, 97, 116, 101, 112, 114, 111, 120, 121, 45, 97, 117, 116,
+ 104, 111, 114, 105, 122, 97, 116, 105, 111, 110, 80, 85, 84, 114, 97,
+ 110, 103, 101, 114, 101, 102, 101, 114, 101, 114, 114, 101, 102, 114, 101,
+ 115, 104, 114, 101, 116, 114, 121, 45, 97, 102, 116, 101, 114, 58, 115,
+ 99, 104, 101, 109, 101, 115, 101, 114, 118, 101, 114, 115, 101, 116, 45,
+ 99, 111, 111, 107, 105, 101, 47, 47, 105, 110, 100, 101, 120, 46, 104,
+ 116, 109, 108, 58, 115, 116, 97, 116, 117, 115, 115, 116, 114, 105, 99,
+ 116, 45, 116, 114, 97, 110, 115, 112, 111, 114, 116, 45, 115, 101, 99,
+ 117, 114, 105, 116, 121, 116, 101, 116, 114, 97, 105, 108, 101, 114, 115,
+ 116, 114, 97, 110, 115, 102, 101, 114, 45, 101, 110, 99, 111, 100, 105,
+ 110, 103, 117, 115, 101, 114, 45, 97, 103, 101, 110, 116, 118, 97, 114,
+ 121, 118, 105, 97, 119, 119, 119, 45, 97, 117, 116, 104, 101, 110, 116,
+ 105, 99, 97, 116, 101};
+
+static void static_ref(void *unused) {}
+static void static_unref(grpc_exec_ctx *exec_ctx, void *unused) {}
+static grpc_slice_refcount g_refcnt = {static_ref, static_unref};
+
+bool grpc_is_static_metadata_string(grpc_slice slice) {
+ return slice.refcount != NULL && slice.refcount->ref == static_ref;
+};
+
+const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT] = {
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 0, .length = 1}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 1, .length = 1}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 2, .length = 1}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 3, .length = 3}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 6, .length = 3}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 9, .length = 3}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 12, .length = 3}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 15, .length = 3}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 18, .length = 3}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 21, .length = 3}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 24, .length = 6}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 30, .length = 14}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 44, .length = 15}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 59, .length = 15}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 74, .length = 13}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 87, .length = 27}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 114, .length = 3}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 117, .length = 5}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 122, .length = 16}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 138, .length = 10}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 148, .length = 13}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 161, .length = 13}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 174, .length = 19}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 193, .length = 16}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 209, .length = 16}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 225, .length = 14}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 239, .length = 16}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 255, .length = 13}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 268, .length = 12}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 280, .length = 6}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 286, .length = 4}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 290, .length = 7}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 297, .length = 12}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 309, .length = 0}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 309, .length = 4}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 313, .length = 6}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 319, .length = 7}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 326, .length = 4}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 330, .length = 3}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 333, .length = 4}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 337, .length = 20}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 357, .length = 30}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 387, .length = 31}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 418, .length = 12}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 430, .length = 19}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 449, .length = 13}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 462, .length = 30}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 492, .length = 12}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 504, .length = 16}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 520, .length = 14}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 534, .length = 11}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 545, .length = 12}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 557, .length = 16}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 573, .length = 4}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 577, .length = 13}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 590, .length = 4}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 594, .length = 4}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 598, .length = 5}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 603, .length = 8}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 611, .length = 16}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 627, .length = 21}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 648, .length = 13}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 661, .length = 8}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 669, .length = 17}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 686, .length = 13}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 699, .length = 8}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 707, .length = 19}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 726, .length = 13}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 739, .length = 11}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 750, .length = 8}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 758, .length = 4}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 762, .length = 8}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 770, .length = 12}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 782, .length = 7}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 789, .length = 5}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 794, .length = 4}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 798, .length = 18}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 816, .length = 19}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 835, .length = 3}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 838, .length = 5}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 843, .length = 7}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 850, .length = 7}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 857, .length = 11}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 868, .length = 7}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 875, .length = 6}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 881, .length = 10}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 891, .length = 1}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 892, .length = 11}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 903, .length = 7}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 910, .length = 25}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 935, .length = 2}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 937, .length = 8}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 945, .length = 17}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 962, .length = 10}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 972, .length = 4}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 976, .length = 3}},
+ {.refcount = &g_refcnt,
+ .data.refcounted = {.bytes = g_raw_bytes + 979, .length = 16}},
+};
+
+static const uint8_t g_revmap[] = {
+ 0, 1, 2, 3, 255, 255, 4, 255, 255, 5, 255, 255, 6, 255, 255,
+ 7, 255, 255, 8, 255, 255, 9, 255, 255, 10, 255, 255, 255, 255, 255,
+ 11, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 12,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 13,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 14,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 15, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 16, 255, 255, 17, 255, 255,
+ 255, 255, 18, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 19, 255, 255, 255, 255, 255, 255, 255, 255, 255, 20, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 21, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 22, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 23, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 24,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 25, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 26,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 27, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 28, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 29, 255, 255, 255, 255,
+ 255, 30, 255, 255, 255, 31, 255, 255, 255, 255, 255, 255, 32, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 34, 255, 255, 255, 35, 255,
+ 255, 255, 255, 255, 36, 255, 255, 255, 255, 255, 255, 37, 255, 255, 255,
+ 38, 255, 255, 39, 255, 255, 255, 40, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 41, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 42, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 43, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 44, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 45,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 46, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 47, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 48, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 49, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 50, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 52, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 53, 255, 255, 255, 54, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 55, 255, 255, 255, 56, 255, 255, 255, 57, 255,
+ 255, 255, 255, 58, 255, 255, 255, 255, 255, 255, 255, 59, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 60, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 61, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 62, 255, 255, 255, 255, 255, 255, 255, 63, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 64, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 65, 255, 255, 255, 255, 255,
+ 255, 255, 66, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 67, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 68, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 69, 255, 255, 255, 255, 255, 255, 255, 70, 255, 255, 255, 71, 255, 255,
+ 255, 255, 255, 255, 255, 72, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 73, 255, 255, 255, 255, 255, 255, 74, 255, 255, 255, 255, 75,
+ 255, 255, 255, 76, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 77, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 78, 255, 255, 79, 255,
+ 255, 255, 255, 80, 255, 255, 255, 255, 255, 255, 81, 255, 255, 255, 255,
+ 255, 255, 82, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 83, 255,
+ 255, 255, 255, 255, 255, 84, 255, 255, 255, 255, 255, 85, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 86, 87, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 88, 255, 255, 255, 255, 255, 255, 89, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 90, 255, 91, 255, 255, 255, 255, 255, 255, 255,
+ 92, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 93, 255, 255, 255, 255, 255, 255, 255, 255, 255, 94, 255, 255,
+ 255, 95, 255, 255, 96, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255};
+
+int grpc_static_metadata_index(grpc_slice slice) {
+ if (GRPC_SLICE_LENGTH(slice) == 0) return 33;
+ size_t ofs = (size_t)(GRPC_SLICE_START_PTR(slice) - g_raw_bytes);
+ if (ofs > sizeof(g_revmap)) return -1;
+ uint8_t id = g_revmap[ofs];
+ return id == 255 ? -1 : id;
+};
grpc_mdelem grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];
uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT] = {
@@ -50,111 +399,65 @@ uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+#define ELEMS_PHASHLEN 0x40
+#define ELEMS_PHASHNKEYS 81
+#define ELEMS_PHASHRANGE 128
+#define ELEMS_PHASHSALT 0x9e3779b9
+
+static const uint8_t elems_tab[] = {
+ 47, 1, 61, 0, 32, 0, 47, 1, 37, 0, 0, 0, 47, 61, 76, 0,
+ 76, 0, 61, 0, 32, 37, 51, 0, 47, 47, 79, 4, 76, 1, 0, 0,
+ 0, 76, 0, 47, 85, 34, 0, 10, 0, 28, 0, 76, 0, 61, 0, 0,
+ 46, 4, 12, 47, 88, 28, 61, 79, 28, 70, 0, 68, 85, 0, 87, 0,
+};
+
+static uint32_t elems_phash(uint32_t val) {
+ val -= 1003;
+
+ uint32_t a, b, rsl;
+
+ b = (val & 0x3f);
+ a = ((val << 18) >> 26);
+ rsl = (a ^ elems_tab[b]);
+ return rsl;
+}
+
+static const uint16_t elem_keys[] = {
+ 1218, 8544, 2652, 1973, 7264, 2458, 2734, 3933, 1682, 6435, 3912, 3941,
+ 4396, 4418, 4850, 4852, 7890, 8541, 6726, 9345, 6338, 6629, 6920, 3939,
+ 7156, 8540, 8108, 8090, 8181, 8666, 8821, 1876, 8545, 1391, 8957, 1488,
+ 7405, 7265, 3331, 2943, 2846, 6241, 4851, 2167, 5368, 1585, 1294, 1003,
+ 9054, 6144, 8542, 8539, 8107, 7793, 7502, 7159, 7696, 2264, 6532, 2749,
+ 9248, 1197, 7987, 9151, 7017, 4423, 7119, 6823, 3938, 8543, 3525, 3911,
+ 2070, 2361, 2555, 6047, 1100, 3940, 3622, 3428, 8278, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0};
+static const uint8_t elem_idxs[] = {
+ 3, 72, 17, 10, 54, 15, 18, 28, 8, 44, 27, 32, 33, 34, 36, 38, 60,
+ 69, 47, 80, 43, 46, 49, 30, 52, 68, 64, 62, 65, 74, 75, 9, 73, 5,
+ 76, 6, 56, 55, 22, 21, 20, 42, 37, 12, 39, 7, 4, 1, 77, 41, 70,
+ 67, 63, 59, 57, 53, 58, 13, 45, 19, 79, 2, 61, 78, 50, 35, 51, 48,
+ 29, 71, 24, 26, 11, 14, 16, 40, 0, 31, 25, 23, 66};
+
+grpc_mdelem *grpc_static_mdelem_for_static_strings(int a, int b) {
+ if (a == -1 || b == -1) return NULL;
+ uint32_t k = (uint32_t)(a * 97 + b);
+ uint32_t h = elems_phash(k);
+ return elem_keys[h] == k ? &grpc_static_mdelem_table[elem_idxs[h]] : NULL;
+}
+
const uint8_t grpc_static_metadata_elem_indices[GRPC_STATIC_MDELEM_COUNT * 2] =
- {11, 33, 10, 33, 12, 33, 12, 50, 13, 33, 14, 33, 15, 33, 16, 33, 17, 33,
+ {11, 33, 10, 33, 12, 33, 12, 54, 13, 33, 14, 33, 15, 33, 16, 33, 17, 33,
19, 33, 20, 33, 21, 33, 22, 33, 23, 33, 24, 33, 25, 33, 26, 33, 27, 33,
28, 18, 28, 33, 29, 33, 30, 33, 34, 33, 35, 33, 36, 33, 37, 33, 40, 31,
- 40, 32, 40, 49, 40, 54, 40, 55, 40, 56, 40, 57, 41, 31, 41, 49, 41, 54,
- 46, 0, 46, 1, 46, 2, 51, 33, 58, 33, 59, 33, 60, 33, 61, 33, 62, 33,
- 63, 33, 64, 33, 65, 33, 66, 33, 67, 33, 68, 33, 69, 38, 69, 71, 69, 74,
- 70, 82, 70, 83, 72, 33, 73, 33, 75, 33, 76, 33, 77, 33, 78, 33, 79, 39,
- 79, 52, 79, 53, 80, 33, 81, 33, 84, 3, 84, 4, 84, 5, 84, 6, 84, 7,
- 84, 8, 84, 9, 85, 33, 86, 87, 88, 33, 89, 33, 90, 33, 91, 33, 92, 33};
-
-const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT] = {
- "0",
- "1",
- "2",
- "200",
- "204",
- "206",
- "304",
- "400",
- "404",
- "500",
- "accept",
- "accept-charset",
- "accept-encoding",
- "accept-language",
- "accept-ranges",
- "access-control-allow-origin",
- "age",
- "allow",
- "application/grpc",
- ":authority",
- "authorization",
- "cache-control",
- "content-disposition",
- "content-encoding",
- "content-language",
- "content-length",
- "content-location",
- "content-range",
- "content-type",
- "cookie",
- "date",
- "deflate",
- "deflate,gzip",
- "",
- "etag",
- "expect",
- "expires",
- "from",
- "GET",
- "grpc",
- "grpc-accept-encoding",
- "grpc-encoding",
- "grpc-internal-encoding-request",
- "grpc-message",
- "grpc-payload-bin",
- "grpc-stats-bin",
- "grpc-status",
- "grpc-timeout",
- "grpc-tracing-bin",
- "gzip",
- "gzip, deflate",
- "host",
- "http",
- "https",
- "identity",
- "identity,deflate",
- "identity,deflate,gzip",
- "identity,gzip",
- "if-match",
- "if-modified-since",
- "if-none-match",
- "if-range",
- "if-unmodified-since",
- "last-modified",
- "lb-cost-bin",
- "lb-token",
- "link",
- "location",
- "max-forwards",
- ":method",
- ":path",
- "POST",
- "proxy-authenticate",
- "proxy-authorization",
- "PUT",
- "range",
- "referer",
- "refresh",
- "retry-after",
- ":scheme",
- "server",
- "set-cookie",
- "/",
- "/index.html",
- ":status",
- "strict-transport-security",
- "te",
- "trailers",
- "transfer-encoding",
- "user-agent",
- "vary",
- "via",
- "www-authenticate"};
+ 40, 32, 40, 53, 40, 58, 40, 59, 40, 60, 40, 61, 45, 31, 45, 53, 45, 58,
+ 50, 0, 50, 1, 50, 2, 55, 33, 62, 33, 63, 33, 64, 33, 65, 33, 66, 33,
+ 67, 33, 68, 33, 69, 33, 70, 33, 71, 33, 72, 33, 73, 38, 73, 75, 73, 78,
+ 74, 86, 74, 87, 76, 33, 77, 33, 79, 33, 80, 33, 81, 33, 82, 33, 83, 39,
+ 83, 56, 83, 57, 84, 33, 85, 33, 88, 3, 88, 4, 88, 5, 88, 6, 88, 7,
+ 88, 8, 88, 9, 89, 33, 90, 91, 92, 33, 93, 33, 94, 33, 95, 33, 96, 33};
const uint8_t grpc_static_accept_encoding_metadata[8] = {0, 29, 26, 30,
28, 32, 27, 31};
diff --git a/src/core/lib/transport/static_metadata.h b/src/core/lib/transport/static_metadata.h
index 28ad6f2961..c6348a5280 100644
--- a/src/core/lib/transport/static_metadata.h
+++ b/src/core/lib/transport/static_metadata.h
@@ -44,195 +44,207 @@
#include "src/core/lib/transport/metadata.h"
-#define GRPC_STATIC_MDSTR_COUNT 93
-extern grpc_mdstr grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT];
+#define GRPC_STATIC_MDSTR_COUNT 97
+extern const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT];
/* "0" */
-#define GRPC_MDSTR_0 (&grpc_static_mdstr_table[0])
+#define GRPC_MDSTR_0 (grpc_static_slice_table[0])
/* "1" */
-#define GRPC_MDSTR_1 (&grpc_static_mdstr_table[1])
+#define GRPC_MDSTR_1 (grpc_static_slice_table[1])
/* "2" */
-#define GRPC_MDSTR_2 (&grpc_static_mdstr_table[2])
+#define GRPC_MDSTR_2 (grpc_static_slice_table[2])
/* "200" */
-#define GRPC_MDSTR_200 (&grpc_static_mdstr_table[3])
+#define GRPC_MDSTR_200 (grpc_static_slice_table[3])
/* "204" */
-#define GRPC_MDSTR_204 (&grpc_static_mdstr_table[4])
+#define GRPC_MDSTR_204 (grpc_static_slice_table[4])
/* "206" */
-#define GRPC_MDSTR_206 (&grpc_static_mdstr_table[5])
+#define GRPC_MDSTR_206 (grpc_static_slice_table[5])
/* "304" */
-#define GRPC_MDSTR_304 (&grpc_static_mdstr_table[6])
+#define GRPC_MDSTR_304 (grpc_static_slice_table[6])
/* "400" */
-#define GRPC_MDSTR_400 (&grpc_static_mdstr_table[7])
+#define GRPC_MDSTR_400 (grpc_static_slice_table[7])
/* "404" */
-#define GRPC_MDSTR_404 (&grpc_static_mdstr_table[8])
+#define GRPC_MDSTR_404 (grpc_static_slice_table[8])
/* "500" */
-#define GRPC_MDSTR_500 (&grpc_static_mdstr_table[9])
+#define GRPC_MDSTR_500 (grpc_static_slice_table[9])
/* "accept" */
-#define GRPC_MDSTR_ACCEPT (&grpc_static_mdstr_table[10])
+#define GRPC_MDSTR_ACCEPT (grpc_static_slice_table[10])
/* "accept-charset" */
-#define GRPC_MDSTR_ACCEPT_CHARSET (&grpc_static_mdstr_table[11])
+#define GRPC_MDSTR_ACCEPT_CHARSET (grpc_static_slice_table[11])
/* "accept-encoding" */
-#define GRPC_MDSTR_ACCEPT_ENCODING (&grpc_static_mdstr_table[12])
+#define GRPC_MDSTR_ACCEPT_ENCODING (grpc_static_slice_table[12])
/* "accept-language" */
-#define GRPC_MDSTR_ACCEPT_LANGUAGE (&grpc_static_mdstr_table[13])
+#define GRPC_MDSTR_ACCEPT_LANGUAGE (grpc_static_slice_table[13])
/* "accept-ranges" */
-#define GRPC_MDSTR_ACCEPT_RANGES (&grpc_static_mdstr_table[14])
+#define GRPC_MDSTR_ACCEPT_RANGES (grpc_static_slice_table[14])
/* "access-control-allow-origin" */
-#define GRPC_MDSTR_ACCESS_CONTROL_ALLOW_ORIGIN (&grpc_static_mdstr_table[15])
+#define GRPC_MDSTR_ACCESS_CONTROL_ALLOW_ORIGIN (grpc_static_slice_table[15])
/* "age" */
-#define GRPC_MDSTR_AGE (&grpc_static_mdstr_table[16])
+#define GRPC_MDSTR_AGE (grpc_static_slice_table[16])
/* "allow" */
-#define GRPC_MDSTR_ALLOW (&grpc_static_mdstr_table[17])
+#define GRPC_MDSTR_ALLOW (grpc_static_slice_table[17])
/* "application/grpc" */
-#define GRPC_MDSTR_APPLICATION_SLASH_GRPC (&grpc_static_mdstr_table[18])
+#define GRPC_MDSTR_APPLICATION_SLASH_GRPC (grpc_static_slice_table[18])
/* ":authority" */
-#define GRPC_MDSTR_AUTHORITY (&grpc_static_mdstr_table[19])
+#define GRPC_MDSTR_AUTHORITY (grpc_static_slice_table[19])
/* "authorization" */
-#define GRPC_MDSTR_AUTHORIZATION (&grpc_static_mdstr_table[20])
+#define GRPC_MDSTR_AUTHORIZATION (grpc_static_slice_table[20])
/* "cache-control" */
-#define GRPC_MDSTR_CACHE_CONTROL (&grpc_static_mdstr_table[21])
+#define GRPC_MDSTR_CACHE_CONTROL (grpc_static_slice_table[21])
/* "content-disposition" */
-#define GRPC_MDSTR_CONTENT_DISPOSITION (&grpc_static_mdstr_table[22])
+#define GRPC_MDSTR_CONTENT_DISPOSITION (grpc_static_slice_table[22])
/* "content-encoding" */
-#define GRPC_MDSTR_CONTENT_ENCODING (&grpc_static_mdstr_table[23])
+#define GRPC_MDSTR_CONTENT_ENCODING (grpc_static_slice_table[23])
/* "content-language" */
-#define GRPC_MDSTR_CONTENT_LANGUAGE (&grpc_static_mdstr_table[24])
+#define GRPC_MDSTR_CONTENT_LANGUAGE (grpc_static_slice_table[24])
/* "content-length" */
-#define GRPC_MDSTR_CONTENT_LENGTH (&grpc_static_mdstr_table[25])
+#define GRPC_MDSTR_CONTENT_LENGTH (grpc_static_slice_table[25])
/* "content-location" */
-#define GRPC_MDSTR_CONTENT_LOCATION (&grpc_static_mdstr_table[26])
+#define GRPC_MDSTR_CONTENT_LOCATION (grpc_static_slice_table[26])
/* "content-range" */
-#define GRPC_MDSTR_CONTENT_RANGE (&grpc_static_mdstr_table[27])
+#define GRPC_MDSTR_CONTENT_RANGE (grpc_static_slice_table[27])
/* "content-type" */
-#define GRPC_MDSTR_CONTENT_TYPE (&grpc_static_mdstr_table[28])
+#define GRPC_MDSTR_CONTENT_TYPE (grpc_static_slice_table[28])
/* "cookie" */
-#define GRPC_MDSTR_COOKIE (&grpc_static_mdstr_table[29])
+#define GRPC_MDSTR_COOKIE (grpc_static_slice_table[29])
/* "date" */
-#define GRPC_MDSTR_DATE (&grpc_static_mdstr_table[30])
+#define GRPC_MDSTR_DATE (grpc_static_slice_table[30])
/* "deflate" */
-#define GRPC_MDSTR_DEFLATE (&grpc_static_mdstr_table[31])
+#define GRPC_MDSTR_DEFLATE (grpc_static_slice_table[31])
/* "deflate,gzip" */
-#define GRPC_MDSTR_DEFLATE_COMMA_GZIP (&grpc_static_mdstr_table[32])
+#define GRPC_MDSTR_DEFLATE_COMMA_GZIP (grpc_static_slice_table[32])
/* "" */
-#define GRPC_MDSTR_EMPTY (&grpc_static_mdstr_table[33])
+#define GRPC_MDSTR_EMPTY (grpc_static_slice_table[33])
/* "etag" */
-#define GRPC_MDSTR_ETAG (&grpc_static_mdstr_table[34])
+#define GRPC_MDSTR_ETAG (grpc_static_slice_table[34])
/* "expect" */
-#define GRPC_MDSTR_EXPECT (&grpc_static_mdstr_table[35])
+#define GRPC_MDSTR_EXPECT (grpc_static_slice_table[35])
/* "expires" */
-#define GRPC_MDSTR_EXPIRES (&grpc_static_mdstr_table[36])
+#define GRPC_MDSTR_EXPIRES (grpc_static_slice_table[36])
/* "from" */
-#define GRPC_MDSTR_FROM (&grpc_static_mdstr_table[37])
+#define GRPC_MDSTR_FROM (grpc_static_slice_table[37])
/* "GET" */
-#define GRPC_MDSTR_GET (&grpc_static_mdstr_table[38])
+#define GRPC_MDSTR_GET (grpc_static_slice_table[38])
/* "grpc" */
-#define GRPC_MDSTR_GRPC (&grpc_static_mdstr_table[39])
+#define GRPC_MDSTR_GRPC (grpc_static_slice_table[39])
/* "grpc-accept-encoding" */
-#define GRPC_MDSTR_GRPC_ACCEPT_ENCODING (&grpc_static_mdstr_table[40])
+#define GRPC_MDSTR_GRPC_ACCEPT_ENCODING (grpc_static_slice_table[40])
+/* "grpc.max_request_message_bytes" */
+#define GRPC_MDSTR_GRPC_DOT_MAX_REQUEST_MESSAGE_BYTES \
+ (grpc_static_slice_table[41])
+/* "grpc.max_response_message_bytes" */
+#define GRPC_MDSTR_GRPC_DOT_MAX_RESPONSE_MESSAGE_BYTES \
+ (grpc_static_slice_table[42])
+/* "grpc.timeout" */
+#define GRPC_MDSTR_GRPC_DOT_TIMEOUT (grpc_static_slice_table[43])
+/* "grpc.wait_for_ready" */
+#define GRPC_MDSTR_GRPC_DOT_WAIT_FOR_READY (grpc_static_slice_table[44])
/* "grpc-encoding" */
-#define GRPC_MDSTR_GRPC_ENCODING (&grpc_static_mdstr_table[41])
+#define GRPC_MDSTR_GRPC_ENCODING (grpc_static_slice_table[45])
/* "grpc-internal-encoding-request" */
-#define GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST (&grpc_static_mdstr_table[42])
+#define GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST (grpc_static_slice_table[46])
/* "grpc-message" */
-#define GRPC_MDSTR_GRPC_MESSAGE (&grpc_static_mdstr_table[43])
+#define GRPC_MDSTR_GRPC_MESSAGE (grpc_static_slice_table[47])
/* "grpc-payload-bin" */
-#define GRPC_MDSTR_GRPC_PAYLOAD_BIN (&grpc_static_mdstr_table[44])
+#define GRPC_MDSTR_GRPC_PAYLOAD_BIN (grpc_static_slice_table[48])
/* "grpc-stats-bin" */
-#define GRPC_MDSTR_GRPC_STATS_BIN (&grpc_static_mdstr_table[45])
+#define GRPC_MDSTR_GRPC_STATS_BIN (grpc_static_slice_table[49])
/* "grpc-status" */
-#define GRPC_MDSTR_GRPC_STATUS (&grpc_static_mdstr_table[46])
+#define GRPC_MDSTR_GRPC_STATUS (grpc_static_slice_table[50])
/* "grpc-timeout" */
-#define GRPC_MDSTR_GRPC_TIMEOUT (&grpc_static_mdstr_table[47])
+#define GRPC_MDSTR_GRPC_TIMEOUT (grpc_static_slice_table[51])
/* "grpc-tracing-bin" */
-#define GRPC_MDSTR_GRPC_TRACING_BIN (&grpc_static_mdstr_table[48])
+#define GRPC_MDSTR_GRPC_TRACING_BIN (grpc_static_slice_table[52])
/* "gzip" */
-#define GRPC_MDSTR_GZIP (&grpc_static_mdstr_table[49])
+#define GRPC_MDSTR_GZIP (grpc_static_slice_table[53])
/* "gzip, deflate" */
-#define GRPC_MDSTR_GZIP_COMMA_DEFLATE (&grpc_static_mdstr_table[50])
+#define GRPC_MDSTR_GZIP_COMMA_DEFLATE (grpc_static_slice_table[54])
/* "host" */
-#define GRPC_MDSTR_HOST (&grpc_static_mdstr_table[51])
+#define GRPC_MDSTR_HOST (grpc_static_slice_table[55])
/* "http" */
-#define GRPC_MDSTR_HTTP (&grpc_static_mdstr_table[52])
+#define GRPC_MDSTR_HTTP (grpc_static_slice_table[56])
/* "https" */
-#define GRPC_MDSTR_HTTPS (&grpc_static_mdstr_table[53])
+#define GRPC_MDSTR_HTTPS (grpc_static_slice_table[57])
/* "identity" */
-#define GRPC_MDSTR_IDENTITY (&grpc_static_mdstr_table[54])
+#define GRPC_MDSTR_IDENTITY (grpc_static_slice_table[58])
/* "identity,deflate" */
-#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE (&grpc_static_mdstr_table[55])
+#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE (grpc_static_slice_table[59])
/* "identity,deflate,gzip" */
#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \
- (&grpc_static_mdstr_table[56])
+ (grpc_static_slice_table[60])
/* "identity,gzip" */
-#define GRPC_MDSTR_IDENTITY_COMMA_GZIP (&grpc_static_mdstr_table[57])
+#define GRPC_MDSTR_IDENTITY_COMMA_GZIP (grpc_static_slice_table[61])
/* "if-match" */
-#define GRPC_MDSTR_IF_MATCH (&grpc_static_mdstr_table[58])
+#define GRPC_MDSTR_IF_MATCH (grpc_static_slice_table[62])
/* "if-modified-since" */
-#define GRPC_MDSTR_IF_MODIFIED_SINCE (&grpc_static_mdstr_table[59])
+#define GRPC_MDSTR_IF_MODIFIED_SINCE (grpc_static_slice_table[63])
/* "if-none-match" */
-#define GRPC_MDSTR_IF_NONE_MATCH (&grpc_static_mdstr_table[60])
+#define GRPC_MDSTR_IF_NONE_MATCH (grpc_static_slice_table[64])
/* "if-range" */
-#define GRPC_MDSTR_IF_RANGE (&grpc_static_mdstr_table[61])
+#define GRPC_MDSTR_IF_RANGE (grpc_static_slice_table[65])
/* "if-unmodified-since" */
-#define GRPC_MDSTR_IF_UNMODIFIED_SINCE (&grpc_static_mdstr_table[62])
+#define GRPC_MDSTR_IF_UNMODIFIED_SINCE (grpc_static_slice_table[66])
/* "last-modified" */
-#define GRPC_MDSTR_LAST_MODIFIED (&grpc_static_mdstr_table[63])
+#define GRPC_MDSTR_LAST_MODIFIED (grpc_static_slice_table[67])
/* "lb-cost-bin" */
-#define GRPC_MDSTR_LB_COST_BIN (&grpc_static_mdstr_table[64])
+#define GRPC_MDSTR_LB_COST_BIN (grpc_static_slice_table[68])
/* "lb-token" */
-#define GRPC_MDSTR_LB_TOKEN (&grpc_static_mdstr_table[65])
+#define GRPC_MDSTR_LB_TOKEN (grpc_static_slice_table[69])
/* "link" */
-#define GRPC_MDSTR_LINK (&grpc_static_mdstr_table[66])
+#define GRPC_MDSTR_LINK (grpc_static_slice_table[70])
/* "location" */
-#define GRPC_MDSTR_LOCATION (&grpc_static_mdstr_table[67])
+#define GRPC_MDSTR_LOCATION (grpc_static_slice_table[71])
/* "max-forwards" */
-#define GRPC_MDSTR_MAX_FORWARDS (&grpc_static_mdstr_table[68])
+#define GRPC_MDSTR_MAX_FORWARDS (grpc_static_slice_table[72])
/* ":method" */
-#define GRPC_MDSTR_METHOD (&grpc_static_mdstr_table[69])
+#define GRPC_MDSTR_METHOD (grpc_static_slice_table[73])
/* ":path" */
-#define GRPC_MDSTR_PATH (&grpc_static_mdstr_table[70])
+#define GRPC_MDSTR_PATH (grpc_static_slice_table[74])
/* "POST" */
-#define GRPC_MDSTR_POST (&grpc_static_mdstr_table[71])
+#define GRPC_MDSTR_POST (grpc_static_slice_table[75])
/* "proxy-authenticate" */
-#define GRPC_MDSTR_PROXY_AUTHENTICATE (&grpc_static_mdstr_table[72])
+#define GRPC_MDSTR_PROXY_AUTHENTICATE (grpc_static_slice_table[76])
/* "proxy-authorization" */
-#define GRPC_MDSTR_PROXY_AUTHORIZATION (&grpc_static_mdstr_table[73])
+#define GRPC_MDSTR_PROXY_AUTHORIZATION (grpc_static_slice_table[77])
/* "PUT" */
-#define GRPC_MDSTR_PUT (&grpc_static_mdstr_table[74])
+#define GRPC_MDSTR_PUT (grpc_static_slice_table[78])
/* "range" */
-#define GRPC_MDSTR_RANGE (&grpc_static_mdstr_table[75])
+#define GRPC_MDSTR_RANGE (grpc_static_slice_table[79])
/* "referer" */
-#define GRPC_MDSTR_REFERER (&grpc_static_mdstr_table[76])
+#define GRPC_MDSTR_REFERER (grpc_static_slice_table[80])
/* "refresh" */
-#define GRPC_MDSTR_REFRESH (&grpc_static_mdstr_table[77])
+#define GRPC_MDSTR_REFRESH (grpc_static_slice_table[81])
/* "retry-after" */
-#define GRPC_MDSTR_RETRY_AFTER (&grpc_static_mdstr_table[78])
+#define GRPC_MDSTR_RETRY_AFTER (grpc_static_slice_table[82])
/* ":scheme" */
-#define GRPC_MDSTR_SCHEME (&grpc_static_mdstr_table[79])
+#define GRPC_MDSTR_SCHEME (grpc_static_slice_table[83])
/* "server" */
-#define GRPC_MDSTR_SERVER (&grpc_static_mdstr_table[80])
+#define GRPC_MDSTR_SERVER (grpc_static_slice_table[84])
/* "set-cookie" */
-#define GRPC_MDSTR_SET_COOKIE (&grpc_static_mdstr_table[81])
+#define GRPC_MDSTR_SET_COOKIE (grpc_static_slice_table[85])
/* "/" */
-#define GRPC_MDSTR_SLASH (&grpc_static_mdstr_table[82])
+#define GRPC_MDSTR_SLASH (grpc_static_slice_table[86])
/* "/index.html" */
-#define GRPC_MDSTR_SLASH_INDEX_DOT_HTML (&grpc_static_mdstr_table[83])
+#define GRPC_MDSTR_SLASH_INDEX_DOT_HTML (grpc_static_slice_table[87])
/* ":status" */
-#define GRPC_MDSTR_STATUS (&grpc_static_mdstr_table[84])
+#define GRPC_MDSTR_STATUS (grpc_static_slice_table[88])
/* "strict-transport-security" */
-#define GRPC_MDSTR_STRICT_TRANSPORT_SECURITY (&grpc_static_mdstr_table[85])
+#define GRPC_MDSTR_STRICT_TRANSPORT_SECURITY (grpc_static_slice_table[89])
/* "te" */
-#define GRPC_MDSTR_TE (&grpc_static_mdstr_table[86])
+#define GRPC_MDSTR_TE (grpc_static_slice_table[90])
/* "trailers" */
-#define GRPC_MDSTR_TRAILERS (&grpc_static_mdstr_table[87])
+#define GRPC_MDSTR_TRAILERS (grpc_static_slice_table[91])
/* "transfer-encoding" */
-#define GRPC_MDSTR_TRANSFER_ENCODING (&grpc_static_mdstr_table[88])
+#define GRPC_MDSTR_TRANSFER_ENCODING (grpc_static_slice_table[92])
/* "user-agent" */
-#define GRPC_MDSTR_USER_AGENT (&grpc_static_mdstr_table[89])
+#define GRPC_MDSTR_USER_AGENT (grpc_static_slice_table[93])
/* "vary" */
-#define GRPC_MDSTR_VARY (&grpc_static_mdstr_table[90])
+#define GRPC_MDSTR_VARY (grpc_static_slice_table[94])
/* "via" */
-#define GRPC_MDSTR_VIA (&grpc_static_mdstr_table[91])
+#define GRPC_MDSTR_VIA (grpc_static_slice_table[95])
/* "www-authenticate" */
-#define GRPC_MDSTR_WWW_AUTHENTICATE (&grpc_static_mdstr_table[92])
+#define GRPC_MDSTR_WWW_AUTHENTICATE (grpc_static_slice_table[96])
+
+bool grpc_is_static_metadata_string(grpc_slice slice);
#define GRPC_STATIC_MDELEM_COUNT 81
extern grpc_mdelem grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];
@@ -409,9 +421,9 @@ extern uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT];
/* "www-authenticate": "" */
#define GRPC_MDELEM_WWW_AUTHENTICATE_EMPTY (&grpc_static_mdelem_table[80])
+grpc_mdelem *grpc_static_mdelem_for_static_strings(int a, int b);
extern const uint8_t
grpc_static_metadata_elem_indices[GRPC_STATIC_MDELEM_COUNT * 2];
-extern const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT];
extern const uint8_t grpc_static_accept_encoding_metadata[8];
#define GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(algs) \
(&grpc_static_mdelem_table[grpc_static_accept_encoding_metadata[(algs)]])
diff --git a/src/core/lib/transport/transport_op_string.c b/src/core/lib/transport/transport_op_string.c
index 58d6ad508e..deb155e659 100644
--- a/src/core/lib/transport/transport_op_string.c
+++ b/src/core/lib/transport/transport_op_string.c
@@ -49,12 +49,10 @@
static void put_metadata(gpr_strvec *b, grpc_mdelem *md) {
gpr_strvec_add(b, gpr_strdup("key="));
- gpr_strvec_add(
- b, grpc_dump_slice(md->key->slice, GPR_DUMP_HEX | GPR_DUMP_ASCII));
+ gpr_strvec_add(b, grpc_dump_slice(md->key, GPR_DUMP_HEX | GPR_DUMP_ASCII));
gpr_strvec_add(b, gpr_strdup(" value="));
- gpr_strvec_add(
- b, grpc_dump_slice(md->value->slice, GPR_DUMP_HEX | GPR_DUMP_ASCII));
+ gpr_strvec_add(b, grpc_dump_slice(md->value, GPR_DUMP_HEX | GPR_DUMP_ASCII));
}
static void put_metadata_list(gpr_strvec *b, grpc_metadata_batch md) {
diff --git a/src/cpp/util/slice_cc.cc b/src/cpp/util/slice_cc.cc
index c05f1cf124..6efb68e123 100644
--- a/src/cpp/util/slice_cc.cc
+++ b/src/cpp/util/slice_cc.cc
@@ -35,7 +35,7 @@
namespace grpc {
-Slice::Slice() : slice_(gpr_empty_slice()) {}
+Slice::Slice() : slice_(grpc_empty_slice()) {}
Slice::~Slice() { grpc_slice_unref(slice_); }
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index 3ca4d07f35..e53ed72c1b 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -157,6 +157,7 @@ CORE_SOURCE_FILES = [
'src/core/lib/slice/percent_encoding.c',
'src/core/lib/slice/slice.c',
'src/core/lib/slice/slice_buffer.c',
+ 'src/core/lib/slice/slice_hash_table.c',
'src/core/lib/slice/slice_intern.c',
'src/core/lib/slice/slice_string_helpers.c',
'src/core/lib/surface/alarm.c',
@@ -179,7 +180,6 @@ CORE_SOURCE_FILES = [
'src/core/lib/surface/version.c',
'src/core/lib/transport/byte_stream.c',
'src/core/lib/transport/connectivity_state.c',
- 'src/core/lib/transport/mdstr_hash_table.c',
'src/core/lib/transport/metadata.c',
'src/core/lib/transport/metadata_batch.c',
'src/core/lib/transport/method_config.c',
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
index bc411250a2..665903e22c 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
@@ -130,8 +130,11 @@ grpc_server_cancel_all_calls_type grpc_server_cancel_all_calls_import;
grpc_server_destroy_type grpc_server_destroy_import;
grpc_tracer_set_enabled_type grpc_tracer_set_enabled_import;
grpc_header_key_is_legal_type grpc_header_key_is_legal_import;
+grpc_header_key_slice_is_legal_type grpc_header_key_slice_is_legal_import;
grpc_header_nonbin_value_is_legal_type grpc_header_nonbin_value_is_legal_import;
+grpc_header_nonbin_value_slice_is_legal_type grpc_header_nonbin_value_slice_is_legal_import;
grpc_is_binary_header_type grpc_is_binary_header_import;
+grpc_slice_is_binary_header_type grpc_slice_is_binary_header_import;
grpc_call_error_to_string_type grpc_call_error_to_string_import;
grpc_resource_quota_create_type grpc_resource_quota_create_import;
grpc_resource_quota_ref_type grpc_resource_quota_ref_import;
@@ -187,9 +190,13 @@ grpc_slice_sub_type grpc_slice_sub_import;
grpc_slice_sub_no_ref_type grpc_slice_sub_no_ref_import;
grpc_slice_split_tail_type grpc_slice_split_tail_import;
grpc_slice_split_head_type grpc_slice_split_head_import;
-gpr_empty_slice_type gpr_empty_slice_import;
+grpc_empty_slice_type grpc_empty_slice_import;
grpc_slice_cmp_type grpc_slice_cmp_import;
grpc_slice_str_cmp_type grpc_slice_str_cmp_import;
+grpc_slice_buf_cmp_type grpc_slice_buf_cmp_import;
+grpc_slice_buf_start_eq_type grpc_slice_buf_start_eq_import;
+grpc_slice_rchr_type grpc_slice_rchr_import;
+grpc_slice_hash_type grpc_slice_hash_import;
grpc_slice_is_equivalent_type grpc_slice_is_equivalent_import;
grpc_slice_buffer_init_type grpc_slice_buffer_init_import;
grpc_slice_buffer_destroy_type grpc_slice_buffer_destroy_import;
@@ -407,8 +414,11 @@ void grpc_rb_load_imports(HMODULE library) {
grpc_server_destroy_import = (grpc_server_destroy_type) GetProcAddress(library, "grpc_server_destroy");
grpc_tracer_set_enabled_import = (grpc_tracer_set_enabled_type) GetProcAddress(library, "grpc_tracer_set_enabled");
grpc_header_key_is_legal_import = (grpc_header_key_is_legal_type) GetProcAddress(library, "grpc_header_key_is_legal");
+ grpc_header_key_slice_is_legal_import = (grpc_header_key_slice_is_legal_type) GetProcAddress(library, "grpc_header_key_slice_is_legal");
grpc_header_nonbin_value_is_legal_import = (grpc_header_nonbin_value_is_legal_type) GetProcAddress(library, "grpc_header_nonbin_value_is_legal");
+ grpc_header_nonbin_value_slice_is_legal_import = (grpc_header_nonbin_value_slice_is_legal_type) GetProcAddress(library, "grpc_header_nonbin_value_slice_is_legal");
grpc_is_binary_header_import = (grpc_is_binary_header_type) GetProcAddress(library, "grpc_is_binary_header");
+ grpc_slice_is_binary_header_import = (grpc_slice_is_binary_header_type) GetProcAddress(library, "grpc_slice_is_binary_header");
grpc_call_error_to_string_import = (grpc_call_error_to_string_type) GetProcAddress(library, "grpc_call_error_to_string");
grpc_resource_quota_create_import = (grpc_resource_quota_create_type) GetProcAddress(library, "grpc_resource_quota_create");
grpc_resource_quota_ref_import = (grpc_resource_quota_ref_type) GetProcAddress(library, "grpc_resource_quota_ref");
@@ -464,9 +474,13 @@ void grpc_rb_load_imports(HMODULE library) {
grpc_slice_sub_no_ref_import = (grpc_slice_sub_no_ref_type) GetProcAddress(library, "grpc_slice_sub_no_ref");
grpc_slice_split_tail_import = (grpc_slice_split_tail_type) GetProcAddress(library, "grpc_slice_split_tail");
grpc_slice_split_head_import = (grpc_slice_split_head_type) GetProcAddress(library, "grpc_slice_split_head");
- gpr_empty_slice_import = (gpr_empty_slice_type) GetProcAddress(library, "gpr_empty_slice");
+ grpc_empty_slice_import = (grpc_empty_slice_type) GetProcAddress(library, "grpc_empty_slice");
grpc_slice_cmp_import = (grpc_slice_cmp_type) GetProcAddress(library, "grpc_slice_cmp");
grpc_slice_str_cmp_import = (grpc_slice_str_cmp_type) GetProcAddress(library, "grpc_slice_str_cmp");
+ grpc_slice_buf_cmp_import = (grpc_slice_buf_cmp_type) GetProcAddress(library, "grpc_slice_buf_cmp");
+ grpc_slice_buf_start_eq_import = (grpc_slice_buf_start_eq_type) GetProcAddress(library, "grpc_slice_buf_start_eq");
+ grpc_slice_rchr_import = (grpc_slice_rchr_type) GetProcAddress(library, "grpc_slice_rchr");
+ grpc_slice_hash_import = (grpc_slice_hash_type) GetProcAddress(library, "grpc_slice_hash");
grpc_slice_is_equivalent_import = (grpc_slice_is_equivalent_type) GetProcAddress(library, "grpc_slice_is_equivalent");
grpc_slice_buffer_init_import = (grpc_slice_buffer_init_type) GetProcAddress(library, "grpc_slice_buffer_init");
grpc_slice_buffer_destroy_import = (grpc_slice_buffer_destroy_type) GetProcAddress(library, "grpc_slice_buffer_destroy");
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
index 17b625c6f5..14d5835201 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
@@ -176,7 +176,7 @@ extern census_resource_id_type census_resource_id_import;
typedef void(*census_record_values_type)(census_context *context, census_value *values, size_t nvalues);
extern census_record_values_type census_record_values_import;
#define census_record_values census_record_values_import
-typedef int(*grpc_compression_algorithm_parse_type)(const char *name, size_t name_length, grpc_compression_algorithm *algorithm);
+typedef int(*grpc_compression_algorithm_parse_type)(grpc_slice value, grpc_compression_algorithm *algorithm);
extern grpc_compression_algorithm_parse_type grpc_compression_algorithm_parse_import;
#define grpc_compression_algorithm_parse grpc_compression_algorithm_parse_import
typedef int(*grpc_compression_algorithm_name_type)(grpc_compression_algorithm algorithm, char **name);
@@ -254,7 +254,7 @@ extern grpc_channel_check_connectivity_state_type grpc_channel_check_connectivit
typedef void(*grpc_channel_watch_connectivity_state_type)(grpc_channel *channel, grpc_connectivity_state last_observed_state, gpr_timespec deadline, grpc_completion_queue *cq, void *tag);
extern grpc_channel_watch_connectivity_state_type grpc_channel_watch_connectivity_state_import;
#define grpc_channel_watch_connectivity_state grpc_channel_watch_connectivity_state_import
-typedef grpc_call *(*grpc_channel_create_call_type)(grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask, grpc_completion_queue *completion_queue, const char *method, const char *host, gpr_timespec deadline, void *reserved);
+typedef grpc_call *(*grpc_channel_create_call_type)(grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask, grpc_completion_queue *completion_queue, grpc_slice method, const grpc_slice *host, gpr_timespec deadline, void *reserved);
extern grpc_channel_create_call_type grpc_channel_create_call_import;
#define grpc_channel_create_call grpc_channel_create_call_import
typedef void(*grpc_channel_ping_type)(grpc_channel *channel, grpc_completion_queue *cq, void *tag, void *reserved);
@@ -341,12 +341,21 @@ extern grpc_tracer_set_enabled_type grpc_tracer_set_enabled_import;
typedef int(*grpc_header_key_is_legal_type)(const char *key, size_t length);
extern grpc_header_key_is_legal_type grpc_header_key_is_legal_import;
#define grpc_header_key_is_legal grpc_header_key_is_legal_import
+typedef int(*grpc_header_key_slice_is_legal_type)(grpc_slice slice);
+extern grpc_header_key_slice_is_legal_type grpc_header_key_slice_is_legal_import;
+#define grpc_header_key_slice_is_legal grpc_header_key_slice_is_legal_import
typedef int(*grpc_header_nonbin_value_is_legal_type)(const char *value, size_t length);
extern grpc_header_nonbin_value_is_legal_type grpc_header_nonbin_value_is_legal_import;
#define grpc_header_nonbin_value_is_legal grpc_header_nonbin_value_is_legal_import
+typedef int(*grpc_header_nonbin_value_slice_is_legal_type)(grpc_slice slice);
+extern grpc_header_nonbin_value_slice_is_legal_type grpc_header_nonbin_value_slice_is_legal_import;
+#define grpc_header_nonbin_value_slice_is_legal grpc_header_nonbin_value_slice_is_legal_import
typedef int(*grpc_is_binary_header_type)(const char *key, size_t length);
extern grpc_is_binary_header_type grpc_is_binary_header_import;
#define grpc_is_binary_header grpc_is_binary_header_import
+typedef int(*grpc_slice_is_binary_header_type)(grpc_slice slice);
+extern grpc_slice_is_binary_header_type grpc_slice_is_binary_header_import;
+#define grpc_slice_is_binary_header grpc_slice_is_binary_header_import
typedef const char *(*grpc_call_error_to_string_type)(grpc_call_error error);
extern grpc_call_error_to_string_type grpc_call_error_to_string_import;
#define grpc_call_error_to_string grpc_call_error_to_string_import
@@ -512,15 +521,27 @@ extern grpc_slice_split_tail_type grpc_slice_split_tail_import;
typedef grpc_slice(*grpc_slice_split_head_type)(grpc_slice *s, size_t split);
extern grpc_slice_split_head_type grpc_slice_split_head_import;
#define grpc_slice_split_head grpc_slice_split_head_import
-typedef grpc_slice(*gpr_empty_slice_type)(void);
-extern gpr_empty_slice_type gpr_empty_slice_import;
-#define gpr_empty_slice gpr_empty_slice_import
+typedef grpc_slice(*grpc_empty_slice_type)(void);
+extern grpc_empty_slice_type grpc_empty_slice_import;
+#define grpc_empty_slice grpc_empty_slice_import
typedef int(*grpc_slice_cmp_type)(grpc_slice a, grpc_slice b);
extern grpc_slice_cmp_type grpc_slice_cmp_import;
#define grpc_slice_cmp grpc_slice_cmp_import
typedef int(*grpc_slice_str_cmp_type)(grpc_slice a, const char *b);
extern grpc_slice_str_cmp_type grpc_slice_str_cmp_import;
#define grpc_slice_str_cmp grpc_slice_str_cmp_import
+typedef int(*grpc_slice_buf_cmp_type)(grpc_slice a, const void *b, size_t blen);
+extern grpc_slice_buf_cmp_type grpc_slice_buf_cmp_import;
+#define grpc_slice_buf_cmp grpc_slice_buf_cmp_import
+typedef int(*grpc_slice_buf_start_eq_type)(grpc_slice a, const void *b, size_t blen);
+extern grpc_slice_buf_start_eq_type grpc_slice_buf_start_eq_import;
+#define grpc_slice_buf_start_eq grpc_slice_buf_start_eq_import
+typedef int(*grpc_slice_rchr_type)(grpc_slice s, char c);
+extern grpc_slice_rchr_type grpc_slice_rchr_import;
+#define grpc_slice_rchr grpc_slice_rchr_import
+typedef uint32_t(*grpc_slice_hash_type)(grpc_slice s);
+extern grpc_slice_hash_type grpc_slice_hash_import;
+#define grpc_slice_hash grpc_slice_hash_import
typedef int(*grpc_slice_is_equivalent_type)(grpc_slice a, grpc_slice b);
extern grpc_slice_is_equivalent_type grpc_slice_is_equivalent_import;
#define grpc_slice_is_equivalent grpc_slice_is_equivalent_import
diff --git a/test/core/compression/algorithm_test.c b/test/core/compression/algorithm_test.c
index ff17667b94..4b85489044 100644
--- a/test/core/compression/algorithm_test.c
+++ b/test/core/compression/algorithm_test.c
@@ -59,8 +59,8 @@ static void test_algorithm_mesh(void) {
GPR_ASSERT(grpc_compression_algorithm_parse(name, strlen(name), &parsed));
GPR_ASSERT((int)parsed == i);
mdstr = grpc_mdstr_from_string(name);
- GPR_ASSERT(mdstr == grpc_compression_algorithm_mdstr(parsed));
- GPR_ASSERT(parsed == grpc_compression_algorithm_from_mdstr(mdstr));
+ GPR_ASSERT(mdstr == grpc_compression_algorithm_slice(parsed));
+ GPR_ASSERT(parsed == grpc_compression_algorithm_from_slice(mdstr));
mdelem = grpc_compression_encoding_mdelem(parsed);
GPR_ASSERT(mdelem->value == mdstr);
GPR_ASSERT(mdelem->key == GRPC_MDSTR_GRPC_ENCODING);
@@ -85,11 +85,11 @@ static void test_algorithm_failure(void) {
GPR_ASSERT(grpc_compression_algorithm_name(GRPC_COMPRESS_ALGORITHMS_COUNT + 1,
NULL) == 0);
mdstr = grpc_mdstr_from_string("this-is-an-invalid-algorithm");
- GPR_ASSERT(grpc_compression_algorithm_from_mdstr(mdstr) ==
+ GPR_ASSERT(grpc_compression_algorithm_from_slice(mdstr) ==
GRPC_COMPRESS_ALGORITHMS_COUNT);
- GPR_ASSERT(grpc_compression_algorithm_mdstr(GRPC_COMPRESS_ALGORITHMS_COUNT) ==
+ GPR_ASSERT(grpc_compression_algorithm_slice(GRPC_COMPRESS_ALGORITHMS_COUNT) ==
NULL);
- GPR_ASSERT(grpc_compression_algorithm_mdstr(GRPC_COMPRESS_ALGORITHMS_COUNT +
+ GPR_ASSERT(grpc_compression_algorithm_slice(GRPC_COMPRESS_ALGORITHMS_COUNT +
1) == NULL);
GRPC_MDSTR_UNREF(&exec_ctx, mdstr);
grpc_exec_ctx_finish(&exec_ctx);
diff --git a/test/core/end2end/cq_verifier.c b/test/core/end2end/cq_verifier.c
index 57373970c4..925c59e696 100644
--- a/test/core/end2end/cq_verifier.c
+++ b/test/core/end2end/cq_verifier.c
@@ -92,8 +92,8 @@ static int has_metadata(const grpc_metadata *md, size_t count, const char *key,
const char *value) {
size_t i;
for (i = 0; i < count; i++) {
- if (0 == strcmp(key, md[i].key) && strlen(value) == md[i].value_length &&
- 0 == memcmp(md[i].value, value, md[i].value_length)) {
+ if (0 == grpc_slice_str_cmp(md[i].key, key) &&
+ 0 == grpc_slice_str_cmp(md[i].value, value)) {
return 1;
}
}
@@ -105,6 +105,23 @@ int contains_metadata(grpc_metadata_array *array, const char *key,
return has_metadata(array->metadata, array->count, key, value);
}
+static int has_metadata_slices(const grpc_metadata *md, size_t count,
+ grpc_slice key, grpc_slice value) {
+ size_t i;
+ for (i = 0; i < count; i++) {
+ if (0 == grpc_slice_cmp(md[i].key, key) &&
+ 0 == grpc_slice_cmp(md[i].value, value)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int contains_metadata_slices(grpc_metadata_array *array, grpc_slice key,
+ grpc_slice value) {
+ return has_metadata_slices(array->metadata, array->count, key, value);
+}
+
static grpc_slice merge_slices(grpc_slice *slices, size_t nslices) {
size_t i;
size_t len = 0;
diff --git a/test/core/end2end/cq_verifier.h b/test/core/end2end/cq_verifier.h
index b754de9bbe..035aa270e4 100644
--- a/test/core/end2end/cq_verifier.h
+++ b/test/core/end2end/cq_verifier.h
@@ -71,5 +71,7 @@ int byte_buffer_eq_slice(grpc_byte_buffer *bb, grpc_slice b);
int byte_buffer_eq_string(grpc_byte_buffer *byte_buffer, const char *string);
int contains_metadata(grpc_metadata_array *array, const char *key,
const char *value);
+int contains_metadata_slices(grpc_metadata_array *array, grpc_slice key,
+ grpc_slice value);
#endif /* GRPC_TEST_CORE_END2END_CQ_VERIFIER_H */
diff --git a/test/core/end2end/end2end_test_utils.c b/test/core/end2end/end2end_test_utils.c
index 46fb4ec1af..8783d8451b 100644
--- a/test/core/end2end/end2end_test_utils.c
+++ b/test/core/end2end/end2end_test_utils.c
@@ -39,13 +39,27 @@
const char *get_host_override_string(const char *str,
grpc_end2end_test_config config) {
- return (config.feature_mask & FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER ? str
- : NULL);
+ if (config.feature_mask & FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER) {
+ return str;
+ } else {
+ return NULL;
+ }
+}
+
+const grpc_slice *get_host_override_slice(const char *str,
+ grpc_end2end_test_config config) {
+ const char *r = get_host_override_string(str, config);
+ if (r != NULL) {
+ static grpc_slice ret;
+ ret = grpc_slice_from_static_string(r);
+ return &ret;
+ }
+ return NULL;
}
-void validate_host_override_string(const char *pattern, const char *str,
+void validate_host_override_string(const char *pattern, grpc_slice str,
grpc_end2end_test_config config) {
if (config.feature_mask & FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER) {
- GPR_ASSERT(0 == strcmp(str, pattern));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(str, pattern));
}
}
diff --git a/test/core/end2end/end2end_tests.h b/test/core/end2end/end2end_tests.h
index f25e90b5f6..cb0afd9cd9 100644
--- a/test/core/end2end/end2end_tests.h
+++ b/test/core/end2end/end2end_tests.h
@@ -72,8 +72,12 @@ void grpc_end2end_tests(int argc, char **argv, grpc_end2end_test_config config);
const char *get_host_override_string(const char *str,
grpc_end2end_test_config config);
+/* Returns a pointer to a statically allocated slice: future invocations
+ overwrite past invocations, not threadsafe, etc... */
+const grpc_slice *get_host_override_slice(const char *str,
+ grpc_end2end_test_config config);
-void validate_host_override_string(const char *pattern, const char *str,
+void validate_host_override_string(const char *pattern, grpc_slice str,
grpc_end2end_test_config config);
#endif /* GRPC_TEST_CORE_END2END_END2END_TESTS_H */
diff --git a/test/core/end2end/fixtures/proxy.c b/test/core/end2end/fixtures/proxy.c
index beed80df81..d014893742 100644
--- a/test/core/end2end/fixtures/proxy.c
+++ b/test/core/end2end/fixtures/proxy.c
@@ -80,8 +80,7 @@ typedef struct {
grpc_metadata_array p2s_trailing_metadata;
grpc_status_code p2s_status;
- char *p2s_status_details;
- size_t p2s_status_details_capacity;
+ grpc_slice p2s_status_details;
int c2p_server_cancelled;
} proxy_call;
@@ -153,7 +152,7 @@ static void unrefpc(proxy_call *pc, const char *reason) {
grpc_metadata_array_destroy(&pc->c2p_initial_metadata);
grpc_metadata_array_destroy(&pc->p2s_initial_metadata);
grpc_metadata_array_destroy(&pc->p2s_trailing_metadata);
- gpr_free(pc->p2s_status_details);
+ grpc_slice_unref(pc->p2s_status_details);
gpr_free(pc);
}
}
@@ -309,7 +308,6 @@ static void on_p2s_status(void *arg, int success) {
op.data.send_status_from_server.trailing_metadata =
pc->p2s_trailing_metadata.metadata;
op.data.send_status_from_server.status = pc->p2s_status;
- op.data.send_status_from_server.status_details = pc->p2s_status_details;
refpc(pc, "on_c2p_sent_status");
err = grpc_call_start_batch(pc->c2p, &op, 1,
new_closure(on_c2p_sent_status, pc), NULL);
@@ -339,7 +337,7 @@ static void on_new_call(void *arg, int success) {
pc->c2p = proxy->new_call;
pc->p2s = grpc_channel_create_call(
proxy->client, pc->c2p, GRPC_PROPAGATE_DEFAULTS, proxy->cq,
- proxy->new_call_details.method, proxy->new_call_details.host,
+ proxy->new_call_details.method, &proxy->new_call_details.host,
proxy->new_call_details.deadline, NULL);
gpr_ref_init(&pc->refs, 1);
@@ -384,8 +382,6 @@ static void on_new_call(void *arg, int success) {
&pc->p2s_trailing_metadata;
op.data.recv_status_on_client.status = &pc->p2s_status;
op.data.recv_status_on_client.status_details = &pc->p2s_status_details;
- op.data.recv_status_on_client.status_details_capacity =
- &pc->p2s_status_details_capacity;
refpc(pc, "on_p2s_status");
err = grpc_call_start_batch(pc->p2s, &op, 1, new_closure(on_p2s_status, pc),
NULL);
diff --git a/test/core/end2end/fuzzers/hpack.dictionary b/test/core/end2end/fuzzers/hpack.dictionary
index 12db0ff024..7563482609 100644
--- a/test/core/end2end/fuzzers/hpack.dictionary
+++ b/test/core/end2end/fuzzers/hpack.dictionary
@@ -40,6 +40,10 @@
"\x03GET"
"\x04grpc"
"\x14grpc-accept-encoding"
+"\x1Egrpc.max_request_message_bytes"
+"\x1Fgrpc.max_response_message_bytes"
+"\x0Cgrpc.timeout"
+"\x13grpc.wait_for_ready"
"\x0Dgrpc-encoding"
"\x1Egrpc-internal-encoding-request"
"\x0Cgrpc-message"
diff --git a/test/core/end2end/tests/authority_not_supported.c b/test/core/end2end/tests/authority_not_supported.c
index 705970f6ca..40d217e619 100644
--- a/test/core/end2end/tests/authority_not_supported.c
+++ b/test/core/end2end/tests/authority_not_supported.c
@@ -103,9 +103,14 @@ static void test_with_authority_header(grpc_end2end_test_config config) {
grpc_byte_buffer *request_payload =
grpc_raw_byte_buffer_create(&request_payload_slice, 1);
gpr_timespec deadline = five_seconds_time();
- grpc_metadata meta_c[2] = {
- {"key1", "val1", 4, 0, {{NULL, NULL, NULL, NULL}}},
- {"key2", "val2", 4, 0, {{NULL, NULL, NULL, NULL}}}};
+ grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"),
+ grpc_slice_from_static_string("val1"),
+ 0,
+ {{NULL, NULL, NULL, NULL}}},
+ {grpc_slice_from_static_string("key2"),
+ grpc_slice_from_static_string("val2"),
+ 0,
+ {{NULL, NULL, NULL, NULL}}}};
grpc_end2end_test_fixture f =
begin_test(config, "test_with_authority_header", NULL, NULL);
cq_verifier *cqv = cq_verifier_create(f.cq);
@@ -116,11 +121,12 @@ static void test_with_authority_header(grpc_end2end_test_config config) {
grpc_byte_buffer *response_payload_recv = NULL;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
+ grpc_slice host = grpc_slice_from_static_string("foo.test.google.fr");
c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
- "/foo", "foo.test.google.fr", deadline, NULL);
+ grpc_slice_from_static_string("/foo"), &host,
+ deadline, NULL);
GPR_ASSERT(c);
grpc_metadata_array_init(&initial_metadata_recv);
@@ -157,7 +163,6 @@ static void test_with_authority_header(grpc_end2end_test_config config) {
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -169,7 +174,7 @@ static void test_with_authority_header(grpc_end2end_test_config config) {
GPR_ASSERT(status == GRPC_STATUS_CANCELLED);
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
diff --git a/test/core/end2end/tests/bad_hostname.c b/test/core/end2end/tests/bad_hostname.c
index e0c7ac7c02..f18abc78f0 100644
--- a/test/core/end2end/tests/bad_hostname.c
+++ b/test/core/end2end/tests/bad_hostname.c
@@ -109,11 +109,12 @@ static void simple_request_body(grpc_end2end_test_fixture f) {
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
+ grpc_slice host = grpc_slice_from_static_string("slartibartfast.local");
c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
- "/foo", "slartibartfast.local", deadline, NULL);
+ grpc_slice_from_static_string("/foo"), &host,
+ deadline, NULL);
GPR_ASSERT(c);
grpc_metadata_array_init(&initial_metadata_recv);
@@ -141,7 +142,6 @@ static void simple_request_body(grpc_end2end_test_fixture f) {
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -153,7 +153,7 @@ static void simple_request_body(grpc_end2end_test_fixture f) {
GPR_ASSERT(status == GRPC_STATUS_INTERNAL);
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/binary_metadata.c b/test/core/end2end/tests/binary_metadata.c
index dd7a8a9ad3..004cc9e2af 100644
--- a/test/core/end2end/tests/binary_metadata.c
+++ b/test/core/end2end/tests/binary_metadata.c
@@ -110,25 +110,25 @@ static void test_request_response_with_metadata_and_payload(
grpc_raw_byte_buffer_create(&response_payload_slice, 1);
gpr_timespec deadline = five_seconds_time();
grpc_metadata meta_c[2] = {
- {"key1-bin",
- "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc",
- 13,
+ {grpc_slice_from_static_string("key1-bin"),
+ grpc_slice_from_static_string(
+ "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc"),
0,
{{NULL, NULL, NULL, NULL}}},
- {"key2-bin",
- "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d",
- 14,
+ {grpc_slice_from_static_string("key2-bin"),
+ grpc_slice_from_static_string(
+ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d"),
0,
{{NULL, NULL, NULL, NULL}}}};
grpc_metadata meta_s[2] = {
- {"key3-bin",
- "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee",
- 15,
+ {grpc_slice_from_static_string("key3-bin"),
+ grpc_slice_from_static_string(
+ "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee"),
0,
{{NULL, NULL, NULL, NULL}}},
- {"key4-bin",
- "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
- 16,
+ {grpc_slice_from_static_string("key4-bin"),
+ grpc_slice_from_static_string(
+ "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"),
0,
{{NULL, NULL, NULL, NULL}}}};
grpc_end2end_test_fixture f = begin_test(
@@ -144,13 +144,13 @@ static void test_request_response_with_metadata_and_payload(
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -190,7 +190,6 @@ static void test_request_response_with_metadata_and_payload(
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -238,7 +237,7 @@ static void test_request_response_with_metadata_and_payload(
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_OK;
- op->data.send_status_from_server.status_details =
+ grpc_slice status_string = grpc_slice_from_static_string(
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12"
"\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24"
"\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36"
@@ -253,7 +252,8 @@ static void test_request_response_with_metadata_and_payload(
"\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8"
"\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea"
"\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc"
- "\xfd\xfe\xff";
+ "\xfd\xfe\xff");
+ op->data.send_status_from_server.status_details = &status_string;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -267,24 +267,25 @@ static void test_request_response_with_metadata_and_payload(
GPR_ASSERT(status == GRPC_STATUS_OK);
GPR_ASSERT(
0 ==
- strcmp(details,
- "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
- "\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"
- "\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30"
- "\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"
- "\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50"
- "\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60"
- "\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70"
- "\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80"
- "\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90"
- "\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0"
- "\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0"
- "\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0"
- "\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0"
- "\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0"
- "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0"
- "\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"));
- GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+ grpc_slice_str_cmp(
+ details,
+ "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
+ "\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"
+ "\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30"
+ "\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"
+ "\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50"
+ "\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60"
+ "\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70"
+ "\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80"
+ "\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90"
+ "\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0"
+ "\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0"
+ "\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0"
+ "\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0"
+ "\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0"
+ "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0"
+ "\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
validate_host_override_string("foo.test.google.fr:1234", call_details.host,
config);
GPR_ASSERT(was_cancelled == 0);
@@ -303,7 +304,7 @@ static void test_request_response_with_metadata_and_payload(
&initial_metadata_recv, "key4-bin",
"\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"));
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/call_creds.c b/test/core/end2end/tests/call_creds.c
index 606938fff6..ebc854606b 100644
--- a/test/core/end2end/tests/call_creds.c
+++ b/test/core/end2end/tests/call_creds.c
@@ -156,8 +156,7 @@ static void request_response_with_payload_and_call_creds(
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
grpc_call_credentials *creds = NULL;
grpc_auth_context *s_auth_context = NULL;
@@ -167,8 +166,9 @@ static void request_response_with_payload_and_call_creds(
cqv = cq_verifier_create(f.cq);
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
creds = grpc_google_iam_credentials_create(iam_token, iam_selector, NULL);
@@ -225,7 +225,6 @@ static void request_response_with_payload_and_call_creds(
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -284,7 +283,8 @@ static void request_response_with_payload_and_call_creds(
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_OK;
- op->data.send_status_from_server.status_details = "xyz";
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_details;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -296,8 +296,8 @@ static void request_response_with_payload_and_call_creds(
cq_verify(cqv);
GPR_ASSERT(status == GRPC_STATUS_OK);
- GPR_ASSERT(0 == strcmp(details, "xyz"));
- GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
validate_host_override_string("foo.test.google.fr:1234", call_details.host,
config);
GPR_ASSERT(was_cancelled == 0);
@@ -337,7 +337,7 @@ static void request_response_with_payload_and_call_creds(
break;
}
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
@@ -391,8 +391,7 @@ static void test_request_with_server_rejecting_client_creds(
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
grpc_byte_buffer *response_payload_recv = NULL;
grpc_slice request_payload_slice =
grpc_slice_from_copied_string("hello world");
@@ -404,8 +403,9 @@ static void test_request_with_server_rejecting_client_creds(
cqv = cq_verifier_create(f.cq);
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -425,7 +425,6 @@ static void test_request_with_server_rejecting_client_creds(
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -468,7 +467,7 @@ static void test_request_with_server_rejecting_client_creds(
grpc_byte_buffer_destroy(request_payload);
grpc_byte_buffer_destroy(response_payload_recv);
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_call_destroy(c);
diff --git a/test/core/end2end/tests/cancel_after_accept.c b/test/core/end2end/tests/cancel_after_accept.c
index c0beb456ad..a2301d725c 100644
--- a/test/core/end2end/tests/cancel_after_accept.c
+++ b/test/core/end2end/tests/cancel_after_accept.c
@@ -43,6 +43,7 @@
#include <grpc/support/useful.h>
#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/transport/metadata.h"
#include "src/core/lib/transport/method_config.h"
@@ -118,8 +119,7 @@ static void test_cancel_after_accept(grpc_end2end_test_config config,
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
grpc_byte_buffer *request_payload_recv = NULL;
grpc_byte_buffer *response_payload_recv = NULL;
grpc_slice request_payload_slice =
@@ -136,13 +136,13 @@ static void test_cancel_after_accept(grpc_end2end_test_config config,
if (use_service_config) {
gpr_timespec timeout = {5, 0, GPR_TIMESPAN};
grpc_method_config_table_entry entry = {
- grpc_mdstr_from_string("/service/method"),
+ grpc_slice_from_static_string("/service/method"),
grpc_method_config_create(NULL, &timeout, NULL, NULL),
};
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_method_config_table *method_config_table =
grpc_method_config_table_create(1, &entry);
- GRPC_MDSTR_UNREF(&exec_ctx, entry.method_name);
+ grpc_slice_unref_internal(&exec_ctx, entry.method_name);
grpc_method_config_unref(&exec_ctx, entry.method_config);
grpc_arg arg =
grpc_method_config_table_create_channel_arg(method_config_table);
@@ -156,8 +156,9 @@ static void test_cancel_after_accept(grpc_end2end_test_config config,
cq_verifier *cqv = cq_verifier_create(f.cq);
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/service/method",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/service/method"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -172,7 +173,6 @@ static void test_cancel_after_accept(grpc_end2end_test_config config,
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -248,7 +248,7 @@ static void test_cancel_after_accept(grpc_end2end_test_config config,
grpc_byte_buffer_destroy(response_payload);
grpc_byte_buffer_destroy(request_payload_recv);
grpc_byte_buffer_destroy(response_payload_recv);
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_call_destroy(c);
grpc_call_destroy(s);
diff --git a/test/core/end2end/tests/cancel_after_client_done.c b/test/core/end2end/tests/cancel_after_client_done.c
index 7742f9d179..63b8150cb6 100644
--- a/test/core/end2end/tests/cancel_after_client_done.c
+++ b/test/core/end2end/tests/cancel_after_client_done.c
@@ -113,8 +113,7 @@ static void test_cancel_after_accept_and_writes_closed(
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
grpc_byte_buffer *request_payload_recv = NULL;
grpc_byte_buffer *response_payload_recv = NULL;
grpc_slice request_payload_slice =
@@ -128,8 +127,9 @@ static void test_cancel_after_accept_and_writes_closed(
int was_cancelled = 2;
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -144,7 +144,6 @@ static void test_cancel_after_accept_and_writes_closed(
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -224,7 +223,7 @@ static void test_cancel_after_accept_and_writes_closed(
grpc_byte_buffer_destroy(response_payload);
grpc_byte_buffer_destroy(request_payload_recv);
grpc_byte_buffer_destroy(response_payload_recv);
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_call_destroy(c);
grpc_call_destroy(s);
diff --git a/test/core/end2end/tests/cancel_after_invoke.c b/test/core/end2end/tests/cancel_after_invoke.c
index c3c5418f20..216c363760 100644
--- a/test/core/end2end/tests/cancel_after_invoke.c
+++ b/test/core/end2end/tests/cancel_after_invoke.c
@@ -113,8 +113,7 @@ static void test_cancel_after_invoke(grpc_end2end_test_config config,
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
grpc_byte_buffer *response_payload_recv = NULL;
grpc_slice request_payload_slice =
grpc_slice_from_copied_string("hello world");
@@ -122,8 +121,9 @@ static void test_cancel_after_invoke(grpc_end2end_test_config config,
grpc_raw_byte_buffer_create(&request_payload_slice, 1);
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -138,7 +138,6 @@ static void test_cancel_after_invoke(grpc_end2end_test_config config,
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -183,7 +182,7 @@ static void test_cancel_after_invoke(grpc_end2end_test_config config,
grpc_byte_buffer_destroy(request_payload);
grpc_byte_buffer_destroy(response_payload_recv);
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_call_destroy(c);
diff --git a/test/core/end2end/tests/cancel_before_invoke.c b/test/core/end2end/tests/cancel_before_invoke.c
index d4842829c0..c198fd1713 100644
--- a/test/core/end2end/tests/cancel_before_invoke.c
+++ b/test/core/end2end/tests/cancel_before_invoke.c
@@ -111,8 +111,7 @@ static void test_cancel_before_invoke(grpc_end2end_test_config config,
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
grpc_byte_buffer *response_payload_recv = NULL;
grpc_slice request_payload_slice =
grpc_slice_from_copied_string("hello world");
@@ -120,8 +119,9 @@ static void test_cancel_before_invoke(grpc_end2end_test_config config,
grpc_raw_byte_buffer_create(&request_payload_slice, 1);
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -138,7 +138,6 @@ static void test_cancel_before_invoke(grpc_end2end_test_config config,
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -181,7 +180,7 @@ static void test_cancel_before_invoke(grpc_end2end_test_config config,
grpc_byte_buffer_destroy(request_payload);
grpc_byte_buffer_destroy(response_payload_recv);
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_call_destroy(c);
diff --git a/test/core/end2end/tests/cancel_in_a_vacuum.c b/test/core/end2end/tests/cancel_in_a_vacuum.c
index 5be850b6ea..af919805c7 100644
--- a/test/core/end2end/tests/cancel_in_a_vacuum.c
+++ b/test/core/end2end/tests/cancel_in_a_vacuum.c
@@ -106,8 +106,9 @@ static void test_cancel_in_a_vacuum(grpc_end2end_test_config config,
cq_verifier *v_client = cq_verifier_create(f.cq);
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
diff --git a/test/core/end2end/tests/cancel_with_status.c b/test/core/end2end/tests/cancel_with_status.c
index 3aecaf7159..38f8c612d1 100644
--- a/test/core/end2end/tests/cancel_with_status.c
+++ b/test/core/end2end/tests/cancel_with_status.c
@@ -108,14 +108,14 @@ static void simple_request_body(grpc_end2end_test_config config,
grpc_metadata_array trailing_metadata_recv;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
gpr_log(GPR_DEBUG, "test with %" PRIuPTR " ops", num_ops);
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -128,7 +128,6 @@ static void simple_request_body(grpc_end2end_test_config config,
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -156,9 +155,9 @@ static void simple_request_body(grpc_end2end_test_config config,
cq_verify(cqv);
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
- GPR_ASSERT(0 == strcmp(details, "xyz"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
diff --git a/test/core/end2end/tests/compressed_payload.c b/test/core/end2end/tests/compressed_payload.c
index d7efe7747b..847bc1a8c9 100644
--- a/test/core/end2end/tests/compressed_payload.c
+++ b/test/core/end2end/tests/compressed_payload.c
@@ -48,6 +48,7 @@
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/surface/call.h"
#include "src/core/lib/surface/call_test_only.h"
+#include "src/core/lib/transport/static_metadata.h"
#include "test/core/end2end/cq_verifier.h"
static void *tag(intptr_t t) { return (void *)t; }
@@ -125,8 +126,7 @@ static void request_for_disabled_algorithm(
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
cq_verifier *cqv;
char str[1024];
@@ -151,8 +151,9 @@ static void request_for_disabled_algorithm(
cqv = cq_verifier_create(f.cq);
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -191,7 +192,6 @@ static void request_for_disabled_algorithm(
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -245,13 +245,13 @@ static void request_for_disabled_algorithm(
gpr_asprintf(&expected_details, "Compression algorithm '%s' is disabled.",
algo_name);
/* and we expect a specific reason for it */
- GPR_ASSERT(0 == strcmp(details, expected_details));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(details, expected_details));
gpr_free(expected_details);
- GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
validate_host_override_string("foo.test.google.fr:1234", call_details.host,
config);
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
@@ -305,8 +305,7 @@ static void request_with_payload_template(
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
cq_verifier *cqv;
char request_str[1024];
@@ -331,8 +330,9 @@ static void request_with_payload_template(
cqv = cq_verifier_create(f.cq);
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -362,7 +362,6 @@ static void request_with_payload_template(
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -489,7 +488,8 @@ static void request_with_payload_template(
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_OK;
- op->data.send_status_from_server.status_details = "xyz";
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_details;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -503,13 +503,13 @@ static void request_with_payload_template(
cq_verify(cqv);
GPR_ASSERT(status == GRPC_STATUS_OK);
- GPR_ASSERT(0 == strcmp(details, "xyz"));
- GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
validate_host_override_string("foo.test.google.fr:1234", call_details.host,
config);
GPR_ASSERT(was_cancelled == 0);
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
@@ -569,17 +569,14 @@ static void test_invoke_request_with_compressed_payload_md_override(
grpc_metadata gzip_compression_override;
grpc_metadata identity_compression_override;
- gzip_compression_override.key = GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY;
- gzip_compression_override.value = "gzip";
- gzip_compression_override.value_length =
- strlen(gzip_compression_override.value);
+ gzip_compression_override.key = GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST;
+ gzip_compression_override.value = grpc_slice_from_static_string("gzip");
memset(&gzip_compression_override.internal_data, 0,
sizeof(gzip_compression_override.internal_data));
- identity_compression_override.key = GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY;
- identity_compression_override.value = "identity";
- identity_compression_override.value_length =
- strlen(identity_compression_override.value);
+ identity_compression_override.key = GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST;
+ identity_compression_override.value =
+ grpc_slice_from_static_string("identity");
memset(&identity_compression_override.internal_data, 0,
sizeof(identity_compression_override.internal_data));
diff --git a/test/core/end2end/tests/default_host.c b/test/core/end2end/tests/default_host.c
index 208e31697e..0c39957fa7 100644
--- a/test/core/end2end/tests/default_host.c
+++ b/test/core/end2end/tests/default_host.c
@@ -110,13 +110,13 @@ static void simple_request_body(grpc_end2end_test_fixture f) {
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
char *peer;
c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
- "/foo", NULL, deadline, NULL);
+ grpc_slice_from_static_string("/foo"), NULL,
+ deadline, NULL);
GPR_ASSERT(c);
peer = grpc_call_get_peer(c);
@@ -149,7 +149,6 @@ static void simple_request_body(grpc_end2end_test_fixture f) {
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -182,7 +181,8 @@ static void simple_request_body(grpc_end2end_test_fixture f) {
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
- op->data.send_status_from_server.status_details = "xyz";
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_details;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -199,12 +199,12 @@ static void simple_request_body(grpc_end2end_test_fixture f) {
cq_verify(cqv);
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
- GPR_ASSERT(0 == strcmp(details, "xyz"));
- GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
- GPR_ASSERT(0 == strncmp(call_details.host, "localhost", 9));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
+ GPR_ASSERT(grpc_slice_buf_start_eq(call_details.host, "localhost", 9));
GPR_ASSERT(was_cancelled == 1);
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/disappearing_server.c b/test/core/end2end/tests/disappearing_server.c
index 8ebf7e643e..a01372144c 100644
--- a/test/core/end2end/tests/disappearing_server.c
+++ b/test/core/end2end/tests/disappearing_server.c
@@ -93,13 +93,13 @@ static void do_request_and_shutdown_server(grpc_end2end_test_config config,
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
c = grpc_channel_create_call(
- f->client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f->client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -128,7 +128,6 @@ static void do_request_and_shutdown_server(grpc_end2end_test_config config,
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -156,7 +155,8 @@ static void do_request_and_shutdown_server(grpc_end2end_test_config config,
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
- op->data.send_status_from_server.status_details = "xyz";
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_details;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -174,13 +174,13 @@ static void do_request_and_shutdown_server(grpc_end2end_test_config config,
cq_verify(cqv);
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
- GPR_ASSERT(0 == strcmp(details, "xyz"));
- GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
validate_host_override_string("foo.test.google.fr:1234", call_details.host,
config);
GPR_ASSERT(was_cancelled == 1);
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/empty_batch.c b/test/core/end2end/tests/empty_batch.c
index dc8e52a60f..1b420ad4cb 100644
--- a/test/core/end2end/tests/empty_batch.c
+++ b/test/core/end2end/tests/empty_batch.c
@@ -106,8 +106,9 @@ static void empty_batch_body(grpc_end2end_test_config config,
grpc_op *op = NULL;
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
diff --git a/test/core/end2end/tests/filter_call_init_fails.c b/test/core/end2end/tests/filter_call_init_fails.c
index 01b6c32ee7..5546893ea0 100644
--- a/test/core/end2end/tests/filter_call_init_fails.c
+++ b/test/core/end2end/tests/filter_call_init_fails.c
@@ -125,12 +125,12 @@ static void test_request(grpc_end2end_test_config config) {
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -165,7 +165,6 @@ static void test_request(grpc_end2end_test_config config) {
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -181,9 +180,9 @@ static void test_request(grpc_end2end_test_config config) {
cq_verify(cqv);
GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED);
- GPR_ASSERT(0 == strcmp(details, "access denied"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(details, "access denied"));
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/filter_causes_close.c b/test/core/end2end/tests/filter_causes_close.c
index def21be43f..45040ab351 100644
--- a/test/core/end2end/tests/filter_causes_close.c
+++ b/test/core/end2end/tests/filter_causes_close.c
@@ -121,12 +121,12 @@ static void test_request(grpc_end2end_test_config config) {
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -161,7 +161,6 @@ static void test_request(grpc_end2end_test_config config) {
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -177,9 +176,10 @@ static void test_request(grpc_end2end_test_config config) {
cq_verify(cqv);
GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED);
- GPR_ASSERT(0 == strcmp(details, "Failure that's not preventable."));
+ GPR_ASSERT(0 ==
+ grpc_slice_str_cmp(details, "Failure that's not preventable."));
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/filter_latency.c b/test/core/end2end/tests/filter_latency.c
index 043f12dd9a..e5288d5ef7 100644
--- a/test/core/end2end/tests/filter_latency.c
+++ b/test/core/end2end/tests/filter_latency.c
@@ -128,8 +128,7 @@ static void test_request(grpc_end2end_test_config config) {
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
gpr_mu_lock(&g_mu);
@@ -138,8 +137,10 @@ static void test_request(grpc_end2end_test_config config) {
gpr_mu_unlock(&g_mu);
const gpr_timespec start_time = gpr_now(GPR_CLOCK_MONOTONIC);
- c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
- "/foo", "foo.test.google.fr", deadline, NULL);
+ c = grpc_channel_create_call(
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr", config), deadline, NULL);
GPR_ASSERT(c);
grpc_metadata_array_init(&initial_metadata_recv);
@@ -173,7 +174,6 @@ static void test_request(grpc_end2end_test_config config) {
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -198,7 +198,8 @@ static void test_request(grpc_end2end_test_config config) {
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
- op->data.send_status_from_server.status_details = "xyz";
+ grpc_slice status_string = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_string;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -215,9 +216,9 @@ static void test_request(grpc_end2end_test_config config) {
cq_verify(cqv);
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
- GPR_ASSERT(0 == strcmp(details, "xyz"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/graceful_server_shutdown.c b/test/core/end2end/tests/graceful_server_shutdown.c
index 5fecadbe44..08af25dd28 100644
--- a/test/core/end2end/tests/graceful_server_shutdown.c
+++ b/test/core/end2end/tests/graceful_server_shutdown.c
@@ -107,13 +107,13 @@ static void test_early_server_shutdown_finishes_inflight_calls(
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -143,7 +143,6 @@ static void test_early_server_shutdown_finishes_inflight_calls(
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -171,7 +170,8 @@ static void test_early_server_shutdown_finishes_inflight_calls(
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
- op->data.send_status_from_server.status_details = "xyz";
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_details;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -191,12 +191,12 @@ static void test_early_server_shutdown_finishes_inflight_calls(
grpc_call_destroy(s);
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
- GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
validate_host_override_string("foo.test.google.fr:1234", call_details.host,
config);
GPR_ASSERT(was_cancelled == 1);
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/high_initial_seqno.c b/test/core/end2end/tests/high_initial_seqno.c
index 01a4909ccd..217ca2bb72 100644
--- a/test/core/end2end/tests/high_initial_seqno.c
+++ b/test/core/end2end/tests/high_initial_seqno.c
@@ -113,13 +113,13 @@ static void simple_request_body(grpc_end2end_test_config config,
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -148,7 +148,6 @@ static void simple_request_body(grpc_end2end_test_config config,
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -172,7 +171,8 @@ static void simple_request_body(grpc_end2end_test_config config,
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
- op->data.send_status_from_server.status_details = "xyz";
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_details;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -189,13 +189,13 @@ static void simple_request_body(grpc_end2end_test_config config,
cq_verify(cqv);
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
- GPR_ASSERT(0 == strcmp(details, "xyz"));
- GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
validate_host_override_string("foo.test.google.fr:1234", call_details.host,
config);
GPR_ASSERT(was_cancelled == 1);
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/hpack_size.c b/test/core/end2end/tests/hpack_size.c
index cec8b2faae..9aedc9c143 100644
--- a/test/core/end2end/tests/hpack_size.c
+++ b/test/core/end2end/tests/hpack_size.c
@@ -254,24 +254,24 @@ static void simple_request_body(grpc_end2end_test_config config,
grpc_status_code status;
grpc_call_error error;
grpc_metadata extra_metadata[3];
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
memset(extra_metadata, 0, sizeof(extra_metadata));
- extra_metadata[0].key = "hobbit-first-name";
- extra_metadata[0].value = hobbits[index % GPR_ARRAY_SIZE(hobbits)][0];
- extra_metadata[0].value_length = strlen(extra_metadata[0].value);
- extra_metadata[1].key = "hobbit-second-name";
- extra_metadata[1].value = hobbits[index % GPR_ARRAY_SIZE(hobbits)][1];
- extra_metadata[1].value_length = strlen(extra_metadata[1].value);
- extra_metadata[2].key = "dragon";
- extra_metadata[2].value = dragons[index % GPR_ARRAY_SIZE(dragons)];
- extra_metadata[2].value_length = strlen(extra_metadata[2].value);
+ extra_metadata[0].key = grpc_slice_from_static_string("hobbit-first-name");
+ extra_metadata[0].value = grpc_slice_from_static_string(
+ hobbits[index % GPR_ARRAY_SIZE(hobbits)][0]);
+ extra_metadata[1].key = grpc_slice_from_static_string("hobbit-second-name");
+ extra_metadata[1].value = grpc_slice_from_static_string(
+ hobbits[index % GPR_ARRAY_SIZE(hobbits)][1]);
+ extra_metadata[2].key = grpc_slice_from_static_string("dragon");
+ extra_metadata[2].value =
+ grpc_slice_from_static_string(dragons[index % GPR_ARRAY_SIZE(dragons)]);
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -301,7 +301,6 @@ static void simple_request_body(grpc_end2end_test_config config,
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -325,7 +324,8 @@ static void simple_request_body(grpc_end2end_test_config config,
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
- op->data.send_status_from_server.status_details = "xyz";
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_details;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -342,13 +342,13 @@ static void simple_request_body(grpc_end2end_test_config config,
cq_verify(cqv);
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
- GPR_ASSERT(0 == strcmp(details, "xyz"));
- GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
validate_host_override_string("foo.test.google.fr:1234", call_details.host,
config);
GPR_ASSERT(was_cancelled == 1);
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/idempotent_request.c b/test/core/end2end/tests/idempotent_request.c
index 4f6d3bb808..2db7accaaa 100644
--- a/test/core/end2end/tests/idempotent_request.c
+++ b/test/core/end2end/tests/idempotent_request.c
@@ -111,14 +111,14 @@ static void simple_request_body(grpc_end2end_test_config config,
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
char *peer;
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -152,7 +152,6 @@ static void simple_request_body(grpc_end2end_test_config config,
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -185,7 +184,8 @@ static void simple_request_body(grpc_end2end_test_config config,
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
- op->data.send_status_from_server.status_details = "xyz";
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_details;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -202,14 +202,14 @@ static void simple_request_body(grpc_end2end_test_config config,
cq_verify(cqv);
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
- GPR_ASSERT(0 == strcmp(details, "xyz"));
- GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
validate_host_override_string("foo.test.google.fr:1234", call_details.host,
config);
GPR_ASSERT(GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST == call_details.flags);
GPR_ASSERT(was_cancelled == 1);
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/invoke_large_request.c b/test/core/end2end/tests/invoke_large_request.c
index 24abfa2ea0..e18953a641 100644
--- a/test/core/end2end/tests/invoke_large_request.c
+++ b/test/core/end2end/tests/invoke_large_request.c
@@ -140,13 +140,13 @@ static void test_invoke_large_request(grpc_end2end_test_config config,
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -185,7 +185,6 @@ static void test_invoke_large_request(grpc_end2end_test_config config,
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -232,7 +231,8 @@ static void test_invoke_large_request(grpc_end2end_test_config config,
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
- op->data.send_status_from_server.status_details = "xyz";
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_details;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -244,13 +244,13 @@ static void test_invoke_large_request(grpc_end2end_test_config config,
cq_verify(cqv);
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
- GPR_ASSERT(0 == strcmp(details, "xyz"));
- GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
validate_host_override_string("foo.test.google.fr:1234", call_details.host,
config);
GPR_ASSERT(was_cancelled == 1);
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/large_metadata.c b/test/core/end2end/tests/large_metadata.c
index 69b4b24b06..b45ceb2664 100644
--- a/test/core/end2end/tests/large_metadata.c
+++ b/test/core/end2end/tests/large_metadata.c
@@ -122,21 +122,19 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config) {
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
- meta.key = "key";
- meta.value = gpr_malloc(large_size + 1);
- memset((char *)meta.value, 'a', large_size);
- ((char *)meta.value)[large_size] = 0;
- meta.value_length = large_size;
+ meta.key = grpc_slice_from_static_string("key");
+ meta.value = grpc_slice_malloc(large_size);
+ memset(GRPC_SLICE_START_PTR(meta.value), 'a', large_size);
grpc_metadata_array_init(&initial_metadata_recv);
grpc_metadata_array_init(&trailing_metadata_recv);
@@ -170,7 +168,6 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config) {
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -216,7 +213,8 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config) {
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_OK;
- op->data.send_status_from_server.status_details = "xyz";
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_details;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -228,15 +226,17 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config) {
cq_verify(cqv);
GPR_ASSERT(status == GRPC_STATUS_OK);
- GPR_ASSERT(0 == strcmp(details, "xyz"));
- GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
validate_host_override_string("foo.test.google.fr:1234", call_details.host,
config);
GPR_ASSERT(was_cancelled == 0);
GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
- GPR_ASSERT(contains_metadata(&request_metadata_recv, "key", meta.value));
+ GPR_ASSERT(contains_metadata_slices(&request_metadata_recv,
+ grpc_slice_from_static_string("key"),
+ meta.value));
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
@@ -250,7 +250,7 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config) {
grpc_byte_buffer_destroy(request_payload);
grpc_byte_buffer_destroy(request_payload_recv);
- gpr_free((char *)meta.value);
+ grpc_slice_unref(meta.value);
end_test(&f);
config.tear_down_data(&f);
diff --git a/test/core/end2end/tests/load_reporting_hook.c b/test/core/end2end/tests/load_reporting_hook.c
index ae5c270629..edc4251119 100644
--- a/test/core/end2end/tests/load_reporting_hook.c
+++ b/test/core/end2end/tests/load_reporting_hook.c
@@ -146,13 +146,13 @@ static void request_response_with_payload(
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, method_name,
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string(method_name),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -193,7 +193,6 @@ static void request_response_with_payload(
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -242,7 +241,8 @@ static void request_response_with_payload(
op->data.send_status_from_server.trailing_metadata_count = 1;
op->data.send_status_from_server.trailing_metadata = trailing_lr_metadata;
op->data.send_status_from_server.status = GRPC_STATUS_OK;
- op->data.send_status_from_server.status_details = "xyz";
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_details;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -255,7 +255,7 @@ static void request_response_with_payload(
GPR_ASSERT(status == GRPC_STATUS_OK);
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
@@ -295,15 +295,13 @@ static void test_load_reporting_hook(grpc_end2end_test_config config) {
grpc_metadata initial_lr_metadata;
grpc_metadata trailing_lr_metadata;
- initial_lr_metadata.key = GRPC_LB_TOKEN_MD_KEY;
- initial_lr_metadata.value = "client-token";
- initial_lr_metadata.value_length = strlen(initial_lr_metadata.value);
+ initial_lr_metadata.key = GRPC_MDSTR_LB_TOKEN;
+ initial_lr_metadata.value = grpc_slice_from_static_string("client-token");
memset(&initial_lr_metadata.internal_data, 0,
sizeof(initial_lr_metadata.internal_data));
- trailing_lr_metadata.key = GRPC_LB_COST_MD_KEY;
- trailing_lr_metadata.value = "server-token";
- trailing_lr_metadata.value_length = strlen(trailing_lr_metadata.value);
+ trailing_lr_metadata.key = GRPC_MDSTR_LB_COST_BIN;
+ trailing_lr_metadata.value = grpc_slice_from_static_string("server-token");
memset(&trailing_lr_metadata.internal_data, 0,
sizeof(trailing_lr_metadata.internal_data));
diff --git a/test/core/end2end/tests/max_concurrent_streams.c b/test/core/end2end/tests/max_concurrent_streams.c
index 9338bc5f0d..56243179b0 100644
--- a/test/core/end2end/tests/max_concurrent_streams.c
+++ b/test/core/end2end/tests/max_concurrent_streams.c
@@ -109,13 +109,13 @@ static void simple_request_body(grpc_end2end_test_config config,
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -144,7 +144,6 @@ static void simple_request_body(grpc_end2end_test_config config,
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -168,7 +167,8 @@ static void simple_request_body(grpc_end2end_test_config config,
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
- op->data.send_status_from_server.status_details = "xyz";
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_details;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -185,13 +185,13 @@ static void simple_request_body(grpc_end2end_test_config config,
cq_verify(cqv);
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
- GPR_ASSERT(0 == strcmp(details, "xyz"));
- GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
validate_host_override_string("foo.test.google.fr:1234", call_details.host,
config);
GPR_ASSERT(was_cancelled == 1);
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
@@ -223,11 +223,9 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) {
grpc_metadata_array trailing_metadata_recv2;
grpc_status_code status1;
grpc_call_error error;
- char *details1 = NULL;
- size_t details_capacity1 = 0;
+ grpc_slice details1;
grpc_status_code status2;
- char *details2 = NULL;
- size_t details_capacity2 = 0;
+ grpc_slice details2;
grpc_op ops[6];
grpc_op *op;
int was_cancelled;
@@ -261,13 +259,15 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) {
the first completes */
deadline = n_seconds_time(1000);
c1 = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/alpha",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/alpha"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c1);
c2 = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/beta",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/beta"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c2);
@@ -295,7 +295,6 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) {
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv1;
op->data.recv_status_on_client.status = &status1;
op->data.recv_status_on_client.status_details = &details1;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity1;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -327,7 +326,6 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) {
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv2;
op->data.recv_status_on_client.status = &status2;
op->data.recv_status_on_client.status_details = &details2;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity2;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -378,7 +376,8 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) {
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
- op->data.send_status_from_server.status_details = "xyz";
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_details;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -413,7 +412,7 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) {
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
- op->data.send_status_from_server.status_details = "xyz";
+ op->data.send_status_from_server.status_details = &status_details;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -431,8 +430,8 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) {
grpc_call_destroy(c2);
grpc_call_destroy(s2);
- gpr_free(details1);
- gpr_free(details2);
+ grpc_slice_unref(details1);
+ grpc_slice_unref(details2);
grpc_metadata_array_destroy(&initial_metadata_recv1);
grpc_metadata_array_destroy(&trailing_metadata_recv1);
grpc_metadata_array_destroy(&initial_metadata_recv2);
diff --git a/test/core/end2end/tests/max_message_length.c b/test/core/end2end/tests/max_message_length.c
index ec85f3cb5d..3fbb92863c 100644
--- a/test/core/end2end/tests/max_message_length.c
+++ b/test/core/end2end/tests/max_message_length.c
@@ -43,6 +43,7 @@
#include <grpc/support/useful.h>
#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/transport/metadata.h"
#include "src/core/lib/transport/method_config.h"
@@ -129,8 +130,7 @@ static void test_max_message_length_on_request(grpc_end2end_test_config config,
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
grpc_channel_args *client_args = NULL;
@@ -141,12 +141,12 @@ static void test_max_message_length_on_request(grpc_end2end_test_config config,
GPR_ASSERT(send_limit);
int32_t max_request_message_bytes = 5;
grpc_method_config_table_entry entry = {
- grpc_mdstr_from_string("/service/method"),
+ grpc_slice_from_static_string("/service/method"),
grpc_method_config_create(NULL, NULL, &max_request_message_bytes, NULL),
};
grpc_method_config_table *method_config_table =
grpc_method_config_table_create(1, &entry);
- GRPC_MDSTR_UNREF(&exec_ctx, entry.method_name);
+ grpc_slice_unref_internal(&exec_ctx, entry.method_name);
grpc_method_config_unref(&exec_ctx, entry.method_config);
grpc_arg arg =
grpc_method_config_table_create_channel_arg(method_config_table);
@@ -180,8 +180,9 @@ static void test_max_message_length_on_request(grpc_end2end_test_config config,
cqv = cq_verifier_create(f.cq);
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/service/method",
- get_host_override_string("foo.test.google.fr:1234", config),
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/service/method"),
+ get_host_override_slice("foo.test.google.fr:1234", config),
gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
GPR_ASSERT(c);
@@ -215,7 +216,6 @@ static void test_max_message_length_on_request(grpc_end2end_test_config config,
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -254,19 +254,20 @@ static void test_max_message_length_on_request(grpc_end2end_test_config config,
CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
cq_verify(cqv);
- GPR_ASSERT(0 == strcmp(call_details.method, "/service/method"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
validate_host_override_string("foo.test.google.fr:1234", call_details.host,
config);
GPR_ASSERT(was_cancelled == 1);
done:
GPR_ASSERT(status == GRPC_STATUS_INVALID_ARGUMENT);
- GPR_ASSERT(strcmp(details,
- send_limit
- ? "Sent message larger than max (11 vs. 5)"
- : "Received message larger than max (11 vs. 5)") == 0);
+ GPR_ASSERT(
+ grpc_slice_str_cmp(
+ details, send_limit
+ ? "Sent message larger than max (11 vs. 5)"
+ : "Received message larger than max (11 vs. 5)") == 0);
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
@@ -309,8 +310,7 @@ static void test_max_message_length_on_response(grpc_end2end_test_config config,
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
grpc_channel_args *client_args = NULL;
@@ -321,13 +321,13 @@ static void test_max_message_length_on_response(grpc_end2end_test_config config,
GPR_ASSERT(!send_limit);
int32_t max_response_message_bytes = 5;
grpc_method_config_table_entry entry = {
- grpc_mdstr_from_string("/service/method"),
+ grpc_slice_from_static_string("/service/method"),
grpc_method_config_create(NULL, NULL, NULL,
&max_response_message_bytes),
};
grpc_method_config_table *method_config_table =
grpc_method_config_table_create(1, &entry);
- GRPC_MDSTR_UNREF(&exec_ctx, entry.method_name);
+ grpc_slice_unref_internal(&exec_ctx, entry.method_name);
grpc_method_config_unref(&exec_ctx, entry.method_config);
grpc_arg arg =
grpc_method_config_table_create_channel_arg(method_config_table);
@@ -359,9 +359,11 @@ static void test_max_message_length_on_response(grpc_end2end_test_config config,
}
cqv = cq_verifier_create(f.cq);
- c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
- "/service/method", "foo.test.google.fr:1234",
- gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
+ c = grpc_channel_create_call(
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/service/method"),
+ get_host_override_slice("foo.test.google.fr:1234", config),
+ gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
GPR_ASSERT(c);
grpc_metadata_array_init(&initial_metadata_recv);
@@ -394,7 +396,6 @@ static void test_max_message_length_on_response(grpc_end2end_test_config config,
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -428,7 +429,8 @@ static void test_max_message_length_on_response(grpc_end2end_test_config config,
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_OK;
- op->data.send_status_from_server.status_details = "xyz";
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_details;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -439,16 +441,18 @@ static void test_max_message_length_on_response(grpc_end2end_test_config config,
CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
cq_verify(cqv);
- GPR_ASSERT(0 == strcmp(call_details.method, "/service/method"));
- GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr:1234"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
+ GPR_ASSERT(0 ==
+ grpc_slice_str_cmp(call_details.host, "foo.test.google.fr:1234"));
GPR_ASSERT(status == GRPC_STATUS_INVALID_ARGUMENT);
- GPR_ASSERT(strcmp(details,
- send_limit
- ? "Sent message larger than max (11 vs. 5)"
- : "Received message larger than max (11 vs. 5)") == 0);
+ GPR_ASSERT(
+ grpc_slice_str_cmp(
+ details, send_limit
+ ? "Sent message larger than max (11 vs. 5)"
+ : "Received message larger than max (11 vs. 5)") == 0);
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/negative_deadline.c b/test/core/end2end/tests/negative_deadline.c
index 929777d39e..403386b5e7 100644
--- a/test/core/end2end/tests/negative_deadline.c
+++ b/test/core/end2end/tests/negative_deadline.c
@@ -108,14 +108,14 @@ static void simple_request_body(grpc_end2end_test_config config,
grpc_metadata_array trailing_metadata_recv;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
gpr_log(GPR_DEBUG, "test with %" PRIuPTR " ops", num_ops);
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -128,7 +128,6 @@ static void simple_request_body(grpc_end2end_test_config config,
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -155,7 +154,7 @@ static void simple_request_body(grpc_end2end_test_config config,
GPR_ASSERT(status == GRPC_STATUS_DEADLINE_EXCEEDED);
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
diff --git a/test/core/end2end/tests/network_status_change.c b/test/core/end2end/tests/network_status_change.c
index 2ebda2ccb8..6cfeaa851a 100644
--- a/test/core/end2end/tests/network_status_change.c
+++ b/test/core/end2end/tests/network_status_change.c
@@ -119,13 +119,13 @@ static void test_invoke_network_status_change(grpc_end2end_test_config config) {
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -159,7 +159,6 @@ static void test_invoke_network_status_change(grpc_end2end_test_config config) {
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -201,7 +200,8 @@ static void test_invoke_network_status_change(grpc_end2end_test_config config) {
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_OK;
- op->data.send_status_from_server.status_details = "xyz";
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_details;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -214,11 +214,11 @@ static void test_invoke_network_status_change(grpc_end2end_test_config config) {
// Expected behavior of a RPC when network is lost.
GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE);
- GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
validate_host_override_string("foo.test.google.fr:1234", call_details.host,
config);
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/no_logging.c b/test/core/end2end/tests/no_logging.c
index 54614cb029..5c22631bad 100644
--- a/test/core/end2end/tests/no_logging.c
+++ b/test/core/end2end/tests/no_logging.c
@@ -139,14 +139,14 @@ static void simple_request_body(grpc_end2end_test_config config,
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
char *peer;
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -179,7 +179,6 @@ static void simple_request_body(grpc_end2end_test_config config,
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -210,7 +209,8 @@ static void simple_request_body(grpc_end2end_test_config config,
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
- op->data.send_status_from_server.status_details = "xyz";
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_details;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -227,14 +227,14 @@ static void simple_request_body(grpc_end2end_test_config config,
cq_verify(cqv);
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
- GPR_ASSERT(0 == strcmp(details, "xyz"));
- GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
validate_host_override_string("foo.test.google.fr:1234", call_details.host,
config);
GPR_ASSERT(0 == call_details.flags);
GPR_ASSERT(was_cancelled == 1);
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/payload.c b/test/core/end2end/tests/payload.c
index db2e5c83de..dd989e3ad6 100644
--- a/test/core/end2end/tests/payload.c
+++ b/test/core/end2end/tests/payload.c
@@ -138,13 +138,13 @@ static void request_response_with_payload(grpc_end2end_test_config config,
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -183,7 +183,6 @@ static void request_response_with_payload(grpc_end2end_test_config config,
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -230,7 +229,8 @@ static void request_response_with_payload(grpc_end2end_test_config config,
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_OK;
- op->data.send_status_from_server.status_details = "xyz";
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_details;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -242,8 +242,8 @@ static void request_response_with_payload(grpc_end2end_test_config config,
cq_verify(cqv);
GPR_ASSERT(status == GRPC_STATUS_OK);
- GPR_ASSERT(0 == strcmp(details, "xyz"));
- GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
validate_host_override_string("foo.test.google.fr:1234", call_details.host,
config);
GPR_ASSERT(was_cancelled == 0);
@@ -251,7 +251,7 @@ static void request_response_with_payload(grpc_end2end_test_config config,
GPR_ASSERT(
byte_buffer_eq_slice(response_payload_recv, response_payload_slice));
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/ping_pong_streaming.c b/test/core/end2end/tests/ping_pong_streaming.c
index 0a1566e9c2..b69b7f27a6 100644
--- a/test/core/end2end/tests/ping_pong_streaming.c
+++ b/test/core/end2end/tests/ping_pong_streaming.c
@@ -112,8 +112,7 @@ static void test_pingpong_streaming(grpc_end2end_test_config config,
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
grpc_byte_buffer *request_payload;
grpc_byte_buffer *request_payload_recv;
@@ -126,8 +125,9 @@ static void test_pingpong_streaming(grpc_end2end_test_config config,
grpc_slice_from_copied_string("hello you");
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -152,7 +152,6 @@ static void test_pingpong_streaming(grpc_end2end_test_config config,
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -248,7 +247,8 @@ static void test_pingpong_streaming(grpc_end2end_test_config config,
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
- op->data.send_status_from_server.status_details = "xyz";
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_details;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -270,7 +270,7 @@ static void test_pingpong_streaming(grpc_end2end_test_config config,
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
grpc_call_details_destroy(&call_details);
- gpr_free(details);
+ grpc_slice_unref(details);
end_test(&f);
config.tear_down_data(&f);
diff --git a/test/core/end2end/tests/registered_call.c b/test/core/end2end/tests/registered_call.c
index 6594b420b9..e0716737a3 100644
--- a/test/core/end2end/tests/registered_call.c
+++ b/test/core/end2end/tests/registered_call.c
@@ -111,8 +111,7 @@ static void simple_request_body(grpc_end2end_test_config config,
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
c = grpc_channel_create_registered_call(
@@ -144,7 +143,6 @@ static void simple_request_body(grpc_end2end_test_config config,
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -168,7 +166,8 @@ static void simple_request_body(grpc_end2end_test_config config,
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
- op->data.send_status_from_server.status_details = "xyz";
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_details;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -185,13 +184,13 @@ static void simple_request_body(grpc_end2end_test_config config,
cq_verify(cqv);
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
- GPR_ASSERT(0 == strcmp(details, "xyz"));
- GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
validate_host_override_string("foo.test.google.fr:1234", call_details.host,
config);
GPR_ASSERT(was_cancelled == 1);
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/request_with_flags.c b/test/core/end2end/tests/request_with_flags.c
index 9c18e155f3..cd92b484a3 100644
--- a/test/core/end2end/tests/request_with_flags.c
+++ b/test/core/end2end/tests/request_with_flags.c
@@ -117,13 +117,13 @@ static void test_invoke_request_with_flags(
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
grpc_call_error expectation;
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -157,7 +157,6 @@ static void test_invoke_request_with_flags(
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = flags_for_op[op->op];
op->reserved = NULL;
op++;
@@ -170,7 +169,7 @@ static void test_invoke_request_with_flags(
cq_verify(cqv);
}
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/request_with_payload.c b/test/core/end2end/tests/request_with_payload.c
index c84e3ac5b5..3258c0451b 100644
--- a/test/core/end2end/tests/request_with_payload.c
+++ b/test/core/end2end/tests/request_with_payload.c
@@ -116,13 +116,13 @@ static void test_invoke_request_with_payload(grpc_end2end_test_config config) {
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -156,7 +156,6 @@ static void test_invoke_request_with_payload(grpc_end2end_test_config config) {
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -197,7 +196,8 @@ static void test_invoke_request_with_payload(grpc_end2end_test_config config) {
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_OK;
- op->data.send_status_from_server.status_details = "xyz";
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_details;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -209,14 +209,14 @@ static void test_invoke_request_with_payload(grpc_end2end_test_config config) {
cq_verify(cqv);
GPR_ASSERT(status == GRPC_STATUS_OK);
- GPR_ASSERT(0 == strcmp(details, "xyz"));
- GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
validate_host_override_string("foo.test.google.fr:1234", call_details.host,
config);
GPR_ASSERT(was_cancelled == 0);
GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/resource_quota_server.c b/test/core/end2end/tests/resource_quota_server.c
index 7ec33e97a3..15d7734311 100644
--- a/test/core/end2end/tests/resource_quota_server.c
+++ b/test/core/end2end/tests/resource_quota_server.c
@@ -149,8 +149,7 @@ void resource_quota_server(grpc_end2end_test_config config) {
grpc_call_details *call_details =
malloc(sizeof(grpc_call_details) * NUM_CALLS);
grpc_status_code *status = malloc(sizeof(grpc_status_code) * NUM_CALLS);
- char **details = malloc(sizeof(char *) * NUM_CALLS);
- size_t *details_capacity = malloc(sizeof(size_t) * NUM_CALLS);
+ grpc_slice *details = malloc(sizeof(char *) * NUM_CALLS);
grpc_byte_buffer **request_payload_recv =
malloc(sizeof(grpc_byte_buffer *) * NUM_CALLS);
int *was_cancelled = malloc(sizeof(int) * NUM_CALLS);
@@ -173,8 +172,6 @@ void resource_quota_server(grpc_end2end_test_config config) {
grpc_metadata_array_init(&trailing_metadata_recv[i]);
grpc_metadata_array_init(&request_metadata_recv[i]);
grpc_call_details_init(&call_details[i]);
- details[i] = NULL;
- details_capacity[i] = 0;
request_payload_recv[i] = NULL;
was_cancelled[i] = 0;
}
@@ -190,8 +187,10 @@ void resource_quota_server(grpc_end2end_test_config config) {
for (int i = 0; i < NUM_CALLS; i++) {
client_calls[i] = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- "foo.test.google.fr", n_seconds_time(60), NULL);
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr", config),
+ n_seconds_time(60), NULL);
memset(ops, 0, sizeof(ops));
op = ops;
@@ -219,8 +218,6 @@ void resource_quota_server(grpc_end2end_test_config config) {
&trailing_metadata_recv[i];
op->data.recv_status_on_client.status = &status[i];
op->data.recv_status_on_client.status_details = &details[i];
- op->data.recv_status_on_client.status_details_capacity =
- &details_capacity[i];
op->flags = 0;
op->reserved = NULL;
op++;
@@ -260,7 +257,7 @@ void resource_quota_server(grpc_end2end_test_config config) {
grpc_metadata_array_destroy(&initial_metadata_recv[call_id]);
grpc_metadata_array_destroy(&trailing_metadata_recv[call_id]);
grpc_call_destroy(client_calls[call_id]);
- gpr_free(details[call_id]);
+ grpc_slice_unref(details[call_id]);
pending_client_calls--;
} else if (ev_tag < SERVER_RECV_BASE_TAG) {
@@ -317,7 +314,8 @@ void resource_quota_server(grpc_end2end_test_config config) {
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_OK;
- op->data.send_status_from_server.status_details = "xyz";
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_details;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -370,7 +368,6 @@ void resource_quota_server(grpc_end2end_test_config config) {
free(call_details);
free(status);
free(details);
- free(details_capacity);
free(request_payload_recv);
free(was_cancelled);
diff --git a/test/core/end2end/tests/server_finishes_request.c b/test/core/end2end/tests/server_finishes_request.c
index 3bb25fd924..ee18c6817b 100644
--- a/test/core/end2end/tests/server_finishes_request.c
+++ b/test/core/end2end/tests/server_finishes_request.c
@@ -111,13 +111,13 @@ static void simple_request_body(grpc_end2end_test_config config,
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -142,7 +142,6 @@ static void simple_request_body(grpc_end2end_test_config config,
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -166,7 +165,8 @@ static void simple_request_body(grpc_end2end_test_config config,
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
- op->data.send_status_from_server.status_details = "xyz";
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_details;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -183,13 +183,13 @@ static void simple_request_body(grpc_end2end_test_config config,
cq_verify(cqv);
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
- GPR_ASSERT(0 == strcmp(details, "xyz"));
- GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
validate_host_override_string("foo.test.google.fr:1234", call_details.host,
config);
GPR_ASSERT(was_cancelled == 1);
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/shutdown_finishes_calls.c b/test/core/end2end/tests/shutdown_finishes_calls.c
index b80a2e35f2..0be5315360 100644
--- a/test/core/end2end/tests/shutdown_finishes_calls.c
+++ b/test/core/end2end/tests/shutdown_finishes_calls.c
@@ -100,13 +100,13 @@ static void test_early_server_shutdown_finishes_inflight_calls(
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -136,7 +136,6 @@ static void test_early_server_shutdown_finishes_inflight_calls(
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -172,12 +171,12 @@ static void test_early_server_shutdown_finishes_inflight_calls(
grpc_server_destroy(f.server);
GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE);
- GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
validate_host_override_string("foo.test.google.fr:1234", call_details.host,
config);
GPR_ASSERT(was_cancelled == 1);
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/simple_cacheable_request.c b/test/core/end2end/tests/simple_cacheable_request.c
index 2c229b08fe..ea916e7b3a 100644
--- a/test/core/end2end/tests/simple_cacheable_request.c
+++ b/test/core/end2end/tests/simple_cacheable_request.c
@@ -111,12 +111,22 @@ static void test_cacheable_request_response_with_metadata_and_payload(
grpc_byte_buffer *response_payload =
grpc_raw_byte_buffer_create(&response_payload_slice, 1);
gpr_timespec deadline = five_seconds_time();
- grpc_metadata meta_c[2] = {
- {"key1", "val1", 4, 0, {{NULL, NULL, NULL, NULL}}},
- {"key2", "val2", 4, 0, {{NULL, NULL, NULL, NULL}}}};
- grpc_metadata meta_s[2] = {
- {"key3", "val3", 4, 0, {{NULL, NULL, NULL, NULL}}},
- {"key4", "val4", 4, 0, {{NULL, NULL, NULL, NULL}}}};
+ grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"),
+ grpc_slice_from_static_string("val1"),
+ 0,
+ {{NULL, NULL, NULL, NULL}}},
+ {grpc_slice_from_static_string("key2"),
+ grpc_slice_from_static_string("val2"),
+ 0,
+ {{NULL, NULL, NULL, NULL}}}};
+ grpc_metadata meta_s[2] = {{grpc_slice_from_static_string("key3"),
+ grpc_slice_from_static_string("val3"),
+ 0,
+ {{NULL, NULL, NULL, NULL}}},
+ {grpc_slice_from_static_string("key4"),
+ grpc_slice_from_static_string("val4"),
+ 0,
+ {{NULL, NULL, NULL, NULL}}}};
grpc_end2end_test_fixture f = begin_test(
config, "test_cacheable_request_response_with_metadata_and_payload", NULL,
NULL);
@@ -131,13 +141,13 @@ static void test_cacheable_request_response_with_metadata_and_payload(
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -177,7 +187,6 @@ static void test_cacheable_request_response_with_metadata_and_payload(
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -225,7 +234,8 @@ static void test_cacheable_request_response_with_metadata_and_payload(
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_OK;
- op->data.send_status_from_server.status_details = "xyz";
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_details;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -237,8 +247,8 @@ static void test_cacheable_request_response_with_metadata_and_payload(
cq_verify(cqv);
GPR_ASSERT(status == GRPC_STATUS_OK);
- GPR_ASSERT(0 == strcmp(details, "xyz"));
- GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
validate_host_override_string("foo.test.google.fr:1234", call_details.host,
config);
if (config.feature_mask & FEATURE_MASK_SUPPORTS_REQUEST_PROXYING) {
@@ -254,7 +264,7 @@ static void test_cacheable_request_response_with_metadata_and_payload(
GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key3", "val3"));
GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key4", "val4"));
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/simple_delayed_request.c b/test/core/end2end/tests/simple_delayed_request.c
index ec40c8f22d..83ad8515df 100644
--- a/test/core/end2end/tests/simple_delayed_request.c
+++ b/test/core/end2end/tests/simple_delayed_request.c
@@ -100,15 +100,15 @@ static void simple_delayed_request_body(grpc_end2end_test_config config,
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
config.init_client(f, client_args);
c = grpc_channel_create_call(
- f->client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f->client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -137,7 +137,6 @@ static void simple_delayed_request_body(grpc_end2end_test_config config,
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -163,7 +162,8 @@ static void simple_delayed_request_body(grpc_end2end_test_config config,
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
- op->data.send_status_from_server.status_details = "xyz";
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_details;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -180,13 +180,13 @@ static void simple_delayed_request_body(grpc_end2end_test_config config,
cq_verify(cqv);
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
- GPR_ASSERT(0 == strcmp(details, "xyz"));
- GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
validate_host_override_string("foo.test.google.fr:1234", call_details.host,
config);
GPR_ASSERT(was_cancelled == 1);
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/simple_metadata.c b/test/core/end2end/tests/simple_metadata.c
index 5490cc2b75..162c89c618 100644
--- a/test/core/end2end/tests/simple_metadata.c
+++ b/test/core/end2end/tests/simple_metadata.c
@@ -109,12 +109,22 @@ static void test_request_response_with_metadata_and_payload(
grpc_byte_buffer *response_payload =
grpc_raw_byte_buffer_create(&response_payload_slice, 1);
gpr_timespec deadline = five_seconds_time();
- grpc_metadata meta_c[2] = {
- {"key1", "val1", 4, 0, {{NULL, NULL, NULL, NULL}}},
- {"key2", "val2", 4, 0, {{NULL, NULL, NULL, NULL}}}};
- grpc_metadata meta_s[2] = {
- {"key3", "val3", 4, 0, {{NULL, NULL, NULL, NULL}}},
- {"key4", "val4", 4, 0, {{NULL, NULL, NULL, NULL}}}};
+ grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"),
+ grpc_slice_from_static_string("val1"),
+ 0,
+ {{NULL, NULL, NULL, NULL}}},
+ {grpc_slice_from_static_string("key2"),
+ grpc_slice_from_static_string("val2"),
+ 0,
+ {{NULL, NULL, NULL, NULL}}}};
+ grpc_metadata meta_s[2] = {{grpc_slice_from_static_string("key3"),
+ grpc_slice_from_static_string("val3"),
+ 0,
+ {{NULL, NULL, NULL, NULL}}},
+ {grpc_slice_from_static_string("key4"),
+ grpc_slice_from_static_string("val4"),
+ 0,
+ {{NULL, NULL, NULL, NULL}}}};
grpc_end2end_test_fixture f = begin_test(
config, "test_request_response_with_metadata_and_payload", NULL, NULL);
cq_verifier *cqv = cq_verifier_create(f.cq);
@@ -128,13 +138,13 @@ static void test_request_response_with_metadata_and_payload(
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -174,7 +184,6 @@ static void test_request_response_with_metadata_and_payload(
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -222,7 +231,8 @@ static void test_request_response_with_metadata_and_payload(
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_OK;
- op->data.send_status_from_server.status_details = "xyz";
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_details;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -234,8 +244,8 @@ static void test_request_response_with_metadata_and_payload(
cq_verify(cqv);
GPR_ASSERT(status == GRPC_STATUS_OK);
- GPR_ASSERT(0 == strcmp(details, "xyz"));
- GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
validate_host_override_string("foo.test.google.fr:1234", call_details.host,
config);
GPR_ASSERT(was_cancelled == 0);
@@ -246,7 +256,7 @@ static void test_request_response_with_metadata_and_payload(
GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key3", "val3"));
GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key4", "val4"));
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/simple_request.c b/test/core/end2end/tests/simple_request.c
index 2dea5d6af2..e0a69826c4 100644
--- a/test/core/end2end/tests/simple_request.c
+++ b/test/core/end2end/tests/simple_request.c
@@ -111,14 +111,14 @@ static void simple_request_body(grpc_end2end_test_config config,
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
char *peer;
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -152,7 +152,6 @@ static void simple_request_body(grpc_end2end_test_config config,
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -185,7 +184,8 @@ static void simple_request_body(grpc_end2end_test_config config,
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
- op->data.send_status_from_server.status_details = "xyz";
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_details;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -202,14 +202,14 @@ static void simple_request_body(grpc_end2end_test_config config,
cq_verify(cqv);
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
- GPR_ASSERT(0 == strcmp(details, "xyz"));
- GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
validate_host_override_string("foo.test.google.fr:1234", call_details.host,
config);
GPR_ASSERT(0 == call_details.flags);
GPR_ASSERT(was_cancelled == 1);
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/streaming_error_response.c b/test/core/end2end/tests/streaming_error_response.c
index 583bc9268f..05012523a7 100644
--- a/test/core/end2end/tests/streaming_error_response.c
+++ b/test/core/end2end/tests/streaming_error_response.c
@@ -121,13 +121,13 @@ static void test(grpc_end2end_test_config config, bool request_status_early) {
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -154,7 +154,6 @@ static void test(grpc_end2end_test_config config, bool request_status_early) {
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op++;
}
error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL);
@@ -202,7 +201,8 @@ static void test(grpc_end2end_test_config config, bool request_status_early) {
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_FAILED_PRECONDITION;
- op->data.send_status_from_server.status_details = "xyz";
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_details;
op++;
error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(104), NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
@@ -232,7 +232,6 @@ static void test(grpc_end2end_test_config config, bool request_status_early) {
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op++;
error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
@@ -245,13 +244,13 @@ static void test(grpc_end2end_test_config config, bool request_status_early) {
}
GPR_ASSERT(status == GRPC_STATUS_FAILED_PRECONDITION);
- GPR_ASSERT(0 == strcmp(details, "xyz"));
- GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
validate_host_override_string("foo.test.google.fr:1234", call_details.host,
config);
GPR_ASSERT(was_cancelled == 1);
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/trailing_metadata.c b/test/core/end2end/tests/trailing_metadata.c
index 9fd4fbc052..b6741dbf3d 100644
--- a/test/core/end2end/tests/trailing_metadata.c
+++ b/test/core/end2end/tests/trailing_metadata.c
@@ -109,15 +109,30 @@ static void test_request_response_with_metadata_and_payload(
grpc_byte_buffer *response_payload =
grpc_raw_byte_buffer_create(&response_payload_slice, 1);
gpr_timespec deadline = five_seconds_time();
- grpc_metadata meta_c[2] = {
- {"key1", "val1", 4, 0, {{NULL, NULL, NULL, NULL}}},
- {"key2", "val2", 4, 0, {{NULL, NULL, NULL, NULL}}}};
- grpc_metadata meta_s[2] = {
- {"key3", "val3", 4, 0, {{NULL, NULL, NULL, NULL}}},
- {"key4", "val4", 4, 0, {{NULL, NULL, NULL, NULL}}}};
- grpc_metadata meta_t[2] = {
- {"key5", "val5", 4, 0, {{NULL, NULL, NULL, NULL}}},
- {"key6", "val6", 4, 0, {{NULL, NULL, NULL, NULL}}}};
+ grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"),
+ grpc_slice_from_static_string("val1"),
+ 0,
+ {{NULL, NULL, NULL, NULL}}},
+ {grpc_slice_from_static_string("key2"),
+ grpc_slice_from_static_string("val2"),
+ 0,
+ {{NULL, NULL, NULL, NULL}}}};
+ grpc_metadata meta_s[2] = {{grpc_slice_from_static_string("key3"),
+ grpc_slice_from_static_string("val3"),
+ 0,
+ {{NULL, NULL, NULL, NULL}}},
+ {grpc_slice_from_static_string("key4"),
+ grpc_slice_from_static_string("val4"),
+ 0,
+ {{NULL, NULL, NULL, NULL}}}};
+ grpc_metadata meta_t[2] = {{grpc_slice_from_static_string("key5"),
+ grpc_slice_from_static_string("val5"),
+ 0,
+ {{NULL, NULL, NULL, NULL}}},
+ {grpc_slice_from_static_string("key6"),
+ grpc_slice_from_static_string("val6"),
+ 0,
+ {{NULL, NULL, NULL, NULL}}}};
grpc_end2end_test_fixture f = begin_test(
config, "test_request_response_with_metadata_and_payload", NULL, NULL);
cq_verifier *cqv = cq_verifier_create(f.cq);
@@ -131,13 +146,13 @@ static void test_request_response_with_metadata_and_payload(
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
int was_cancelled = 2;
c = grpc_channel_create_call(
- f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
- get_host_override_string("foo.test.google.fr:1234", config), deadline,
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"),
+ get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
@@ -177,7 +192,6 @@ static void test_request_response_with_metadata_and_payload(
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
- op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -226,7 +240,8 @@ static void test_request_response_with_metadata_and_payload(
op->data.send_status_from_server.trailing_metadata_count = 2;
op->data.send_status_from_server.trailing_metadata = meta_t;
op->data.send_status_from_server.status = GRPC_STATUS_OK;
- op->data.send_status_from_server.status_details = "xyz";
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_details;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -238,8 +253,8 @@ static void test_request_response_with_metadata_and_payload(
cq_verify(cqv);
GPR_ASSERT(status == GRPC_STATUS_OK);
- GPR_ASSERT(0 == strcmp(details, "xyz"));
- GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
validate_host_override_string("foo.test.google.fr:1234", call_details.host,
config);
GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
@@ -251,7 +266,7 @@ static void test_request_response_with_metadata_and_payload(
GPR_ASSERT(contains_metadata(&trailing_metadata_recv, "key5", "val5"));
GPR_ASSERT(contains_metadata(&trailing_metadata_recv, "key6", "val6"));
- gpr_free(details);
+ grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/tools/codegen/core/gen_static_metadata.py b/tools/codegen/core/gen_static_metadata.py
index cf3762dbb8..a9001a6897 100755
--- a/tools/codegen/core/gen_static_metadata.py
+++ b/tools/codegen/core/gen_static_metadata.py
@@ -31,8 +31,11 @@
import hashlib
import itertools
+import collections
import os
import sys
+import subprocess
+import re
# configuration: a list of either strings or 2-tuples of strings
# a single string represents a static grpc_mdstr
@@ -40,6 +43,7 @@ import sys
# also be created)
CONFIG = [
+ # metadata strings
'grpc-timeout',
'grpc-internal-encoding-request',
'grpc-payload-bin',
@@ -54,6 +58,12 @@ CONFIG = [
'grpc-tracing-bin',
'grpc-stats-bin',
'',
+ # channel arg keys
+ 'grpc.wait_for_ready',
+ 'grpc.timeout',
+ 'grpc.max_request_message_bytes',
+ 'grpc.max_response_message_bytes',
+ # metadata elements
('grpc-status', '0'),
('grpc-status', '1'),
('grpc-status', '2'),
@@ -281,12 +291,43 @@ print >>C, '#include "src/core/lib/transport/static_metadata.h"'
print >>C
print >>H, '#define GRPC_STATIC_MDSTR_COUNT %d' % len(all_strs)
-print >>H, 'extern grpc_mdstr grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT];'
+print >>H, 'extern const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT];'
for i, elem in enumerate(all_strs):
print >>H, '/* "%s" */' % elem
- print >>H, '#define %s (&grpc_static_mdstr_table[%d])' % (mangle(elem).upper(), i)
+ print >>H, '#define %s (grpc_static_slice_table[%d])' % (mangle(elem).upper(), i)
print >>H
-print >>C, 'grpc_mdstr grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT];'
+print >>H, 'bool grpc_is_static_metadata_string(grpc_slice slice);'
+print >>H
+print >>C, 'static uint8_t g_raw_bytes[] = {%s};' % (','.join('%d' % ord(c) for c in ''.join(all_strs)))
+print >>C
+print >>C, 'static void static_ref(void *unused) {}'
+print >>C, 'static void static_unref(grpc_exec_ctx *exec_ctx, void *unused) {}'
+print >>C, 'static grpc_slice_refcount g_refcnt = {static_ref, static_unref};'
+print >>C
+print >>C, 'bool grpc_is_static_metadata_string(grpc_slice slice) {'
+print >>C, ' return slice.refcount != NULL && slice.refcount->ref == static_ref;'
+print >>C, '};'
+print >>C
+print >>C, 'const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT] = {'
+str_ofs = 0
+revmap = {}
+zero_length_idx = None
+for i, elem in enumerate(all_strs):
+ print >>C, '{.refcount = &g_refcnt, .data.refcounted = {.bytes = g_raw_bytes+%d, .length=%d}},' % (str_ofs, len(elem))
+ revmap[str_ofs] = i
+ if len(elem) == 0: zero_length_idx = i
+ str_ofs += len(elem);
+print >>C, '};'
+print >>C
+print >>C, 'static const uint8_t g_revmap[] = {%s};' % ','.join('%d' % (revmap[i] if i in revmap else 255) for i in range(0, str_ofs))
+print >>C
+print >>C, 'int grpc_static_metadata_index(grpc_slice slice) {'
+print >>C, ' if (GRPC_SLICE_LENGTH(slice) == 0) return %d;' % zero_length_idx
+print >>C, ' size_t ofs = (size_t)(GRPC_SLICE_START_PTR(slice) - g_raw_bytes);'
+print >>C, ' if (ofs > sizeof(g_revmap)) return -1;'
+print >>C, ' uint8_t id = g_revmap[ofs];'
+print >>C, ' return id == 255 ? -1 : id;'
+print >>C, '};'
print >>C
print >>D, '# hpack fuzzing dictionary'
@@ -319,18 +360,72 @@ def md_idx(m):
if m == m2:
return i
+def perfect_hash(keys, name):
+ tmp = open('/tmp/keys.txt', 'w')
+ tmp.write(''.join('%d\n' % (x - min(keys)) for x in keys))
+ tmp.close()
+ cmd = '%s/perfect/run.sh %s -ds' % (os.path.dirname(sys.argv[0]), tmp.name)
+ subprocess.check_call(cmd, shell=True)
+
+ code = ''
+
+ results = {}
+ with open('%s/perfect/phash.h' % os.path.dirname(sys.argv[0])) as f:
+ txt = f.read()
+ for var in ('PHASHLEN', 'PHASHNKEYS', 'PHASHRANGE', 'PHASHSALT'):
+ val = re.search(r'#define %s ([0-9a-zA-Z]+)' % var, txt).group(1)
+ code += '#define %s_%s %s\n' % (name.upper(), var, val)
+ results[var] = val
+ code += '\n'
+ pycode = 'def f(val):\n'
+ pycode += ' val -= %d\n' % min(keys)
+ with open('%s/perfect/phash.c' % os.path.dirname(sys.argv[0])) as f:
+ txt = f.read()
+ tabdata = re.search(r'ub1 tab\[\] = \{([^}]+)\}', txt, re.MULTILINE).group(1)
+ code += 'static const uint8_t %s_tab[] = {%s};\n\n' % (name, tabdata)
+ func_body = re.search(r'ub4 phash\(val\)\nub4 val;\n\{([^}]+)\}', txt, re.MULTILINE).group(1).replace('ub4', 'uint32_t')
+ code += 'static uint32_t %s_phash(uint32_t val) {\nval -= %d;\n%s}\n' % (name,
+ min(keys), func_body.replace('tab', '%s_tab' % name))
+ pycode += ' tab=(%s)' % tabdata.replace('\n', '')
+ pycode += '\n'.join(' %s' % s.strip() for s in func_body.splitlines()[2:])
+ g = {}
+ exec pycode in g
+ pyfunc = g['f']
+
+ results['code'] = code
+ results['pyfunc'] = pyfunc
+ return results
+
+elem_keys = [str_idx(elem[0]) * len(all_strs) + str_idx(elem[1]) for elem in all_elems]
+elem_hash = perfect_hash(elem_keys, "elems")
+print >>C, elem_hash['code']
+
+keys = [0] * int(elem_hash['PHASHRANGE'])
+idxs = [-1] * int(elem_hash['PHASHNKEYS'])
+for i, k in enumerate(elem_keys):
+ h = elem_hash['pyfunc'](k)
+ assert keys[h] == 0
+ keys[h] = k
+ idxs[h] = i
+print >>C, 'static const uint16_t elem_keys[] = {%s};' % ','.join('%d' % k for k in keys)
+print >>C, 'static const uint8_t elem_idxs[] = {%s};' % ','.join('%d' % i for i in idxs)
+print >>C
+
+print >>H, 'grpc_mdelem *grpc_static_mdelem_for_static_strings(int a, int b);'
+print >>C, 'grpc_mdelem *grpc_static_mdelem_for_static_strings(int a, int b) {'
+print >>C, ' if (a == -1 || b == -1) return NULL;'
+print >>C, ' uint32_t k = (uint32_t)(a * %d + b);' % len(all_strs)
+print >>C, ' uint32_t h = elems_phash(k);'
+print >>C, ' return elem_keys[h] == k ? &grpc_static_mdelem_table[elem_idxs[h]] : NULL;'
+print >>C, '}'
+print >>C
+
print >>H, 'extern const uint8_t grpc_static_metadata_elem_indices[GRPC_STATIC_MDELEM_COUNT*2];'
print >>C, 'const uint8_t grpc_static_metadata_elem_indices[GRPC_STATIC_MDELEM_COUNT*2] = {'
print >>C, ','.join('%d' % str_idx(x) for x in itertools.chain.from_iterable([a,b] for a, b in all_elems))
print >>C, '};'
print >>C
-print >>H, 'extern const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT];'
-print >>C, 'const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT] = {'
-print >>C, '%s' % ',\n'.join(' "%s"' % s for s in all_strs)
-print >>C, '};'
-print >>C
-
print >>H, 'extern const uint8_t grpc_static_accept_encoding_metadata[%d];' % (1 << len(COMPRESSION_ALGORITHMS))
print >>C, 'const uint8_t grpc_static_accept_encoding_metadata[%d] = {' % (1 << len(COMPRESSION_ALGORITHMS))
print >>C, '0,%s' % ','.join('%d' % md_idx(elem) for elem in compression_elems)
diff --git a/tools/codegen/core/perfect/.gitignore b/tools/codegen/core/perfect/.gitignore
new file mode 100644
index 0000000000..c1489f0819
--- /dev/null
+++ b/tools/codegen/core/perfect/.gitignore
@@ -0,0 +1,7 @@
+perfect
+*.o
+phash.h
+phash.c
+compile.txt
+hash.txt
+
diff --git a/tools/codegen/core/perfect/lookupa.c b/tools/codegen/core/perfect/lookupa.c
new file mode 100644
index 0000000000..c122c4f107
--- /dev/null
+++ b/tools/codegen/core/perfect/lookupa.c
@@ -0,0 +1,240 @@
+/*
+--------------------------------------------------------------------
+lookupa.c, by Bob Jenkins, December 1996. Same as lookup2.c
+Use this code however you wish. Public Domain. No warranty.
+Source is http://burtleburtle.net/bob/c/lookupa.c
+--------------------------------------------------------------------
+*/
+#ifndef STANDARD
+#include "standard.h"
+#endif
+#ifndef LOOKUPA
+#include "lookupa.h"
+#endif
+
+/*
+--------------------------------------------------------------------
+mix -- mix 3 32-bit values reversibly.
+For every delta with one or two bit set, and the deltas of all three
+ high bits or all three low bits, whether the original value of a,b,c
+ is almost all zero or is uniformly distributed,
+* If mix() is run forward or backward, at least 32 bits in a,b,c
+ have at least 1/4 probability of changing.
+* If mix() is run forward, every bit of c will change between 1/3 and
+ 2/3 of the time. (Well, 22/100 and 78/100 for some 2-bit deltas.)
+mix() was built out of 36 single-cycle latency instructions in a
+ structure that could supported 2x parallelism, like so:
+ a -= b;
+ a -= c; x = (c>>13);
+ b -= c; a ^= x;
+ b -= a; x = (a<<8);
+ c -= a; b ^= x;
+ c -= b; x = (b>>13);
+ ...
+ Unfortunately, superscalar Pentiums and Sparcs can't take advantage
+ of that parallelism. They've also turned some of those single-cycle
+ latency instructions into multi-cycle latency instructions. Still,
+ this is the fastest good hash I could find. There were about 2^^68
+ to choose from. I only looked at a billion or so.
+--------------------------------------------------------------------
+*/
+#define mix(a,b,c) \
+{ \
+ a -= b; a -= c; a ^= (c>>13); \
+ b -= c; b -= a; b ^= (a<<8); \
+ c -= a; c -= b; c ^= (b>>13); \
+ a -= b; a -= c; a ^= (c>>12); \
+ b -= c; b -= a; b ^= (a<<16); \
+ c -= a; c -= b; c ^= (b>>5); \
+ a -= b; a -= c; a ^= (c>>3); \
+ b -= c; b -= a; b ^= (a<<10); \
+ c -= a; c -= b; c ^= (b>>15); \
+}
+
+/*
+--------------------------------------------------------------------
+lookup() -- hash a variable-length key into a 32-bit value
+ k : the key (the unaligned variable-length array of bytes)
+ len : the length of the key, counting by bytes
+ level : can be any 4-byte value
+Returns a 32-bit value. Every bit of the key affects every bit of
+the return value. Every 1-bit and 2-bit delta achieves avalanche.
+About 6len+35 instructions.
+
+The best hash table sizes are powers of 2. There is no need to do
+mod a prime (mod is sooo slow!). If you need less than 32 bits,
+use a bitmask. For example, if you need only 10 bits, do
+ h = (h & hashmask(10));
+In which case, the hash table should have hashsize(10) elements.
+
+If you are hashing n strings (ub1 **)k, do it like this:
+ for (i=0, h=0; i<n; ++i) h = lookup( k[i], len[i], h);
+
+By Bob Jenkins, 1996. bob_jenkins@burtleburtle.net. You may use this
+code any way you wish, private, educational, or commercial.
+
+See http://burtleburtle.net/bob/hash/evahash.html
+Use for hash table lookup, or anything where one collision in 2^32 is
+acceptable. Do NOT use for cryptographic purposes.
+--------------------------------------------------------------------
+*/
+
+ub4 lookup( k, length, level)
+register ub1 *k; /* the key */
+register ub4 length; /* the length of the key */
+register ub4 level; /* the previous hash, or an arbitrary value */
+{
+ register ub4 a,b,c,len;
+
+ /* Set up the internal state */
+ len = length;
+ a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
+ c = level; /* the previous hash value */
+
+ /*---------------------------------------- handle most of the key */
+ while (len >= 12)
+ {
+ a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24));
+ b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24));
+ c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24));
+ mix(a,b,c);
+ k += 12; len -= 12;
+ }
+
+ /*------------------------------------- handle the last 11 bytes */
+ c += length;
+ switch(len) /* all the case statements fall through */
+ {
+ case 11: c+=((ub4)k[10]<<24);
+ case 10: c+=((ub4)k[9]<<16);
+ case 9 : c+=((ub4)k[8]<<8);
+ /* the first byte of c is reserved for the length */
+ case 8 : b+=((ub4)k[7]<<24);
+ case 7 : b+=((ub4)k[6]<<16);
+ case 6 : b+=((ub4)k[5]<<8);
+ case 5 : b+=k[4];
+ case 4 : a+=((ub4)k[3]<<24);
+ case 3 : a+=((ub4)k[2]<<16);
+ case 2 : a+=((ub4)k[1]<<8);
+ case 1 : a+=k[0];
+ /* case 0: nothing left to add */
+ }
+ mix(a,b,c);
+ /*-------------------------------------------- report the result */
+ return c;
+}
+
+
+/*
+--------------------------------------------------------------------
+mixc -- mixc 8 4-bit values as quickly and thoroughly as possible.
+Repeating mix() three times achieves avalanche.
+Repeating mix() four times eliminates all funnels and all
+ characteristics stronger than 2^{-11}.
+--------------------------------------------------------------------
+*/
+#define mixc(a,b,c,d,e,f,g,h) \
+{ \
+ a^=b<<11; d+=a; b+=c; \
+ b^=c>>2; e+=b; c+=d; \
+ c^=d<<8; f+=c; d+=e; \
+ d^=e>>16; g+=d; e+=f; \
+ e^=f<<10; h+=e; f+=g; \
+ f^=g>>4; a+=f; g+=h; \
+ g^=h<<8; b+=g; h+=a; \
+ h^=a>>9; c+=h; a+=b; \
+}
+
+/*
+--------------------------------------------------------------------
+checksum() -- hash a variable-length key into a 256-bit value
+ k : the key (the unaligned variable-length array of bytes)
+ len : the length of the key, counting by bytes
+ state : an array of CHECKSTATE 4-byte values (256 bits)
+The state is the checksum. Every bit of the key affects every bit of
+the state. There are no funnels. About 112+6.875len instructions.
+
+If you are hashing n strings (ub1 **)k, do it like this:
+ for (i=0; i<8; ++i) state[i] = 0x9e3779b9;
+ for (i=0, h=0; i<n; ++i) checksum( k[i], len[i], state);
+
+See http://burtleburtle.net/bob/hash/evahash.html
+Use to detect changes between revisions of documents, assuming nobody
+is trying to cause collisions. Do NOT use for cryptography.
+--------------------------------------------------------------------
+*/
+void checksum( k, len, state)
+register ub1 *k;
+register ub4 len;
+register ub4 *state;
+{
+ register ub4 a,b,c,d,e,f,g,h,length;
+
+ /* Use the length and level; add in the golden ratio. */
+ length = len;
+ a=state[0]; b=state[1]; c=state[2]; d=state[3];
+ e=state[4]; f=state[5]; g=state[6]; h=state[7];
+
+ /*---------------------------------------- handle most of the key */
+ while (len >= 32)
+ {
+ a += (k[0] +(k[1]<<8) +(k[2]<<16) +(k[3]<<24));
+ b += (k[4] +(k[5]<<8) +(k[6]<<16) +(k[7]<<24));
+ c += (k[8] +(k[9]<<8) +(k[10]<<16)+(k[11]<<24));
+ d += (k[12]+(k[13]<<8)+(k[14]<<16)+(k[15]<<24));
+ e += (k[16]+(k[17]<<8)+(k[18]<<16)+(k[19]<<24));
+ f += (k[20]+(k[21]<<8)+(k[22]<<16)+(k[23]<<24));
+ g += (k[24]+(k[25]<<8)+(k[26]<<16)+(k[27]<<24));
+ h += (k[28]+(k[29]<<8)+(k[30]<<16)+(k[31]<<24));
+ mixc(a,b,c,d,e,f,g,h);
+ mixc(a,b,c,d,e,f,g,h);
+ mixc(a,b,c,d,e,f,g,h);
+ mixc(a,b,c,d,e,f,g,h);
+ k += 32; len -= 32;
+ }
+
+ /*------------------------------------- handle the last 31 bytes */
+ h += length;
+ switch(len)
+ {
+ case 31: h+=(k[30]<<24);
+ case 30: h+=(k[29]<<16);
+ case 29: h+=(k[28]<<8);
+ case 28: g+=(k[27]<<24);
+ case 27: g+=(k[26]<<16);
+ case 26: g+=(k[25]<<8);
+ case 25: g+=k[24];
+ case 24: f+=(k[23]<<24);
+ case 23: f+=(k[22]<<16);
+ case 22: f+=(k[21]<<8);
+ case 21: f+=k[20];
+ case 20: e+=(k[19]<<24);
+ case 19: e+=(k[18]<<16);
+ case 18: e+=(k[17]<<8);
+ case 17: e+=k[16];
+ case 16: d+=(k[15]<<24);
+ case 15: d+=(k[14]<<16);
+ case 14: d+=(k[13]<<8);
+ case 13: d+=k[12];
+ case 12: c+=(k[11]<<24);
+ case 11: c+=(k[10]<<16);
+ case 10: c+=(k[9]<<8);
+ case 9 : c+=k[8];
+ case 8 : b+=(k[7]<<24);
+ case 7 : b+=(k[6]<<16);
+ case 6 : b+=(k[5]<<8);
+ case 5 : b+=k[4];
+ case 4 : a+=(k[3]<<24);
+ case 3 : a+=(k[2]<<16);
+ case 2 : a+=(k[1]<<8);
+ case 1 : a+=k[0];
+ }
+ mixc(a,b,c,d,e,f,g,h);
+ mixc(a,b,c,d,e,f,g,h);
+ mixc(a,b,c,d,e,f,g,h);
+ mixc(a,b,c,d,e,f,g,h);
+
+ /*-------------------------------------------- report the result */
+ state[0]=a; state[1]=b; state[2]=c; state[3]=d;
+ state[4]=e; state[5]=f; state[6]=g; state[7]=h;
+}
diff --git a/tools/codegen/core/perfect/lookupa.h b/tools/codegen/core/perfect/lookupa.h
new file mode 100644
index 0000000000..0b27db680d
--- /dev/null
+++ b/tools/codegen/core/perfect/lookupa.h
@@ -0,0 +1,24 @@
+/*
+------------------------------------------------------------------------------
+By Bob Jenkins, September 1996.
+lookupa.h, a hash function for table lookup, same function as lookup.c.
+Use this code in any way you wish. Public Domain. It has no warranty.
+Source is http://burtleburtle.net/bob/c/lookupa.h
+------------------------------------------------------------------------------
+*/
+
+#ifndef STANDARD
+#include "standard.h"
+#endif
+
+#ifndef LOOKUPA
+#define LOOKUPA
+
+#define CHECKSTATE 8
+#define hashsize(n) ((ub4)1<<(n))
+#define hashmask(n) (hashsize(n)-1)
+
+ub4 lookup(/*_ ub1 *k, ub4 length, ub4 level _*/);
+void checksum(/*_ ub1 *k, ub4 length, ub4 *state _*/);
+
+#endif /* LOOKUPA */
diff --git a/tools/codegen/core/perfect/perfect.c b/tools/codegen/core/perfect/perfect.c
new file mode 100644
index 0000000000..67fd2fd262
--- /dev/null
+++ b/tools/codegen/core/perfect/perfect.c
@@ -0,0 +1,1367 @@
+/*
+------------------------------------------------------------------------------
+perfect.c: code to generate code for a hash for perfect hashing.
+(c) Bob Jenkins, September 1996, December 1999
+You may use this code in any way you wish, and it is free. No warranty.
+I hereby place this in the public domain.
+Source is http://burtleburtle.net/bob/c/perfect.c
+
+This generates a minimal perfect hash function. That means, given a
+set of n keys, this determines a hash function that maps each of
+those keys into a value in 0..n-1 with no collisions.
+
+The perfect hash function first uses a normal hash function on the key
+to determine (a,b) such that the pair (a,b) is distinct for all
+keys, then it computes a^scramble[tab[b]] to get the final perfect hash.
+tab[] is an array of 1-byte values and scramble[] is a 256-term array of
+2-byte or 4-byte values. If there are n keys, the length of tab[] is a
+power of two between n/3 and n.
+
+I found the idea of computing distinct (a,b) values in "Practical minimal
+perfect hash functions for large databases", Fox, Heath, Chen, and Daoud,
+Communications of the ACM, January 1992. They found the idea in Chichelli
+(CACM Jan 1980). Beyond that, our methods differ.
+
+The key is hashed to a pair (a,b) where a in 0..*alen*-1 and b in
+0..*blen*-1. A fast hash function determines both a and b
+simultaneously. Any decent hash function is likely to produce
+hashes so that (a,b) is distinct for all pairs. I try the hash
+using different values of *salt* until all pairs are distinct.
+
+The final hash is (a XOR scramble[tab[b]]). *scramble* is a
+predetermined mapping of 0..255 into 0..smax-1. *tab* is an
+array that we fill in in such a way as to make the hash perfect.
+
+First we fill in all values of *tab* that are used by more than one
+key. We try all possible values for each position until one works.
+
+This leaves m unmapped keys and m values that something could hash to.
+If you treat unmapped keys as lefthand nodes and unused hash values
+as righthand nodes, and draw a line connecting each key to each hash
+value it could map to, you get a bipartite graph. We attempt to
+find a perfect matching in this graph. If we succeed, we have
+determined a perfect hash for the whole set of keys.
+
+*scramble* is used because (a^tab[i]) clusters keys around *a*.
+------------------------------------------------------------------------------
+*/
+
+#ifndef STANDARD
+#include "standard.h"
+#endif
+#ifndef LOOKUPA
+#include "lookupa.h"
+#endif
+#ifndef RECYCLE
+#include "recycle.h"
+#endif
+#ifndef PERFECT
+#include "perfect.h"
+#endif
+
+/*
+------------------------------------------------------------------------------
+Find the mapping that will produce a perfect hash
+------------------------------------------------------------------------------
+*/
+
+/* return the ceiling of the log (base 2) of val */
+ub4 mylog2(val)
+ub4 val;
+{
+ ub4 i;
+ for (i=0; ((ub4)1<<i) < val; ++i)
+ ;
+ return i;
+}
+
+/* compute p(x), where p is a permutation of 0..(1<<nbits)-1 */
+/* permute(0)=0. This is intended and useful. */
+static ub4 permute(x, nbits)
+ub4 x; /* input, a value in some range */
+ub4 nbits; /* input, number of bits in range */
+{
+ int i;
+ int mask = ((ub4)1<<nbits)-1; /* all ones */
+ int const2 = 1+nbits/2;
+ int const3 = 1+nbits/3;
+ int const4 = 1+nbits/4;
+ int const5 = 1+nbits/5;
+ for (i=0; i<20; ++i)
+ {
+ x = (x+(x<<const2)) & mask;
+ x = (x^(x>>const3));
+ x = (x+(x<<const4)) & mask;
+ x = (x^(x>>const5));
+ }
+ return x;
+}
+
+/* initialize scramble[] with distinct random values in 0..smax-1 */
+static void scrambleinit(scramble, smax)
+ub4 *scramble; /* hash is a^scramble[tab[b]] */
+ub4 smax; /* scramble values should be in 0..smax-1 */
+{
+ ub4 i;
+
+ /* fill scramble[] with distinct random integers in 0..smax-1 */
+ for (i=0; i<SCRAMBLE_LEN; ++i)
+ {
+ scramble[i] = permute(i, mylog2(smax));
+ }
+}
+
+/*
+ * Check if key1 and key2 are the same.
+ * We already checked (a,b) are the same.
+ */
+static void checkdup(key1, key2, form)
+key *key1;
+key *key2;
+hashform *form;
+{
+ switch(form->hashtype)
+ {
+ case STRING_HT:
+ if ((key1->len_k == key2->len_k) &&
+ !memcmp(key1->name_k, key2->name_k, (size_t)key1->len_k))
+ {
+ fprintf(stderr, "perfect.c: Duplicates keys! %.*s\n",
+ key1->len_k, key1->name_k);
+ exit(SUCCESS);
+ }
+ break;
+ case INT_HT:
+ if (key1->hash_k == key2->hash_k)
+ {
+ fprintf(stderr, "perfect.c: Duplicate keys! %.8lx\n", key1->hash_k);
+ exit(SUCCESS);
+ }
+ break;
+ case AB_HT:
+ fprintf(stderr, "perfect.c: Duplicate keys! %.8lx %.8lx\n",
+ key1->a_k, key1->b_k);
+ exit(SUCCESS);
+ break;
+ default:
+ fprintf(stderr, "perfect.c: Illegal hash type %ld\n", (ub4)form->hashtype);
+ exit(SUCCESS);
+ break;
+ }
+}
+
+
+/*
+ * put keys in tabb according to key->b_k
+ * check if the initial hash might work
+ */
+static int inittab(tabb, blen, keys, form, complete)
+bstuff *tabb; /* output, list of keys with b for (a,b) */
+ub4 blen; /* length of tabb */
+key *keys; /* list of keys already hashed */
+hashform *form; /* user directives */
+int complete; /* TRUE means to complete init despite collisions */
+{
+ int nocollision = TRUE;
+ key *mykey;
+
+ memset((void *)tabb, 0, (size_t)(sizeof(bstuff)*blen));
+
+ /* Two keys with the same (a,b) guarantees a collision */
+ for (mykey=keys; mykey; mykey=mykey->next_k)
+ {
+ key *otherkey;
+
+ for (otherkey=tabb[mykey->b_k].list_b;
+ otherkey;
+ otherkey=otherkey->nextb_k)
+ {
+ if (mykey->a_k == otherkey->a_k)
+ {
+ nocollision = FALSE;
+ checkdup(mykey, otherkey, form);
+ if (!complete)
+ return FALSE;
+ }
+ }
+ ++tabb[mykey->b_k].listlen_b;
+ mykey->nextb_k = tabb[mykey->b_k].list_b;
+ tabb[mykey->b_k].list_b = mykey;
+ }
+
+ /* no two keys have the same (a,b) pair */
+ return nocollision;
+}
+
+
+/* Do the initial hash for normal mode (use lookup and checksum) */
+static void initnorm(keys, alen, blen, smax, salt, final)
+key *keys; /* list of all keys */
+ub4 alen; /* (a,b) has a in 0..alen-1, a power of 2 */
+ub4 blen; /* (a,b) has b in 0..blen-1, a power of 2 */
+ub4 smax; /* maximum range of computable hash values */
+ub4 salt; /* used to initialize the hash function */
+gencode *final; /* output, code for the final hash */
+{
+ key *mykey;
+ if (mylog2(alen)+mylog2(blen) > UB4BITS)
+ {
+ ub4 initlev = salt*0x9e3779b9; /* the golden ratio; an arbitrary value */
+
+ for (mykey=keys; mykey; mykey=mykey->next_k)
+ {
+ ub4 i, state[CHECKSTATE];
+ for (i=0; i<CHECKSTATE; ++i) state[i] = initlev;
+ checksum( mykey->name_k, mykey->len_k, state);
+ mykey->a_k = state[0]&(alen-1);
+ mykey->b_k = state[1]&(blen-1);
+ }
+ final->used = 4;
+ sprintf(final->line[0],
+ " ub4 i,state[CHECKSTATE],rsl;\n");
+ sprintf(final->line[1],
+ " for (i=0; i<CHECKSTATE; ++i) state[i]=0x%lx;\n",initlev);
+ sprintf(final->line[2],
+ " checksum(key, len, state);\n");
+ sprintf(final->line[3],
+ " rsl = ((state[0]&0x%x)^scramble[tab[state[1]&0x%x]]);\n",
+ alen-1, blen-1);
+ }
+ else
+ {
+ ub4 loga = mylog2(alen); /* log based 2 of blen */
+ ub4 initlev = salt*0x9e3779b9; /* the golden ratio; an arbitrary value */
+
+ for (mykey=keys; mykey; mykey=mykey->next_k)
+ {
+ ub4 hash = lookup(mykey->name_k, mykey->len_k, initlev);
+ mykey->a_k = (loga > 0) ? hash>>(UB4BITS-loga) : 0;
+ mykey->b_k = (blen > 1) ? hash&(blen-1) : 0;
+ }
+ final->used = 2;
+ sprintf(final->line[0],
+ " ub4 rsl, val = lookup(key, len, 0x%lx);\n", initlev);
+ if (smax <= 1)
+ {
+ sprintf(final->line[1], " rsl = 0;\n");
+ }
+ else if (mylog2(alen) == 0)
+ {
+ sprintf(final->line[1], " rsl = tab[val&0x%x];\n", blen-1);
+ }
+ else if (blen < USE_SCRAMBLE)
+ {
+ sprintf(final->line[1], " rsl = ((val>>%ld)^tab[val&0x%x]);\n",
+ UB4BITS-mylog2(alen), blen-1);
+ }
+ else
+ {
+ sprintf(final->line[1], " rsl = ((val>>%ld)^scramble[tab[val&0x%x]]);\n",
+ UB4BITS-mylog2(alen), blen-1);
+ }
+ }
+}
+
+
+
+/* Do initial hash for inline mode */
+static void initinl(keys, alen, blen, smax, salt, final)
+key *keys; /* list of all keys */
+ub4 alen; /* (a,b) has a in 0..alen-1, a power of 2 */
+ub4 blen; /* (a,b) has b in 0..blen-1, a power of 2 */
+ub4 smax; /* range of computable hash values */
+ub4 salt; /* used to initialize the hash function */
+gencode *final; /* generated code for final hash */
+{
+ key *mykey;
+ ub4 amask = alen-1;
+ ub4 blog = mylog2(blen);
+ ub4 initval = salt*0x9e3779b9; /* the golden ratio; an arbitrary value */
+
+ /* It's more important to have b uniform than a, so b is the low bits */
+ for (mykey = keys; mykey != (key *)0; mykey = mykey->next_k)
+ {
+ ub4 hash = initval;
+ ub4 i;
+ for (i=0; i<mykey->len_k; ++i)
+ {
+ hash = (mykey->name_k[i] ^ hash) + ((hash<<(UB4BITS-6))+(hash>>6));
+ }
+ mykey->hash_k = hash;
+ mykey->a_k = (alen > 1) ? (hash & amask) : 0;
+ mykey->b_k = (blen > 1) ? (hash >> (UB4BITS-blog)) : 0;
+ }
+ final->used = 1;
+ if (smax <= 1)
+ {
+ sprintf(final->line[0], " ub4 rsl = 0;\n");
+ }
+ else if (blen < USE_SCRAMBLE)
+ {
+ sprintf(final->line[0], " ub4 rsl = ((val & 0x%lx) ^ tab[val >> %ld]);\n",
+ amask, UB4BITS-blog);
+ }
+ else
+ {
+ sprintf(final->line[0], " ub4 rsl = ((val & 0x%lx) ^ scramble[tab[val >> %ld]]);\n",
+ amask, UB4BITS-blog);
+ }
+}
+
+
+/*
+ * Run a hash function on the key to get a and b
+ * Returns:
+ * 0: didn't find distinct (a,b) for all keys
+ * 1: found distinct (a,b) for all keys, put keys in tabb[]
+ * 2: found a perfect hash, no need to do any more work
+ */
+static ub4 initkey(keys, nkeys, tabb, alen, blen, smax, salt, form, final)
+key *keys; /* list of all keys */
+ub4 nkeys; /* total number of keys */
+bstuff *tabb; /* stuff indexed by b */
+ub4 alen; /* (a,b) has a in 0..alen-1, a power of 2 */
+ub4 blen; /* (a,b) has b in 0..blen-1, a power of 2 */
+ub4 smax; /* range of computable hash values */
+ub4 salt; /* used to initialize the hash function */
+hashform *form; /* user directives */
+gencode *final; /* code for final hash */
+{
+ ub4 finished;
+
+ /* Do the initial hash of the keys */
+ switch(form->mode)
+ {
+ case NORMAL_HM:
+ initnorm(keys, alen, blen, smax, salt, final);
+ break;
+ case INLINE_HM:
+ initinl(keys, alen, blen, smax, salt, final);
+ break;
+ case HEX_HM:
+ case DECIMAL_HM:
+ finished = inithex(keys, nkeys, alen, blen, smax, salt, final, form);
+ if (finished) return 2;
+ break;
+ default:
+ fprintf(stderr, "fatal error: illegal mode\n");
+ exit(1);
+ }
+
+ if (nkeys <= 1)
+ {
+ final->used = 1;
+ sprintf(final->line[0], " ub4 rsl = 0;\n");
+ return 2;
+ }
+
+ return inittab(tabb, blen, keys, form, FALSE);
+}
+
+/* Print an error message and exit if there are duplicates */
+static void duplicates(tabb, blen, keys, form)
+bstuff *tabb; /* array of lists of keys with the same b */
+ub4 blen; /* length of tabb, a power of 2 */
+key *keys;
+hashform *form; /* user directives */
+{
+ ub4 i;
+ key *key1;
+ key *key2;
+
+ (void)inittab(tabb, blen, keys, form, TRUE);
+
+ /* for each b, do nested loops through key list looking for duplicates */
+ for (i=0; i<blen; ++i)
+ for (key1=tabb[i].list_b; key1; key1=key1->nextb_k)
+ for (key2=key1->nextb_k; key2; key2=key2->nextb_k)
+ checkdup(key1, key2, form);
+}
+
+
+/* Try to apply an augmenting list */
+static int apply(tabb, tabh, tabq, blen, scramble, tail, rollback)
+bstuff *tabb;
+hstuff *tabh;
+qstuff *tabq;
+ub4 blen;
+ub4 *scramble;
+ub4 tail;
+int rollback; /* FALSE applies augmenting path, TRUE rolls back */
+{
+ ub4 hash;
+ key *mykey;
+ bstuff *pb;
+ ub4 child;
+ ub4 parent;
+ ub4 stabb; /* scramble[tab[b]] */
+
+ /* walk from child to parent */
+ for (child=tail-1; child; child=parent)
+ {
+ parent = tabq[child].parent_q; /* find child's parent */
+ pb = tabq[parent].b_q; /* find parent's list of siblings */
+
+ /* erase old hash values */
+ stabb = scramble[pb->val_b];
+ for (mykey=pb->list_b; mykey; mykey=mykey->nextb_k)
+ {
+ hash = mykey->a_k^stabb;
+ if (mykey == tabh[hash].key_h)
+ { /* erase hash for all of child's siblings */
+ tabh[hash].key_h = (key *)0;
+ }
+ }
+
+ /* change pb->val_b, which will change the hashes of all parent siblings */
+ pb->val_b = (rollback ? tabq[child].oldval_q : tabq[child].newval_q);
+
+ /* set new hash values */
+ stabb = scramble[pb->val_b];
+ for (mykey=pb->list_b; mykey; mykey=mykey->nextb_k)
+ {
+ hash = mykey->a_k^stabb;
+ if (rollback)
+ {
+ if (parent == 0) continue; /* root never had a hash */
+ }
+ else if (tabh[hash].key_h)
+ {
+ /* very rare: roll back any changes */
+ (void *)apply(tabb, tabh, tabq, blen, scramble, tail, TRUE);
+ return FALSE; /* failure, collision */
+ }
+ tabh[hash].key_h = mykey;
+ }
+ }
+ return TRUE;
+}
+
+
+/*
+-------------------------------------------------------------------------------
+augment(): Add item to the mapping.
+
+Construct a spanning tree of *b*s with *item* as root, where each
+parent can have all its hashes changed (by some new val_b) with
+at most one collision, and each child is the b of that collision.
+
+I got this from Tarjan's "Data Structures and Network Algorithms". The
+path from *item* to a *b* that can be remapped with no collision is
+an "augmenting path". Change values of tab[b] along the path so that
+the unmapped key gets mapped and the unused hash value gets used.
+
+Assuming 1 key per b, if m out of n hash values are still unused,
+you should expect the transitive closure to cover n/m nodes before
+an unused node is found. Sum(i=1..n)(n/i) is about nlogn, so expect
+this approach to take about nlogn time to map all single-key b's.
+-------------------------------------------------------------------------------
+*/
+static int augment(tabb, tabh, tabq, blen, scramble, smax, item, nkeys,
+ highwater, form)
+bstuff *tabb; /* stuff indexed by b */
+hstuff *tabh; /* which key is associated with which hash, indexed by hash */
+qstuff *tabq; /* queue of *b* values, this is the spanning tree */
+ub4 blen; /* length of tabb */
+ub4 *scramble; /* final hash is a^scramble[tab[b]] */
+ub4 smax; /* highest value in scramble */
+bstuff *item; /* &tabb[b] for the b to be mapped */
+ub4 nkeys; /* final hash must be in 0..nkeys-1 */
+ub4 highwater; /* a value higher than any now in tabb[].water_b */
+hashform *form; /* TRUE if we should do a minimal perfect hash */
+{
+ ub4 q; /* current position walking through the queue */
+ ub4 tail; /* tail of the queue. 0 is the head of the queue. */
+ ub4 limit=((blen < USE_SCRAMBLE) ? smax : UB1MAXVAL+1);
+ ub4 highhash = ((form->perfect == MINIMAL_HP) ? nkeys : smax);
+ int trans = (form->speed == SLOW_HS || form->perfect == MINIMAL_HP);
+
+ /* initialize the root of the spanning tree */
+ tabq[0].b_q = item;
+ tail = 1;
+
+ /* construct the spanning tree by walking the queue, add children to tail */
+ for (q=0; q<tail; ++q)
+ {
+ bstuff *myb = tabq[q].b_q; /* the b for this node */
+ ub4 i; /* possible value for myb->val_b */
+
+ if (!trans && (q == 1))
+ break; /* don't do transitive closure */
+
+ for (i=0; i<limit; ++i)
+ {
+ bstuff *childb = (bstuff *)0; /* the b that this i maps to */
+ key *mykey; /* for walking through myb's keys */
+
+ for (mykey = myb->list_b; mykey; mykey=mykey->nextb_k)
+ {
+ key *childkey;
+ ub4 hash = mykey->a_k^scramble[i];
+
+ if (hash >= highhash) break; /* out of bounds */
+ childkey = tabh[hash].key_h;
+
+ if (childkey)
+ {
+ bstuff *hitb = &tabb[childkey->b_k];
+
+ if (childb)
+ {
+ if (childb != hitb) break; /* hit at most one child b */
+ }
+ else
+ {
+ childb = hitb; /* remember this as childb */
+ if (childb->water_b == highwater) break; /* already explored */
+ }
+ }
+ }
+ if (mykey) continue; /* myb with i has multiple collisions */
+
+ /* add childb to the queue of reachable things */
+ if (childb) childb->water_b = highwater;
+ tabq[tail].b_q = childb;
+ tabq[tail].newval_q = i; /* how to make parent (myb) use this hash */
+ tabq[tail].oldval_q = myb->val_b; /* need this for rollback */
+ tabq[tail].parent_q = q;
+ ++tail;
+
+ if (!childb)
+ { /* found an *i* with no collisions? */
+ /* try to apply the augmenting path */
+ if (apply(tabb, tabh, tabq, blen, scramble, tail, FALSE))
+ return TRUE; /* success, item was added to the perfect hash */
+
+ --tail; /* don't know how to handle such a child! */
+ }
+ }
+ }
+ return FALSE;
+}
+
+
+/* find a mapping that makes this a perfect hash */
+static int perfect(tabb, tabh, tabq, blen, smax, scramble, nkeys, form)
+bstuff *tabb;
+hstuff *tabh;
+qstuff *tabq;
+ub4 blen;
+ub4 smax;
+ub4 *scramble;
+ub4 nkeys;
+hashform *form;
+{
+ ub4 maxkeys; /* maximum number of keys for any b */
+ ub4 i, j;
+
+ /* clear any state from previous attempts */
+ memset((void *)tabh, 0,
+ (size_t)(sizeof(hstuff)*
+ ((form->perfect == MINIMAL_HP) ? nkeys : smax)));
+ memset((void *)tabq, 0, (size_t)(sizeof(qstuff)*(blen+1)));
+
+ for (maxkeys=0,i=0; i<blen; ++i)
+ if (tabb[i].listlen_b > maxkeys)
+ maxkeys = tabb[i].listlen_b;
+
+ /* In descending order by number of keys, map all *b*s */
+ for (j=maxkeys; j>0; --j)
+ for (i=0; i<blen; ++i)
+ if (tabb[i].listlen_b == j)
+ if (!augment(tabb, tabh, tabq, blen, scramble, smax, &tabb[i], nkeys,
+ i+1, form))
+ {
+ printf("fail to map group of size %ld for tab size %ld\n", j, blen);
+ return FALSE;
+ }
+
+ /* Success! We found a perfect hash of all keys into 0..nkeys-1. */
+ return TRUE;
+}
+
+
+/*
+ * Simple case: user gave (a,b). No more mixing, no guessing alen or blen.
+ * This assumes a,b reside in (key->a_k, key->b_k), and final->form == AB_HK.
+ */
+static void hash_ab(tabb, alen, blen, salt, final,
+ scramble, smax, keys, nkeys, form)
+bstuff **tabb; /* output, tab[] of the perfect hash, length *blen */
+ub4 *alen; /* output, 0..alen-1 is range for a of (a,b) */
+ub4 *blen; /* output, 0..blen-1 is range for b of (a,b) */
+ub4 *salt; /* output, initializes initial hash */
+gencode *final; /* code for final hash */
+ub4 *scramble; /* input, hash = a^scramble[tab[b]] */
+ub4 *smax; /* input, scramble[i] in 0..smax-1 */
+key *keys; /* input, keys to hash */
+ub4 nkeys; /* input, number of keys being hashed */
+hashform *form; /* user directives */
+{
+ hstuff *tabh;
+ qstuff *tabq;
+ key *mykey;
+ ub4 i;
+ int used_tab;
+
+ /* initially make smax the first power of two bigger than nkeys */
+ *smax = ((ub4)1<<mylog2(nkeys));
+ scrambleinit(scramble, *smax);
+
+ /* set *alen and *blen based on max A and B from user */
+ *alen = 1;
+ *blen = 1;
+ for (mykey = keys; mykey != (key *)0; mykey = mykey->next_k)
+ {
+ while (*alen <= mykey->a_k) *alen *= 2;
+ while (*blen <= mykey->b_k) *blen *= 2;
+ }
+ if (*alen > 2**smax)
+ {
+ fprintf(stderr,
+ "perfect.c: Can't deal with (A,B) having A bigger than twice \n");
+ fprintf(stderr,
+ " the smallest power of two greater or equal to any legal hash.\n");
+ exit(SUCCESS);
+ }
+
+ /* allocate working memory */
+ *tabb = (bstuff *)malloc((size_t)(sizeof(bstuff)*(*blen)));
+ tabq = (qstuff *)remalloc(sizeof(qstuff)*(*blen+1), "perfect.c, tabq");
+ tabh = (hstuff *)remalloc(sizeof(hstuff)*(form->perfect == MINIMAL_HP ?
+ nkeys : *smax),
+ "perfect.c, tabh");
+
+ /* check that (a,b) are distinct and put them in tabb indexed by b */
+ (void)inittab(*tabb, *blen, keys, form, FALSE);
+
+ /* try with smax */
+ if (!perfect(*tabb, tabh, tabq, *blen, *smax, scramble, nkeys, form))
+ {
+ if (form->perfect == MINIMAL_HP)
+ {
+ printf("fatal error: Cannot find perfect hash for user (A,B) pairs\n");
+ exit(SUCCESS);
+ }
+ else
+ {
+ /* try with 2*smax */
+ free((void *)tabh);
+ *smax = *smax * 2;
+ scrambleinit(scramble, *smax);
+ tabh = (hstuff *)remalloc(sizeof(hstuff)*(form->perfect == MINIMAL_HP ?
+ nkeys : *smax),
+ "perfect.c, tabh");
+ if (!perfect(*tabb, tabh, tabq, *blen, *smax, scramble, nkeys, form))
+ {
+ printf("fatal error: Cannot find perfect hash for user (A,B) pairs\n");
+ exit(SUCCESS);
+ }
+ }
+ }
+
+ /* check if tab[] was really needed */
+ for (i=0; i<*blen; ++i)
+ {
+ if ((*tabb)[i].val_b != 0) break; /* assumes permute(0) == 0 */
+ }
+ used_tab = (i < *blen);
+
+ /* write the code for the perfect hash */
+ *salt = 1;
+ final->used = 1;
+ if (!used_tab)
+ {
+ sprintf(final->line[0], " ub4 rsl = a;\n");
+ }
+ else if (*blen < USE_SCRAMBLE)
+ {
+ sprintf(final->line[0], " ub4 rsl = (a ^ tab[b]);\n");
+ }
+ else
+ {
+ sprintf(final->line[0], " ub4 rsl = (a ^ scramble[tab[b]]);\n");
+ }
+
+ printf("success, found a perfect hash\n");
+
+ free((void *)tabq);
+ free((void *)tabh);
+}
+
+
+/* guess initial values for alen and blen */
+static void initalen(alen, blen, smax, nkeys, form)
+ub4 *alen; /* output, initial alen */
+ub4 *blen; /* output, initial blen */
+ub4 *smax; /* input, power of two greater or equal to max hash value */
+ub4 nkeys; /* number of keys being hashed */
+hashform *form; /* user directives */
+{
+ /*
+ * Find initial *alen, *blen
+ * Initial alen and blen values were found empirically. Some factors:
+ *
+ * If smax<256 there is no scramble, so tab[b] needs to cover 0..smax-1.
+ *
+ * alen and blen must be powers of 2 because the values in 0..alen-1 and
+ * 0..blen-1 are produced by applying a bitmask to the initial hash function.
+ *
+ * alen must be less than smax, in fact less than nkeys, because otherwise
+ * there would often be no i such that a^scramble[i] is in 0..nkeys-1 for
+ * all the *a*s associated with a given *b*, so there would be no legal
+ * value to assign to tab[b]. This only matters when we're doing a minimal
+ * perfect hash.
+ *
+ * It takes around 800 trials to find distinct (a,b) with nkey=smax*(5/8)
+ * and alen*blen = smax*smax/32.
+ *
+ * Values of blen less than smax/4 never work, and smax/2 always works.
+ *
+ * We want blen as small as possible because it is the number of bytes in
+ * the huge array we must create for the perfect hash.
+ *
+ * When nkey <= smax*(5/8), blen=smax/4 works much more often with
+ * alen=smax/8 than with alen=smax/4. Above smax*(5/8), blen=smax/4
+ * doesn't seem to care whether alen=smax/8 or alen=smax/4. I think it
+ * has something to do with 5/8 = 1/8 * 5. For example examine 80000,
+ * 85000, and 90000 keys with different values of alen. This only matters
+ * if we're doing a minimal perfect hash.
+ *
+ * When alen*blen <= 1<<UB4BITS, the initial hash must produce one integer.
+ * Bigger than that it must produce two integers, which increases the
+ * cost of the hash per character hashed.
+ */
+ if (form->perfect == NORMAL_HP)
+ {
+ if ((form->speed == FAST_HS) && (nkeys > *smax*0.8))
+ {
+ *smax = *smax * 2;
+ }
+
+ *alen = ((form->hashtype==INT_HT) && *smax>131072) ?
+ ((ub4)1<<(UB4BITS-mylog2(*blen))) : /* distinct keys => distinct (A,B) */
+ *smax; /* no reason to restrict alen to smax/2 */
+ if ((form->hashtype == INT_HT) && *smax < 32)
+ *blen = *smax; /* go for function speed not space */
+ else if (*smax/4 <= (1<<14))
+ *blen = ((nkeys <= *smax*0.56) ? *smax/32 :
+ (nkeys <= *smax*0.74) ? *smax/16 : *smax/8);
+ else
+ *blen = ((nkeys <= *smax*0.6) ? *smax/16 :
+ (nkeys <= *smax*0.8) ? *smax/8 : *smax/4);
+
+ if ((form->speed == FAST_HS) && (*blen < *smax/8))
+ *blen = *smax/8;
+
+ if (*alen < 1) *alen = 1;
+ if (*blen < 1) *blen = 1;
+ }
+ else
+ {
+ switch(mylog2(*smax))
+ {
+ case 0:
+ *alen = 1;
+ *blen = 1;
+ case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
+ *alen = (form->perfect == NORMAL_HP) ? *smax : *smax/2;
+ *blen = *smax/2;
+ break;
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ if (form->speed == FAST_HS)
+ {
+ *alen = *smax/2;
+ *blen = *smax/4;
+ }
+ else if (*smax/4 < USE_SCRAMBLE)
+ {
+ *alen = ((nkeys <= *smax*0.52) ? *smax/8 : *smax/4);
+ *blen = ((nkeys <= *smax*0.52) ? *smax/8 : *smax/4);
+ }
+ else
+ {
+ *alen = ((nkeys <= *smax*(5.0/8.0)) ? *smax/8 :
+ (nkeys <= *smax*(3.0/4.0)) ? *smax/4 : *smax/2);
+ *blen = *smax/4; /* always give the small size a shot */
+ }
+ break;
+ case 18:
+ if (form->speed == FAST_HS)
+ {
+ *alen = *smax/2;
+ *blen = *smax/2;
+ }
+ else
+ {
+ *alen = *smax/8; /* never require the multiword hash */
+ *blen = (nkeys <= *smax*(5.0/8.0)) ? *smax/4 : *smax/2;
+ }
+ break;
+ case 19:
+ case 20:
+ *alen = (nkeys <= *smax*(5.0/8.0)) ? *smax/8 : *smax/2;
+ *blen = (nkeys <= *smax*(5.0/8.0)) ? *smax/4 : *smax/2;
+ break;
+ default:
+ *alen = *smax/2; /* just find a hash as quick as possible */
+ *blen = *smax/2; /* we'll be thrashing virtual memory at this size */
+ break;
+ }
+ }
+}
+
+/*
+** Try to find a perfect hash function.
+** Return the successful initializer for the initial hash.
+** Return 0 if no perfect hash could be found.
+*/
+void findhash(tabb, alen, blen, salt, final,
+ scramble, smax, keys, nkeys, form)
+bstuff **tabb; /* output, tab[] of the perfect hash, length *blen */
+ub4 *alen; /* output, 0..alen-1 is range for a of (a,b) */
+ub4 *blen; /* output, 0..blen-1 is range for b of (a,b) */
+ub4 *salt; /* output, initializes initial hash */
+gencode *final; /* code for final hash */
+ub4 *scramble; /* input, hash = a^scramble[tab[b]] */
+ub4 *smax; /* input, scramble[i] in 0..smax-1 */
+key *keys; /* input, keys to hash */
+ub4 nkeys; /* input, number of keys being hashed */
+hashform *form; /* user directives */
+{
+ ub4 bad_initkey; /* how many times did initkey fail? */
+ ub4 bad_perfect; /* how many times did perfect fail? */
+ ub4 trysalt; /* trial initializer for initial hash */
+ ub4 maxalen;
+ hstuff *tabh; /* table of keys indexed by hash value */
+ qstuff *tabq; /* table of stuff indexed by queue value, used by augment */
+
+ /* The case of (A,B) supplied by the user is a special case */
+ if (form->hashtype == AB_HT)
+ {
+ hash_ab(tabb, alen, blen, salt, final,
+ scramble, smax, keys, nkeys, form);
+ return;
+ }
+
+ /* guess initial values for smax, alen and blen */
+ *smax = ((ub4)1<<mylog2(nkeys));
+ initalen(alen, blen, smax, nkeys, form);
+
+ scrambleinit(scramble, *smax);
+
+ maxalen = (form->perfect == MINIMAL_HP) ? *smax/2 : *smax;
+
+ /* allocate working memory */
+ *tabb = (bstuff *)remalloc((size_t)(sizeof(bstuff)*(*blen)),
+ "perfect.c, tabb");
+ tabq = (qstuff *)remalloc(sizeof(qstuff)*(*blen+1), "perfect.c, tabq");
+ tabh = (hstuff *)remalloc(sizeof(hstuff)*(form->perfect == MINIMAL_HP ?
+ nkeys : *smax),
+ "perfect.c, tabh");
+
+ /* Actually find the perfect hash */
+ *salt = 0;
+ bad_initkey = 0;
+ bad_perfect = 0;
+ for (trysalt=1; ; ++trysalt)
+ {
+ ub4 rslinit;
+ /* Try to find distinct (A,B) for all keys */
+
+ rslinit = initkey(keys, nkeys, *tabb, *alen, *blen, *smax, trysalt,
+ form, final);
+
+ if (rslinit == 2)
+ { /* initkey actually found a perfect hash, not just distinct (a,b) */
+ *salt = 1;
+ *blen = 0;
+ break;
+ }
+ else if (rslinit == 0)
+ {
+ /* didn't find distinct (a,b) */
+ if (++bad_initkey >= RETRY_INITKEY)
+ {
+ /* Try to put more bits in (A,B) to make distinct (A,B) more likely */
+ if (*alen < maxalen)
+ {
+ *alen *= 2;
+ }
+ else if (*blen < *smax)
+ {
+ *blen *= 2;
+ free(tabq);
+ free(*tabb);
+ *tabb = (bstuff *)malloc((size_t)(sizeof(bstuff)*(*blen)));
+ tabq = (qstuff *)malloc((size_t)(sizeof(qstuff)*(*blen+1)));
+ }
+ else
+ {
+ duplicates(*tabb, *blen, keys, form); /* check for duplicates */
+ printf("fatal error: Cannot perfect hash: cannot find distinct (A,B)\n");
+ exit(SUCCESS);
+ }
+ bad_initkey = 0;
+ bad_perfect = 0;
+ }
+ continue; /* two keys have same (a,b) pair */
+ }
+
+ printf("found distinct (A,B) on attempt %ld\n", trysalt);
+
+ /* Given distinct (A,B) for all keys, build a perfect hash */
+ if (!perfect(*tabb, tabh, tabq, *blen, *smax, scramble, nkeys, form))
+ {
+ if ((form->hashtype != INT_HT && ++bad_perfect >= RETRY_PERFECT) ||
+ (form->hashtype == INT_HT && ++bad_perfect >= RETRY_HEX))
+ {
+ if (*blen < *smax)
+ {
+ *blen *= 2;
+ free(*tabb);
+ free(tabq);
+ *tabb = (bstuff *)malloc((size_t)(sizeof(bstuff)*(*blen)));
+ tabq = (qstuff *)malloc((size_t)(sizeof(qstuff)*(*blen+1)));
+ --trysalt; /* we know this salt got distinct (A,B) */
+ }
+ else
+ {
+ printf("fatal error: Cannot perfect hash: cannot build tab[]\n");
+ exit(SUCCESS);
+ }
+ bad_perfect = 0;
+ }
+ continue;
+ }
+
+ *salt = trysalt;
+ break;
+ }
+
+ printf("built perfect hash table of size %ld\n", *blen);
+
+ /* free working memory */
+ free((void *)tabh);
+ free((void *)tabq);
+}
+
+/*
+------------------------------------------------------------------------------
+Input/output type routines
+------------------------------------------------------------------------------
+*/
+
+/* get the list of keys */
+static void getkeys(keys, nkeys, textroot, keyroot, form)
+key **keys; /* list of all keys */
+ub4 *nkeys; /* number of keys */
+reroot *textroot; /* get space to store key text */
+reroot *keyroot; /* get space for keys */
+hashform *form; /* user directives */
+{
+ key *mykey;
+ char *mytext;
+ mytext = (char *)renew(textroot);
+ *keys = 0;
+ *nkeys = 0;
+ while (fgets(mytext, MAXKEYLEN, stdin))
+ {
+ mykey = (key *)renew(keyroot);
+ if (form->mode == AB_HM)
+ {
+ sscanf(mytext, "%lx %lx ", &mykey->a_k, &mykey->b_k);
+ }
+ else if (form->mode == ABDEC_HM)
+ {
+ sscanf(mytext, "%ld %ld ", &mykey->a_k, &mykey->b_k);
+ }
+ else if (form->mode == HEX_HM)
+ {
+ sscanf(mytext, "%lx ", &mykey->hash_k);
+ }
+ else if (form->mode == DECIMAL_HM)
+ {
+ sscanf(mytext, "%ld ", &mykey->hash_k);
+ }
+ else
+ {
+ mykey->name_k = (ub1 *)mytext;
+ mytext = (char *)renew(textroot);
+ mykey->len_k = (ub4)(strlen((char *)mykey->name_k)-1);
+ }
+ mykey->next_k = *keys;
+ *keys = mykey;
+ ++*nkeys;
+ }
+ redel(textroot, mytext);
+}
+
+/* make the .h file */
+static void make_h(blen, smax, nkeys, salt)
+ub4 blen;
+ub4 smax;
+ub4 nkeys;
+ub4 salt;
+{
+ FILE *f;
+ f = fopen("phash.h", "w");
+ fprintf(f, "/* Perfect hash definitions */\n");
+ fprintf(f, "#ifndef STANDARD\n");
+ fprintf(f, "#include \"standard.h\"\n");
+ fprintf(f, "#endif /* STANDARD */\n");
+ fprintf(f, "#ifndef PHASH\n");
+ fprintf(f, "#define PHASH\n");
+ fprintf(f, "\n");
+ if (blen > 0)
+ {
+ if (smax <= UB1MAXVAL+1 || blen >= USE_SCRAMBLE)
+ fprintf(f, "extern ub1 tab[];\n");
+ else
+ {
+ fprintf(f, "extern ub2 tab[];\n");
+ if (blen >= USE_SCRAMBLE)
+ {
+ if (smax <= UB2MAXVAL+1)
+ fprintf(f, "extern ub2 scramble[];\n");
+ else
+ fprintf(f, "extern ub4 scramble[];\n");
+ }
+ }
+ fprintf(f, "#define PHASHLEN 0x%lx /* length of hash mapping table */\n",
+ blen);
+ }
+ fprintf(f, "#define PHASHNKEYS %ld /* How many keys were hashed */\n",
+ nkeys);
+ fprintf(f, "#define PHASHRANGE %ld /* Range any input might map to */\n",
+ smax);
+ fprintf(f, "#define PHASHSALT 0x%.8lx /* internal, initialize normal hash */\n",
+ salt*0x9e3779b9);
+ fprintf(f, "\n");
+ fprintf(f, "ub4 phash();\n");
+ fprintf(f, "\n");
+ fprintf(f, "#endif /* PHASH */\n");
+ fprintf(f, "\n");
+ fclose(f);
+}
+
+/* make the .c file */
+static void make_c(tab, smax, blen, scramble, final, form)
+bstuff *tab; /* table indexed by b */
+ub4 smax; /* range of scramble[] */
+ub4 blen; /* b in 0..blen-1, power of 2 */
+ub4 *scramble; /* used in final hash */
+gencode *final; /* code for the final hash */
+hashform *form; /* user directives */
+{
+ ub4 i;
+ FILE *f;
+ f = fopen("phash.c", "w");
+ fprintf(f, "/* table for the mapping for the perfect hash */\n");
+ fprintf(f, "#ifndef STANDARD\n");
+ fprintf(f, "#include \"standard.h\"\n");
+ fprintf(f, "#endif /* STANDARD */\n");
+ fprintf(f, "#ifndef PHASH\n");
+ fprintf(f, "#include \"phash.h\"\n");
+ fprintf(f, "#endif /* PHASH */\n");
+ fprintf(f, "#ifndef LOOKUPA\n");
+ fprintf(f, "#include \"lookupa.h\"\n");
+ fprintf(f, "#endif /* LOOKUPA */\n");
+ fprintf(f, "\n");
+ if (blen >= USE_SCRAMBLE)
+ {
+ fprintf(f, "/* A way to make the 1-byte values in tab bigger */\n");
+ if (smax > UB2MAXVAL+1)
+ {
+ fprintf(f, "ub4 scramble[] = {\n");
+ for (i=0; i<=UB1MAXVAL; i+=4)
+ fprintf(f, "0x%.8lx, 0x%.8lx, 0x%.8lx, 0x%.8lx,\n",
+ scramble[i+0], scramble[i+1], scramble[i+2], scramble[i+3]);
+ }
+ else
+ {
+ fprintf(f, "ub2 scramble[] = {\n");
+ for (i=0; i<=UB1MAXVAL; i+=8)
+ fprintf(f,
+"0x%.4lx, 0x%.4lx, 0x%.4lx, 0x%.4lx, 0x%.4lx, 0x%.4lx, 0x%.4lx, 0x%.4lx,\n",
+ scramble[i+0], scramble[i+1], scramble[i+2], scramble[i+3],
+ scramble[i+4], scramble[i+5], scramble[i+6], scramble[i+7]);
+ }
+ fprintf(f, "};\n");
+ fprintf(f, "\n");
+ }
+ if (blen > 0)
+ {
+ fprintf(f, "/* small adjustments to _a_ to make values distinct */\n");
+
+ if (smax <= UB1MAXVAL+1 || blen >= USE_SCRAMBLE)
+ fprintf(f, "ub1 tab[] = {\n");
+ else
+ fprintf(f, "ub2 tab[] = {\n");
+
+ if (blen < 16)
+ {
+ for (i=0; i<blen; ++i) fprintf(f, "%3d,", scramble[tab[i].val_b]);
+ }
+ else if (blen <= 1024)
+ {
+ for (i=0; i<blen; i+=16)
+ fprintf(f, "%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,\n",
+ scramble[tab[i+0].val_b], scramble[tab[i+1].val_b],
+ scramble[tab[i+2].val_b], scramble[tab[i+3].val_b],
+ scramble[tab[i+4].val_b], scramble[tab[i+5].val_b],
+ scramble[tab[i+6].val_b], scramble[tab[i+7].val_b],
+ scramble[tab[i+8].val_b], scramble[tab[i+9].val_b],
+ scramble[tab[i+10].val_b], scramble[tab[i+11].val_b],
+ scramble[tab[i+12].val_b], scramble[tab[i+13].val_b],
+ scramble[tab[i+14].val_b], scramble[tab[i+15].val_b]);
+ }
+ else if (blen < USE_SCRAMBLE)
+ {
+ for (i=0; i<blen; i+=8)
+ fprintf(f, "%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,\n",
+ scramble[tab[i+0].val_b], scramble[tab[i+1].val_b],
+ scramble[tab[i+2].val_b], scramble[tab[i+3].val_b],
+ scramble[tab[i+4].val_b], scramble[tab[i+5].val_b],
+ scramble[tab[i+6].val_b], scramble[tab[i+7].val_b]);
+ }
+ else
+ {
+ for (i=0; i<blen; i+=16)
+ fprintf(f, "%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,\n",
+ tab[i+0].val_b, tab[i+1].val_b,
+ tab[i+2].val_b, tab[i+3].val_b,
+ tab[i+4].val_b, tab[i+5].val_b,
+ tab[i+6].val_b, tab[i+7].val_b,
+ tab[i+8].val_b, tab[i+9].val_b,
+ tab[i+10].val_b, tab[i+11].val_b,
+ tab[i+12].val_b, tab[i+13].val_b,
+ tab[i+14].val_b, tab[i+15].val_b);
+ }
+ fprintf(f, "};\n");
+ fprintf(f, "\n");
+ }
+ fprintf(f, "/* The hash function */\n");
+ switch(form->mode)
+ {
+ case NORMAL_HM:
+ fprintf(f, "ub4 phash(key, len)\n");
+ fprintf(f, "char *key;\n");
+ fprintf(f, "int len;\n");
+ break;
+ case INLINE_HM:
+ case HEX_HM:
+ case DECIMAL_HM:
+ fprintf(f, "ub4 phash(val)\n");
+ fprintf(f, "ub4 val;\n");
+ break;
+ case AB_HM:
+ case ABDEC_HM:
+ fprintf(f, "ub4 phash(a,b)\n");
+ fprintf(f, "ub4 a;\n");
+ fprintf(f, "ub4 b;\n");
+ break;
+ }
+ fprintf(f, "{\n");
+ for (i=0; i<final->used; ++i)
+ fprintf(f, final->line[i]);
+ fprintf(f, " return rsl;\n");
+ fprintf(f, "}\n");
+ fprintf(f, "\n");
+ fclose(f);
+}
+
+/*
+------------------------------------------------------------------------------
+Read in the keys, find the hash, and write the .c and .h files
+------------------------------------------------------------------------------
+*/
+static void driver(form)
+hashform *form; /* user directives */
+{
+ ub4 nkeys; /* number of keys */
+ key *keys; /* head of list of keys */
+ bstuff *tab; /* table indexed by b */
+ ub4 smax; /* scramble[] values in 0..smax-1, a power of 2 */
+ ub4 alen; /* a in 0..alen-1, a power of 2 */
+ ub4 blen; /* b in 0..blen-1, a power of 2 */
+ ub4 salt; /* a parameter to the hash function */
+ reroot *textroot; /* MAXKEYLEN-character text lines */
+ reroot *keyroot; /* source of keys */
+ gencode final; /* code for final hash */
+ ub4 i;
+ ub4 scramble[SCRAMBLE_LEN]; /* used in final hash function */
+ char buf[10][80]; /* buffer for generated code */
+ char *buf2[10]; /* also for generated code */
+
+ /* set up memory sources */
+ textroot = remkroot((size_t)MAXKEYLEN);
+ keyroot = remkroot(sizeof(key));
+
+ /* set up code for final hash */
+ final.line = buf2;
+ final.used = 0;
+ final.len = 10;
+ for (i=0; i<10; ++i) final.line[i] = buf[i];
+
+ /* read in the list of keywords */
+ getkeys(&keys, &nkeys, textroot, keyroot, form);
+ printf("Read in %ld keys\n",nkeys);
+
+ /* find the hash */
+ findhash(&tab, &alen, &blen, &salt, &final,
+ scramble, &smax, keys, nkeys, form);
+
+ /* generate the phash.h file */
+ make_h(blen, smax, nkeys, salt);
+ printf("Wrote phash.h\n");
+
+ /* generate the phash.c file */
+ make_c(tab, smax, blen, scramble, &final, form);
+ printf("Wrote phash.c\n");
+
+ /* clean up memory sources */
+ refree(textroot);
+ refree(keyroot);
+ free((void *)tab);
+ printf("Cleaned up\n");
+}
+
+
+/* Describe how to use this utility */
+static void usage_error()
+{
+ printf("Usage: perfect [-{NnIiHhDdAaBb}{MmPp}{FfSs}] < key.txt \n");
+ printf("The input is a list of keys, one key per line.\n");
+ printf("Only one of NnIiHhDdAa and one of MmPp may be specified.\n");
+ printf(" N,n: normal mode, key is any string string (default).\n");
+ printf(" I,i: initial hash for ASCII char strings.\n");
+ printf("The initial hash must be\n");
+ printf(" hash = PHASHSALT;\n");
+ printf(" for (i=0; i<keylength; ++i) {\n");
+ printf(" hash = (hash ^ key[i]) + ((hash<<26)+(hash>>6));\n");
+ printf(" }\n");
+ printf("Note that this can be inlined in any user loop that walks\n");
+ printf("through the key anyways, eliminating the loop overhead.\n");
+ printf(" H,h: Keys are 4-byte integers in hex in this format:\n");
+ printf("ffffffff\n");
+ printf("This is good for optimizing switch statement compilation.\n");
+ printf(" D,d: Same as H,h, except in decimal not hexidecimal\n");
+ printf(" A,a: An (A,B) pair is supplied in hex in this format:\n");
+ printf("aaa bbb\n");
+ printf(" B,b: Same as A,a, except in decimal not hexidecimal\n");
+ printf("This mode does nothing but find the values of tab[].\n");
+ printf("*A* must be less than the total number of keys.\n");
+ printf(" M,m: Minimal perfect hash. Hash will be in 0..nkeys-1 (default)\n");
+ printf(" P,p: Perfect hash. Hash will be in 0..n-1, where n >= nkeys\n");
+ printf("and n is a power of 2. Will probably use a smaller tab[].");
+ printf(" F,f: Fast mode. Generate the perfect hash fast.\n");
+ printf(" S,s: Slow mode. Spend time finding a good perfect hash.\n");
+
+ exit(SUCCESS);
+}
+
+
+/* Interpret arguments and call the driver */
+/* See usage_error for the expected arguments */
+int main(argc, argv)
+int argc;
+char **argv;
+{
+ int mode_given = FALSE;
+ int minimal_given = FALSE;
+ int speed_given = FALSE;
+ hashform form;
+ char *c;
+
+ /* default behavior */
+ form.mode = NORMAL_HM;
+ form.hashtype = STRING_HT;
+ form.perfect = MINIMAL_HP;
+ form.speed = SLOW_HS;
+
+ /* let the user override the default behavior */
+ switch (argc)
+ {
+ case 1:
+ break;
+ case 2:
+ if (argv[1][0] != '-')
+ {
+ usage_error();
+ break;
+ }
+ for (c = &argv[1][1]; *c != '\0'; ++c) switch(*c)
+ {
+ case 'n': case 'N':
+ case 'i': case 'I':
+ case 'h': case 'H':
+ case 'd': case 'D':
+ case 'a': case 'A':
+ case 'b': case 'B':
+ if (mode_given == TRUE)
+ usage_error();
+ switch(*c)
+ {
+ case 'n': case 'N':
+ form.mode = NORMAL_HM; form.hashtype = STRING_HT; break;
+ case 'i': case 'I':
+ form.mode = INLINE_HM; form.hashtype = STRING_HT; break;
+ case 'h': case 'H':
+ form.mode = HEX_HM; form.hashtype = INT_HT; break;
+ case 'd': case 'D':
+ form.mode = DECIMAL_HM; form.hashtype = INT_HT; break;
+ case 'a': case 'A':
+ form.mode = AB_HM; form.hashtype = AB_HT; break;
+ case 'b': case 'B':
+ form.mode = ABDEC_HM; form.hashtype = AB_HT; break;
+ }
+ mode_given = TRUE;
+ break;
+ case 'm': case 'M':
+ case 'p': case 'P':
+ if (minimal_given == TRUE)
+ usage_error();
+ switch(*c)
+ {
+ case 'p': case 'P':
+ form.perfect = NORMAL_HP; break;
+ case 'm': case 'M':
+ form.perfect = MINIMAL_HP; break;
+ }
+ minimal_given = TRUE;
+ break;
+ case 'f': case 'F':
+ case 's': case 'S':
+ if (speed_given == TRUE)
+ usage_error();
+ switch(*c)
+ {
+ case 'f': case 'F':
+ form.speed = FAST_HS; break;
+ case 's': case 'S':
+ form.speed = SLOW_HS; break;
+ }
+ speed_given = TRUE;
+ break;
+ default:
+ usage_error();
+ }
+ break;
+ default:
+ usage_error();
+ }
+
+ /* Generate the [minimal] perfect hash */
+ driver(&form);
+
+ return SUCCESS;
+}
diff --git a/tools/codegen/core/perfect/perfect.h b/tools/codegen/core/perfect/perfect.h
new file mode 100644
index 0000000000..fed5296bb7
--- /dev/null
+++ b/tools/codegen/core/perfect/perfect.h
@@ -0,0 +1,132 @@
+/*
+------------------------------------------------------------------------------
+perfect.h: code to generate code for a hash for perfect hashing.
+(c) Bob Jenkins, September 1996
+You may use this code in any way you wish, and it is free. No warranty.
+I hereby place this in the public domain.
+Source is http://burtleburtle.net/bob/c/perfect.h
+------------------------------------------------------------------------------
+*/
+
+#ifndef STANDARD
+#include "standard.h"
+#endif
+
+#ifndef PERFECT
+#define PERFECT
+
+#define MAXKEYLEN 30 /* maximum length of a key */
+#define USE_SCRAMBLE 4096 /* use scramble if blen >= USE_SCRAMBLE */
+#define SCRAMBLE_LEN ((ub4)1<<16) /* length of *scramble* */
+#define RETRY_INITKEY 2048 /* number of times to try to find distinct (a,b) */
+#define RETRY_PERFECT 1 /* number of times to try to make a perfect hash */
+#define RETRY_HEX 200 /* RETRY_PERFECT when hex keys given */
+
+/* the generated code for the final hash, assumes initial hash is done */
+struct gencode
+{
+ char **line; /* array of text lines, 80 bytes apiece */
+ /*
+ * The code placed here must declare "ub4 rsl"
+ * and assign it the value of the perfect hash using the function inputs.
+ * Later code will be tacked on which returns rsl or manipulates it according
+ * to the user directives.
+ *
+ * This code is at the top of the routine; it may and must declare any
+ * local variables it needs.
+ *
+ * Each way of filling in **line should be given a comment that is a unique
+ * tag. A testcase named with that tag should also be found which tests
+ * the generated code.
+ */
+ ub4 len; /* number of lines available for final hash */
+ ub4 used; /* number of lines used by final hash */
+
+ ub4 lowbit; /* for HEX, lowest interesting bit */
+ ub4 highbit; /* for HEX, highest interesting bit */
+ ub4 diffbits; /* bits which differ for some key */
+ ub4 i,j,k,l,m,n,o; /* state machine used in hexn() */
+};
+typedef struct gencode gencode;
+
+/* user directives: perfect hash? minimal perfect hash? input is an int? */
+struct hashform
+{
+ enum {
+ NORMAL_HM, /* key is a string */
+ INLINE_HM, /* user will do initial hash, we must choose salt for them */
+ HEX_HM, /* key to be hashed is a hexidecimal 4-byte integer */
+ DECIMAL_HM, /* key to be hashed is a decimal 4-byte integer */
+ AB_HM, /* key to be hashed is "A B", where A and B are (A,B) in hex */
+ ABDEC_HM /* like AB_HM, but in decimal */
+ } mode;
+ enum {
+ STRING_HT, /* key is a string */
+ INT_HT, /* key is an integer */
+ AB_HT /* dunno what key is, but input is distinct (A,B) pair */
+ } hashtype;
+ enum {
+ NORMAL_HP, /* just find a perfect hash */
+ MINIMAL_HP /* find a minimal perfect hash */
+ } perfect;
+ enum {
+ FAST_HS, /* fast mode */
+ SLOW_HS /* slow mode */
+ } speed;
+};
+typedef struct hashform hashform;
+
+/* representation of a key */
+struct key
+{
+ ub1 *name_k; /* the actual key */
+ ub4 len_k; /* the length of the actual key */
+ ub4 hash_k; /* the initial hash value for this key */
+ struct key *next_k; /* next key */
+/* beyond this point is mapping-dependent */
+ ub4 a_k; /* a, of the key maps to (a,b) */
+ ub4 b_k; /* b, of the key maps to (a,b) */
+ struct key *nextb_k; /* next key with this b */
+};
+typedef struct key key;
+
+/* things indexed by b of original (a,b) pair */
+struct bstuff
+{
+ ub2 val_b; /* hash=a^tabb[b].val_b */
+ key *list_b; /* tabb[i].list_b is list of keys with b==i */
+ ub4 listlen_b; /* length of list_b */
+ ub4 water_b; /* high watermark of who has visited this map node */
+};
+typedef struct bstuff bstuff;
+
+/* things indexed by final hash value */
+struct hstuff
+{
+ key *key_h; /* tabh[i].key_h is the key with a hash of i */
+};
+typedef struct hstuff hstuff;
+
+/* things indexed by queue position */
+struct qstuff
+{
+ bstuff *b_q; /* b that currently occupies this hash */
+ ub4 parent_q; /* queue position of parent that could use this hash */
+ ub2 newval_q; /* what to change parent tab[b] to to use this hash */
+ ub2 oldval_q; /* original value of tab[b] */
+};
+typedef struct qstuff qstuff;
+
+/* return ceiling(log based 2 of x) */
+ub4 mylog2(/*_ ub4 x _*/);
+
+/* Given the keys, scramble[], and hash mode, find the perfect hash */
+void findhash(/*_ bstuff **tabb, ub4 *alen, ub4 *blen, ub4 *salt,
+ gencode *final, ub4 *scramble, ub4 smax, key *keys, ub4 nkeys,
+ hashform *form _*/);
+
+/* private, but in a different file because it's excessively verbose */
+int inithex(/*_ key *keys, ub4 *alen, ub4 *blen, ub4 smax, ub4 nkeys,
+ ub4 salt, gencode *final, gencode *form _*/);
+
+#endif /* PERFECT */
diff --git a/tools/codegen/core/perfect/perfhex.c b/tools/codegen/core/perfect/perfhex.c
new file mode 100644
index 0000000000..9c28dc734b
--- /dev/null
+++ b/tools/codegen/core/perfect/perfhex.c
@@ -0,0 +1,1308 @@
+/*
+------------------------------------------------------------------------------
+perfhex.c: code to generate code for a hash for perfect hashing.
+(c) Bob Jenkins, December 31 1999
+You may use this code in any way you wish, and it is free. No warranty.
+I hereby place this in the public domain.
+Source is http://burtleburtle.net/bob/c/perfhex.c
+
+The task of this file is to do the minimal amount of mixing needed to
+find distinct (a,b) for each key when each key is a distinct ub4. That
+means trying all possible ways to mix starting with the fastest. The
+output is those (a,b) pairs and code in the *final* structure for producing
+those pairs.
+------------------------------------------------------------------------------
+*/
+
+#ifndef STANDARD
+#include "standard.h"
+#endif
+#ifndef LOOKUPA
+#include "lookupa.h"
+#endif
+#ifndef RECYCLE
+#include "recycle.h"
+#endif
+#ifndef PERFECT
+#include "perfect.h"
+#endif
+
+/*
+ * Find a perfect hash when there is only one key. Zero instructions.
+ * Hint: the one key always hashes to 0
+ */
+static void hexone(keys, final)
+key *keys;
+gencode *final;
+{
+ /* 1 key: the hash is always 0 */
+ keys->a_k = 0;
+ keys->b_k = 0;
+ final->used = 1;
+ sprintf(final->line[0], " ub4 rsl = 0;\n"); /* h1a: 37 */
+}
+
+
+
+/*
+ * Find a perfect hash when there are only two keys. Max 2 instructions.
+ * There exists a bit that is different for the two keys. Test it.
+ * Note that a perfect hash of 2 keys is automatically minimal.
+ */
+static void hextwo(keys, final)
+key *keys;
+gencode *final;
+{
+ ub4 a = keys->hash_k;
+ ub4 b = keys->next_k->hash_k;
+ ub4 i;
+
+ if (a == b)
+ {
+ printf("fatal error: duplicate keys\n");
+ exit(SUCCESS);
+ }
+
+ final->used = 1;
+
+ /* one instruction */
+ if ((a&1) != (b&1))
+ {
+ sprintf(final->line[0], " ub4 rsl = (val & 1);\n"); /* h2a: 3,4 */
+ return;
+ }
+
+ /* two instructions */
+ for (i=0; i<UB4BITS; ++i)
+ {
+ if ((a&((ub4)1<<i)) != (b&((ub4)1<<i))) break;
+ }
+ /* h2b: 4,6 */
+ sprintf(final->line[0], " ub4 rsl = ((val << %ld) & 1);\n", i);
+}
+
+
+
+/*
+ * find the value to xor to a and b and c to make none of them 3
+ * assert, (a,b,c) are three distinct values in (0,1,2,3).
+ */
+static ub4 find_adder(a,b,c)
+ub4 a;
+ub4 b;
+ub4 c;
+{
+ return (a^b^c^3);
+}
+
+
+
+/*
+ * Find a perfect hash when there are only three keys. Max 6 instructions.
+ *
+ * keys a,b,c.
+ * There exists bit i such that a[i] != b[i].
+ * Either c[i] != a[i] or c[i] != b[i], assume c[i] != a[i].
+ * There exists bit j such that b[j] != c[j]. Note i != j.
+ * Final hash should be no longer than val[i]^val[j].
+ *
+ * A minimal perfect hash needs to xor one of 0,1,2,3 afterwards to cause
+ * the hole to land on 3. find_adder() finds that constant
+ */
+static void hexthree(keys, final, form)
+key *keys;
+gencode *final;
+hashform *form;
+{
+ ub4 a = keys->hash_k;
+ ub4 b = keys->next_k->hash_k;
+ ub4 c = keys->next_k->next_k->hash_k;
+ ub4 i,j,x,y,z;
+
+ final->used = 1;
+
+ if (a == b || a == c || b == c)
+ {
+ printf("fatal error: duplicate keys\n");
+ exit(SUCCESS);
+ }
+
+ /* one instruction */
+ x = a&3;
+ y = b&3;
+ z = c&3;
+ if (x != y && x != z && y != z)
+ {
+ if (form->perfect == NORMAL_HP || (x != 3 && y != 3 && z != 3))
+ {
+ /* h3a: 0,1,2 */
+ sprintf(final->line[0], " ub4 rsl = (val & 3);\n");
+ }
+ else
+ {
+ /* h3b: 0,3,2 */
+ sprintf(final->line[0], " ub4 rsl = ((val & 3) ^ %d);\n",
+ find_adder(x,y,z));
+ }
+ return;
+ }
+
+ x = a>>(UB4BITS-2);
+ y = b>>(UB4BITS-2);
+ z = c>>(UB4BITS-2);
+ if (x != y && x != z && y != z)
+ {
+ if (form->perfect == NORMAL_HP || (x != 3 && y != 3 && z != 3))
+ {
+ /* h3c: 3fffffff, 7fffffff, bfffffff */
+ sprintf(final->line[0], " ub4 rsl = (val >> %ld);\n", (ub4)(UB4BITS-2));
+ }
+ else
+ {
+ /* h3d: 7fffffff, bfffffff, ffffffff */
+ sprintf(final->line[0], " ub4 rsl = ((val >> %ld) ^ %ld);\n",
+ (ub4)(UB4BITS-2), find_adder(x,y,z));
+ }
+ return;
+ }
+
+ /* two instructions */
+ for (i=0; i<final->highbit; ++i)
+ {
+ x = (a>>i)&3;
+ y = (b>>i)&3;
+ z = (c>>i)&3;
+ if (x != y && x != z && y != z)
+ {
+ if (form->perfect == NORMAL_HP || (x != 3 && y != 3 && z != 3))
+ {
+ /* h3e: ffff3fff, ffff7fff, ffffbfff */
+ sprintf(final->line[0], " ub4 rsl = ((val >> %ld) & 3);\n", i);
+ }
+ else
+ {
+ /* h3f: ffff7fff, ffffbfff, ffffffff */
+ sprintf(final->line[0], " ub4 rsl = (((val >> %ld) & 3) ^ %ld);\n", i,
+ find_adder(x,y,z));
+ }
+ return;
+ }
+ }
+
+ /* three instructions */
+ for (i=0; i<=final->highbit; ++i)
+ {
+ x = (a+(a>>i))&3;
+ y = (b+(b>>i))&3;
+ z = (c+(c>>i))&3;
+ if (x != y && x != z && y != z)
+ {
+ if (form->perfect == NORMAL_HP || (x != 3 && y != 3 && z != 3))
+ {
+ /* h3g: 0x000, 0x001, 0x100 */
+ sprintf(final->line[0], " ub4 rsl = ((val+(val>>%ld))&3);\n", i);
+ }
+ else
+ {
+ /* h3h: 0x001, 0x100, 0x101 */
+ sprintf(final->line[0], " ub4 rsl = (((val+(val>>%ld))&3)^%ld);\n", i,
+ find_adder(x,y,z));
+ }
+ return;
+ }
+ }
+
+ /*
+ * Four instructions: I can prove this will always work.
+ *
+ * If the three values are distinct, there are two bits which
+ * distinguish them. Choose the two such bits that are closest together.
+ * If those bits are values 001 and 100 for those three values,
+ * then there either aren't any bits in between
+ * or the in-between bits aren't valued 001, 110, 100, 011, 010, or 101,
+ * because that would violate the closest-together assumption.
+ * So any in-between bits must be 000 or 111, and of 000 and 111 with
+ * the distinguishing bits won't cause them to stop being distinguishing.
+ */
+ for (i=final->lowbit; i<=final->highbit; ++i)
+ {
+ for (j=i; j<=final->highbit; ++j)
+ {
+ x = ((a>>i)^(a>>j))&3;
+ y = ((b>>i)^(b>>j))&3;
+ z = ((c>>i)^(c>>j))&3;
+ if (x != y && x != z && y != z)
+ {
+ if (form->perfect == NORMAL_HP || (x != 3 && y != 3 && z != 3))
+ {
+ /* h3i: 0x00, 0x04, 0x10 */
+ sprintf(final->line[0],
+ " ub4 rsl = (((val>>%ld) ^ (val>>%ld)) & 3);\n", i, j);
+ }
+ else
+ {
+ /* h3j: 0x04, 0x10, 0x14 */
+ sprintf(final->line[0],
+ " ub4 rsl = ((((val>>%ld) ^ (val>>%ld)) & 3) ^ %ld);\n",
+ i, j, find_adder(x,y,z));
+ }
+ return;
+ }
+ }
+ }
+
+ printf("fatal error: hexthree\n");
+ exit(SUCCESS);
+}
+
+
+
+/*
+ * Check that a,b,c,d are some permutation of 0,1,2,3
+ * Assume that a,b,c,d are all have values less than 32.
+ */
+static int testfour(a,b,c,d)
+ub4 a;
+ub4 b;
+ub4 c;
+ub4 d;
+{
+ ub4 mask = (1<<a)^(1<<b)^(1<<c)^(1<<d);
+ return (mask == 0xf);
+}
+
+
+
+/*
+ * Find a perfect hash when there are only four keys. Max 10 instructions.
+ * Note that a perfect hash for 4 keys will automatically be minimal.
+ */
+static void hexfour(keys, final)
+key *keys;
+gencode *final;
+{
+ ub4 a = keys->hash_k;
+ ub4 b = keys->next_k->hash_k;
+ ub4 c = keys->next_k->next_k->hash_k;
+ ub4 d = keys->next_k->next_k->next_k->hash_k;
+ ub4 w,x,y,z;
+ ub4 i,j,k;
+
+ if (a==b || a==c || a==d || b==c || b==d || c==d)
+ {
+ printf("fatal error: Duplicate keys\n");
+ exit(SUCCESS);
+ }
+
+ final->used = 1;
+
+ /* one instruction */
+ if ((final->diffbits & 3) == 3)
+ {
+ w = a&3;
+ x = b&3;
+ y = c&3;
+ z = d&3;
+ if (testfour(w,x,y,z))
+ {
+ sprintf(final->line[0], " ub4 rsl = (val & 3);\n"); /* h4a: 0,1,2,3 */
+ return;
+ }
+ }
+
+ if (((final->diffbits >> (UB4BITS-2)) & 3) == 3)
+ {
+ w = a>>(UB4BITS-2);
+ x = b>>(UB4BITS-2);
+ y = c>>(UB4BITS-2);
+ z = d>>(UB4BITS-2);
+ if (testfour(w,x,y,z))
+ { /* h4b: 0fffffff, 4fffffff, 8fffffff, cfffffff */
+ sprintf(final->line[0], " ub4 rsl = (val >> %ld);\n", (ub4)(UB4BITS-2));
+ return;
+ }
+ }
+
+ /* two instructions */
+ for (i=final->lowbit; i<final->highbit; ++i)
+ {
+ if (((final->diffbits >> i) & 3) == 3)
+ {
+ w = (a>>i)&3;
+ x = (b>>i)&3;
+ y = (c>>i)&3;
+ z = (d>>i)&3;
+ if (testfour(w,x,y,z))
+ { /* h4c: 0,2,4,6 */
+ sprintf(final->line[0], " ub4 rsl = ((val >> %ld) & 3);\n", i);
+ return;
+ }
+ }
+ }
+
+ /* three instructions (linear with the number of diffbits) */
+ if ((final->diffbits & 3) != 0)
+ {
+ for (i=final->lowbit; i<=final->highbit; ++i)
+ {
+ if (((final->diffbits >> i) & 3) != 0)
+ {
+ w = (a+(a>>i))&3;
+ x = (b+(b>>i))&3;
+ y = (c+(c>>i))&3;
+ z = (d+(d>>i))&3;
+ if (testfour(w,x,y,z))
+ { /* h4d: 0,1,2,4 */
+ sprintf(final->line[0],
+ " ub4 rsl = ((val + (val >> %ld)) & 3);\n", i);
+ return;
+ }
+
+ w = (a-(a>>i))&3;
+ x = (b-(b>>i))&3;
+ y = (c-(c>>i))&3;
+ z = (d-(d>>i))&3;
+ if (testfour(w,x,y,z))
+ { /* h4e: 0,1,3,5 */
+ sprintf(final->line[0],
+ " ub4 rsl = ((val - (val >> %ld)) & 3);\n", i);
+ return;
+ }
+
+ /* h4f: ((val>>k)-val)&3: redundant with h4e */
+
+ w = (a^(a>>i))&3;
+ x = (b^(b>>i))&3;
+ y = (c^(c>>i))&3;
+ z = (d^(d>>i))&3;
+ if (testfour(w,x,y,z))
+ { /* h4g: 3,4,5,8 */
+ sprintf(final->line[0],
+ " ub4 rsl = ((val ^ (val >> %ld)) & 3);\n", i);
+ return;
+ }
+ }
+ }
+ }
+
+ /* four instructions (linear with the number of diffbits) */
+ if ((final->diffbits & 3) != 0)
+ {
+ for (i=final->lowbit; i<=final->highbit; ++i)
+ {
+ if ((((final->diffbits >> i) & 1) != 0) &&
+ ((final->diffbits & 2) != 0))
+ {
+ w = (a&3)^((a>>i)&1);
+ x = (b&3)^((b>>i)&1);
+ y = (c&3)^((c>>i)&1);
+ z = (d&3)^((d>>i)&1);
+ if (testfour(w,x,y,z))
+ { /* h4h: 1,2,6,8 */
+ sprintf(final->line[0],
+ " ub4 rsl = ((val & 3) ^ ((val >> %ld) & 1));\n", i);
+ return;
+ }
+
+ w = (a&2)^((a>>i)&1);
+ x = (b&2)^((b>>i)&1);
+ y = (c&2)^((c>>i)&1);
+ z = (d&2)^((d>>i)&1);
+ if (testfour(w,x,y,z))
+ { /* h4i: 1,2,8,a */
+ sprintf(final->line[0],
+ " ub4 rsl = ((val & 2) ^ ((val >> %ld) & 1));\n", i);
+ return;
+ }
+ }
+
+ if ((((final->diffbits >> i) & 2) != 0) &&
+ ((final->diffbits & 1) != 0))
+ {
+ w = (a&3)^((a>>i)&2);
+ x = (b&3)^((b>>i)&2);
+ y = (c&3)^((c>>i)&2);
+ z = (d&3)^((d>>i)&2);
+ if (testfour(w,x,y,z))
+ { /* h4j: 0,1,3,4 */
+ sprintf(final->line[0],
+ " ub4 rsl = ((val & 3) ^ ((val >> %ld) & 2));\n", i);
+ return;
+ }
+
+ w = (a&1)^((a>>i)&2);
+ x = (b&1)^((b>>i)&2);
+ y = (c&1)^((c>>i)&2);
+ z = (d&1)^((d>>i)&2);
+ if (testfour(w,x,y,z))
+ { /* h4k: 1,4,7,8 */
+ sprintf(final->line[0],
+ " ub4 rsl = ((val & 1) ^ ((val >> %ld) & 2));\n", i);
+ return;
+ }
+ }
+ }
+ }
+
+ /* four instructions (quadratic in the number of diffbits) */
+ for (i=final->lowbit; i<=final->highbit; ++i)
+ {
+ if (((final->diffbits >> i) & 1) == 1)
+ {
+ for (j=final->lowbit; j<=final->highbit; ++j)
+ {
+ if (((final->diffbits >> j) & 3) != 0)
+ {
+ /* test + */
+ w = ((a>>i)+(a>>j))&3;
+ x = ((b>>i)+(a>>j))&3;
+ y = ((c>>i)+(a>>j))&3;
+ z = ((d>>i)+(a>>j))&3;
+ if (testfour(w,x,y,z))
+ { /* h4l: testcase? */
+ sprintf(final->line[0],
+ " ub4 rsl = (((val >> %ld) + (val >> %ld)) & 3);\n",
+ i, j);
+ return;
+ }
+
+ /* test - */
+ w = ((a>>i)-(a>>j))&3;
+ x = ((b>>i)-(a>>j))&3;
+ y = ((c>>i)-(a>>j))&3;
+ z = ((d>>i)-(a>>j))&3;
+ if (testfour(w,x,y,z))
+ { /* h4m: testcase? */
+ sprintf(final->line[0],
+ " ub4 rsl = (((val >> %ld) - (val >> %ld)) & 3);\n",
+ i, j);
+ return;
+ }
+
+ /* test ^ */
+ w = ((a>>i)^(a>>j))&3;
+ x = ((b>>i)^(a>>j))&3;
+ y = ((c>>i)^(a>>j))&3;
+ z = ((d>>i)^(a>>j))&3;
+ if (testfour(w,x,y,z))
+ { /* h4n: testcase? */
+ sprintf(final->line[0],
+ " ub4 rsl = (((val >> %ld) ^ (val >> %ld)) & 3);\n",
+ i, j);
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ /* five instructions (quadratic in the number of diffbits) */
+ for (i=final->lowbit; i<=final->highbit; ++i)
+ {
+ if (((final->diffbits >> i) & 1) != 0)
+ {
+ for (j=final->lowbit; j<=final->highbit; ++j)
+ {
+ if (((final->diffbits >> j) & 3) != 0)
+ {
+ w = ((a>>j)&3)^((a>>i)&1);
+ x = ((b>>j)&3)^((b>>i)&1);
+ y = ((c>>j)&3)^((c>>i)&1);
+ z = ((d>>j)&3)^((d>>i)&1);
+ if (testfour(w,x,y,z))
+ { /* h4o: 0,4,8,a */
+ sprintf(final->line[0],
+ " ub4 rsl = (((val >> %ld) & 3) ^ ((val >> %ld) & 1));\n",
+ j, i);
+ return;
+ }
+
+ w = ((a>>j)&2)^((a>>i)&1);
+ x = ((b>>j)&2)^((b>>i)&1);
+ y = ((c>>j)&2)^((c>>i)&1);
+ z = ((d>>j)&2)^((d>>i)&1);
+ if (testfour(w,x,y,z))
+ { /* h4p: 0x04, 0x08, 0x10, 0x14 */
+ sprintf(final->line[0],
+ " ub4 rsl = (((val >> %ld) & 2) ^ ((val >> %ld) & 1));\n",
+ j, i);
+ return;
+ }
+ }
+
+ if (i==0)
+ {
+ w = ((a>>j)^(a<<1))&3;
+ x = ((b>>j)^(b<<1))&3;
+ y = ((c>>j)^(c<<1))&3;
+ z = ((d>>j)^(d<<1))&3;
+ }
+ else
+ {
+ w = ((a>>j)&3)^((a>>(i-1))&2);
+ x = ((b>>j)&3)^((b>>(i-1))&2);
+ y = ((c>>j)&3)^((c>>(i-1))&2);
+ z = ((d>>j)&3)^((d>>(i-1))&2);
+ }
+ if (testfour(w,x,y,z))
+ {
+ if (i==0) /* h4q: 0,4,5,8 */
+ {
+ sprintf(final->line[0],
+ " ub4 rsl = (((val >> %ld) ^ (val << 1)) & 3);\n",
+ j);
+ }
+ else if (i==1) /* h4r: 0x01,0x09,0x0b,0x10 */
+ {
+ sprintf(final->line[0],
+ " ub4 rsl = (((val >> %ld) & 3) ^ (val & 2));\n",
+ j);
+ }
+ else /* h4s: 0,2,6,8 */
+ {
+ sprintf(final->line[0],
+ " ub4 rsl = (((val >> %ld) & 3) ^ ((val >> %ld) & 2));\n",
+ j, (i-1));
+ }
+ return;
+ }
+
+ w = ((a>>j)&1)^((a>>i)&2);
+ x = ((b>>j)&1)^((b>>i)&2);
+ y = ((c>>j)&1)^((c>>i)&2);
+ z = ((d>>j)&1)^((d>>i)&2);
+ if (testfour(w,x,y,z)) /* h4t: 0x20,0x14,0x10,0x06 */
+ {
+ sprintf(final->line[0],
+ " ub4 rsl = (((val >> %ld) & 1) ^ ((val >> %ld) & 2));\n",
+ j, i);
+ return;
+ }
+ }
+ }
+ }
+
+ /*
+ * OK, bring out the big guns.
+ * There exist three bits i,j,k which distinguish a,b,c,d.
+ * i^(j<<1)^(k*q) is guaranteed to work for some q in {0,1,2,3},
+ * proven by exhaustive search of all (8 choose 4) cases.
+ * Find three such bits and try the 4 cases.
+ * Linear with the number of diffbits.
+ * Some cases below may duplicate some cases above. I did it that way
+ * so that what is below is guaranteed to work, no matter what was
+ * attempted above.
+ * The generated hash is at most 10 instructions.
+ */
+ for (i=final->lowbit; i<UB4BITS; ++i)
+ {
+ y = (c>>i)&1;
+ z = (d>>i)&1;
+ if (y != z)
+ break;
+ }
+
+ for (j=final->lowbit; j<UB4BITS; ++j)
+ {
+ x = ((b>>i)&1)^(((b>>j)&1)<<1);
+ y = ((c>>i)&1)^(((c>>j)&1)<<1);
+ z = ((d>>i)&1)^(((d>>j)&1)<<1);
+ if (x != y && x != z && y != z)
+ break;
+ }
+
+ for (k=final->lowbit; k<UB4BITS; ++k)
+ {
+ w = ((a>>i)&1)^(((a>>j)&1)<<1)^(((a>>k)&1)<<2);
+ x = ((b>>i)&1)^(((b>>j)&1)<<1)^(((b>>k)&1)<<2);
+ y = ((c>>i)&1)^(((c>>j)&1)<<1)^(((c>>k)&1)<<2);
+ z = ((d>>i)&1)^(((d>>j)&1)<<1)^(((d>>k)&1)<<2);
+ if (w != x && w != y && w != z && x != y && x != z && y != z)
+ break;
+ }
+
+ /* Assert: bits i,j,k were found which distinguish a,b,c,d */
+ if (i==UB4BITS || j==UB4BITS || k==UB4BITS)
+ {
+ printf("Fatal error: hexfour(), i %ld j %ld k %ld\n", i,j,k);
+ exit(SUCCESS);
+ }
+
+ /* now try the four cases */
+ {
+ ub4 m,n,o,p;
+
+ /* if any bit has two 1s and two 0s, make that bit o */
+ if (((a>>i)&1)+((b>>i)&1)+((c>>i)&1)+((d>>i)&1) != 2)
+ { m=j; n=k; o=i; }
+ else if (((a>>j)&1)+((b>>j)&1)+((c>>j)&1)+((d>>j)&1) != 2)
+ { m=i; n=k; o=j; }
+ else
+ { m=i; n=j; o=k; }
+ if (m > n) {p=m; m=n; n=p; } /* guarantee m < n */
+
+ /* printf("m %ld n %ld o %ld %ld %ld %ld %ld\n", m, n, o, w,x,y,z); */
+
+ /* seven instructions, multiply bit o by 1 */
+ w = (((a>>m)^(a>>o))&1)^((a>>(n-1))&2);
+ x = (((b>>m)^(b>>o))&1)^((b>>(n-1))&2);
+ y = (((c>>m)^(c>>o))&1)^((c>>(n-1))&2);
+ z = (((d>>m)^(d>>o))&1)^((d>>(n-1))&2);
+ if (testfour(w,x,y,z))
+ {
+ if (m>o) {p=m; m=o; o=p;} /* make sure m < o and m < n */
+
+ if (m==0) /* 0,2,8,9 */
+ {
+ sprintf(final->line[0],
+ " ub4 rsl = (((val^(val>>%ld))&1)^((val>>%ld)&2));\n", o, n-1);
+ }
+ else /* 0x00,0x04,0x10,0x12 */
+ {
+ sprintf(final->line[0],
+ " ub4 rsl = ((((val>>%ld) ^ (val>>%ld)) & 1) ^ ((val>>%ld) & 2));\n",
+ m, o, n-1);
+ }
+ return;
+ }
+
+ /* six to seven instructions, multiply bit o by 2 */
+ w = ((a>>m)&1)^((((a>>n)^(a>>o))&1)<<1);
+ x = ((b>>m)&1)^((((b>>n)^(b>>o))&1)<<1);
+ y = ((c>>m)&1)^((((c>>n)^(c>>o))&1)<<1);
+ z = ((d>>m)&1)^((((d>>n)^(d>>o))&1)<<1);
+ if (testfour(w,x,y,z))
+ {
+ if (m==o-1) {p=n; n=o; o=p;} /* make m==n-1 if possible */
+
+ if (m==0) /* 0,1,5,8 */
+ {
+ sprintf(final->line[0],
+ " ub4 rsl = ((val & 1) ^ (((val>>%ld) ^ (val>>%ld)) & 2));\n",
+ n-1, o-1);
+ }
+ else if (o==0) /* 0x00,0x04,0x05,0x10 */
+ {
+ sprintf(final->line[0],
+ " ub4 rsl = (((val>>%ld) & 2) ^ (((val>>%ld) ^ val) & 1));\n",
+ m-1, n);
+ }
+ else /* 0x00,0x02,0x0a,0x10 */
+ {
+ sprintf(final->line[0],
+ " ub4 rsl = (((val>>%ld) & 1) ^ (((val>>%ld) ^ (val>>%ld)) & 2));\n",
+ m, n-1, o-1);
+ }
+ return;
+ }
+
+ /* multiplying by 3 is a pain: seven or eight instructions */
+ w = (((a>>m)&1)^((a>>(n-1))&2))^((a>>o)&1)^(((a>>o)&1)<<1);
+ x = (((b>>m)&1)^((b>>(n-1))&2))^((b>>o)&1)^(((b>>o)&1)<<1);
+ y = (((c>>m)&1)^((c>>(n-1))&2))^((c>>o)&1)^(((c>>o)&1)<<1);
+ z = (((d>>m)&1)^((d>>(n-1))&2))^((d>>o)&1)^(((d>>o)&1)<<1);
+ if (testfour(w,x,y,z))
+ {
+ final->used = 2;
+ sprintf(final->line[0], " ub4 b = (val >> %ld) & 1;\n", o);
+ if (m==o-1 && m==0) /* 0x02,0x10,0x11,0x18 */
+ {
+ sprintf(final->line[1],
+ " ub4 rsl = ((val & 3) ^ ((val >> %ld) & 2) ^ b);\n", n-1);
+ }
+ else if (m==o-1) /* 0,4,6,c */
+ {
+ sprintf(final->line[1],
+ " ub4 rsl = (((val >> %ld) & 3) ^ ((val >> %ld) & 2) ^ b);\n",
+ m, n-1);
+ }
+ else if (m==n-1 && m==0) /* 02,0a,0b,18 */
+ {
+ sprintf(final->line[1],
+ " ub4 rsl = ((val & 3) ^ b ^ (b << 1));\n");
+ }
+ else if (m==n-1) /* 0,2,4,8 */
+ {
+ sprintf(final->line[1],
+ " ub4 rsl = (((val >> %ld) & 3) ^ b ^ (b << 1));\n", m);
+ }
+ else if (o==n-1 && m==0) /* h4am: not reached */
+ {
+ sprintf(final->line[1],
+ " ub4 rsl = ((val & 1) ^ ((val >> %ld) & 3) ^ (b <<1 ));\n",
+ o);
+ }
+ else if (o==n-1) /* 0x00,0x02,0x08,0x10 */
+ {
+ sprintf(final->line[1],
+ " ub4 rsl = (((val >> %ld) & 1) ^ ((val >> %ld) & 3) ^ (b << 1));\n",
+ m, o);
+ }
+ else if ((m != o-1) && (m != n-1) && (o != m-1) && (o != n-1))
+ {
+ final->used = 3;
+ sprintf(final->line[0], " ub4 newval = val & 0x%lx;\n",
+ (((ub4)1<<m)^((ub4)1<<n)^((ub4)1<<o)));
+ if (o==0) /* 0x00,0x01,0x04,0x10 */
+ {
+ sprintf(final->line[1], " ub4 b = -newval;\n");
+ }
+ else /* 0x00,0x04,0x09,0x10 */
+ {
+ sprintf(final->line[1], " ub4 b = -(newval >> %ld);\n", o);
+ }
+ if (m==0) /* 0x00,0x04,0x09,0x10 */
+ {
+ sprintf(final->line[2],
+ " ub4 rsl = ((newval ^ (newval>>%ld) ^ b) & 3);\n", n-1);
+ }
+ else /* 0x00,0x03,0x04,0x10 */
+ {
+ sprintf(final->line[2],
+ " ub4 rsl = (((newval>>%ld) ^ (newval>>%ld) ^ b) & 3);\n",
+ m, n-1);
+ }
+ }
+ else if (o == m-1)
+ {
+ if (o==0) /* 0x02,0x03,0x0a,0x10 */
+ {
+ sprintf(final->line[0], " ub4 b = (val<<1) & 2;\n");
+ }
+ else if (o==1) /* 0x00,0x02,0x04,0x10 */
+ {
+ sprintf(final->line[0], " ub4 b = val & 2;\n");
+ }
+ else /* 0x00,0x04,0x08,0x20 */
+ {
+ sprintf(final->line[0], " ub4 b = (val>>%ld) & 2;\n", o-1);
+ }
+
+ if (o==0) /* 0x02,0x03,0x0a,0x10 */
+ {
+ sprintf(final->line[1],
+ " ub4 rsl = ((val & 3) ^ ((val>>%ld) & 1) ^ b);\n",
+ n);
+ }
+ else /* 0x00,0x02,0x04,0x10 */
+ {
+ sprintf(final->line[1],
+ " ub4 rsl = (((val>>%ld) & 3) ^ ((val>>%ld) & 1) ^ b);\n",
+ o, n);
+ }
+ }
+ else /* h4ax: 10 instructions, but not reached */
+ {
+ sprintf(final->line[1],
+ " ub4 rsl = (((val>>%ld) & 1) ^ ((val>>%ld) & 2) ^ b ^ (b<<1));\n",
+ m, n-1);
+ }
+
+ return;
+ }
+
+ /* five instructions, multiply bit o by 0, covered before the big guns */
+ w = ((a>>m)&1)^(a>>(n-1)&2);
+ x = ((b>>m)&1)^(b>>(n-1)&2);
+ y = ((c>>m)&1)^(c>>(n-1)&2);
+ z = ((d>>m)&1)^(d>>(n-1)&2);
+ if (testfour(w,x,y,z))
+ { /* h4v, not reached */
+ sprintf(final->line[0],
+ " ub4 rsl = (((val>>%ld) & 1) ^ ((val>>%ld) & 2));\n", m, n-1);
+ return;
+ }
+ }
+
+ printf("fatal error: bug in hexfour!\n");
+ exit(SUCCESS);
+ return;
+}
+
+
+/* test if a_k is distinct and in range for all keys */
+static int testeight(keys, badmask)
+key *keys; /* keys being hashed */
+ub1 badmask; /* used for minimal perfect hashing */
+{
+ ub1 mask = badmask;
+ key *mykey;
+
+ for (mykey=keys; mykey; mykey=mykey->next_k)
+ {
+ if (bit(mask, 1<<mykey->a_k)) return FALSE;
+ bis(mask, 1<<mykey->a_k);
+ }
+ return TRUE;
+}
+
+
+
+/*
+ * Try to find a perfect hash when there are five to eight keys.
+ *
+ * We can't deterministically find a perfect hash, but there's a reasonable
+ * chance we'll get lucky. Give it a shot. Return TRUE if we succeed.
+ */
+static int hexeight(keys, nkeys, final, form)
+key *keys;
+ub4 nkeys;
+gencode *final;
+hashform *form;
+{
+ key *mykey; /* walk through the keys */
+ ub4 i,j,k;
+ ub1 badmask;
+
+ printf("hexeight\n");
+
+ /* what hash values should never be used? */
+ badmask = 0;
+ if (form->perfect == MINIMAL_HP)
+ {
+ for (i=nkeys; i<8; ++i)
+ bis(badmask,(1<<i));
+ }
+
+ /* one instruction */
+ for (mykey=keys; mykey; mykey=mykey->next_k)
+ mykey->a_k = mykey->hash_k & 7;
+ if (testeight(keys, badmask))
+ { /* h8a */
+ final->used = 1;
+ sprintf(final->line[0], " ub4 rsl = (val & 7);\n");
+ return TRUE;
+ }
+
+ /* two instructions */
+ for (i=final->lowbit; i<=final->highbit-2; ++i)
+ {
+ for (mykey=keys; mykey; mykey=mykey->next_k)
+ mykey->a_k = (mykey->hash_k >> i) & 7;
+ if (testeight(keys, badmask))
+ { /* h8b */
+ final->used = 1;
+ sprintf(final->line[0], " ub4 rsl = ((val >> %ld) & 7);\n", i);
+ return TRUE;
+ }
+ }
+
+ /* four instructions */
+ for (i=final->lowbit; i<=final->highbit; ++i)
+ {
+ for (j=i+1; j<=final->highbit; ++j)
+ {
+ for (mykey=keys; mykey; mykey=mykey->next_k)
+ mykey->a_k = ((mykey->hash_k >> i)+(mykey->hash_k >> j)) & 7;
+ if (testeight(keys, badmask))
+ {
+ final->used = 1;
+ if (i == 0) /* h8c */
+ sprintf(final->line[0],
+ " ub4 rsl = ((val + (val >> %ld)) & 7);\n", j);
+ else /* h8d */
+ sprintf(final->line[0],
+ " ub4 rsl = (((val >> %ld) + (val >> %ld)) & 7);\n", i, j);
+ return TRUE;
+ }
+
+ for (mykey=keys; mykey; mykey=mykey->next_k)
+ mykey->a_k = ((mykey->hash_k >> i)^(mykey->hash_k >> j)) & 7;
+ if (testeight(keys, badmask))
+ {
+ final->used = 1;
+ if (i == 0) /* h8e */
+ sprintf(final->line[0],
+ " ub4 rsl = ((val ^ (val >> %ld)) & 7);\n", j);
+ else /* h8f */
+ sprintf(final->line[0],
+ " ub4 rsl = (((val >> %ld) ^ (val >> %ld)) & 7);\n", i, j);
+
+ return TRUE;
+ }
+
+ for (mykey=keys; mykey; mykey=mykey->next_k)
+ mykey->a_k = ((mykey->hash_k >> i)-(mykey->hash_k >> j)) & 7;
+ if (testeight(keys, badmask))
+ {
+ final->used = 1;
+ if (i == 0) /* h8g */
+ sprintf(final->line[0],
+ " ub4 rsl = ((val - (val >> %ld)) & 7);\n", j);
+ else /* h8h */
+ sprintf(final->line[0],
+ " ub4 rsl = (((val >> %ld) - (val >> %ld)) & 7);\n", i, j);
+
+ return TRUE;
+ }
+ }
+ }
+
+
+ /* six instructions */
+ for (i=final->lowbit; i<=final->highbit; ++i)
+ {
+ for (j=i+1; j<=final->highbit; ++j)
+ {
+ for (k=j+1; k<=final->highbit; ++k)
+ {
+ for (mykey=keys; mykey; mykey=mykey->next_k)
+ mykey->a_k = ((mykey->hash_k >> i) +
+ (mykey->hash_k >> j) +
+ (mykey->hash_k >> k)) & 7;
+ if (testeight(keys, badmask))
+ { /* h8i */
+ final->used = 1;
+ sprintf(final->line[0],
+ " ub4 rsl = (((val >> %ld) + (val >> %ld) + (val >> %ld)) & 7);\n",
+ i, j, k);
+ return TRUE;
+ }
+ }
+ }
+ }
+
+
+ return FALSE;
+}
+
+
+
+/*
+ * Guns aren't enough. Bring out the Bomb. Use tab[].
+ * This finds the initial (a,b) when we need to use tab[].
+ *
+ * We need to produce a different (a,b) every time this is called. Try all
+ * reasonable cases, fastest first.
+ *
+ * The initial mix (which this determines) can be filled into final starting
+ * at line[1]. val is set and a,b are declared. The final hash (at line[7])
+ * is a^tab[b] or a^scramble[tab[b]].
+ *
+ * The code will probably look like this, minus some stuff:
+ * val += CONSTANT;
+ * val ^= (val<<16);
+ * val += (val>>8);
+ * val ^= (val<<4);
+ * b = (val >> l) & 7;
+ * a = (val + (val<<m)) >> 29;
+ * return a^scramble[tab[b]];
+ * Note that *a* and tab[b] will be computed in parallel by most modern chips.
+ *
+ * final->i is the current state of the state machine.
+ * final->j and final->k are counters in the loops the states simulate.
+ */
+static void hexn(keys, salt, alen, blen, final)
+key *keys;
+ub4 salt;
+ub4 alen;
+ub4 blen;
+gencode *final;
+{
+ key *mykey;
+ ub4 highbit = final->highbit;
+ ub4 lowbit = final->lowbit;
+ ub4 alog = mylog2(alen);
+ ub4 blog = mylog2(blen);
+
+ for (;;)
+ {
+ switch(final->i)
+ {
+ case 1:
+ /* a = val>>30; b=val&3 */
+ for (mykey=keys; mykey; mykey=mykey->next_k)
+ {
+ mykey->a_k = (mykey->hash_k << (UB4BITS-(highbit+1)))>>(UB4BITS-alog);
+ mykey->b_k = (mykey->hash_k >> lowbit) & (blen-1);
+ }
+ if (lowbit == 0) /* hna */
+ sprintf(final->line[5], " b = (val & 0x%lx);\n",
+ blen-1);
+ else /* hnb */
+ sprintf(final->line[5], " b = ((val >> %ld) & 0x%lx);\n",
+ lowbit, blen-1);
+ if (highbit+1 == UB4BITS) /* hnc */
+ sprintf(final->line[6], " a = (val >> %ld);\n",
+ UB4BITS-alog);
+ else /* hnd */
+ sprintf(final->line[6], " a = ((val << %ld ) >> %ld);\n",
+ UB4BITS-(highbit+1), UB4BITS-alog);
+
+ ++final->i;
+ return;
+
+ case 2:
+ /* a = val&3; b=val>>30 */
+ for (mykey=keys; mykey; mykey=mykey->next_k)
+ {
+ mykey->a_k = (mykey->hash_k >> lowbit) & (alen-1);
+ mykey->b_k = (mykey->hash_k << (UB4BITS-(highbit+1)))>>(UB4BITS-blog);
+ }
+ if (highbit+1 == UB4BITS) /* hne */
+ sprintf(final->line[5], " b = (val >> %ld);\n",
+ UB4BITS-blog);
+ else /* hnf */
+ sprintf(final->line[5], " b = ((val << %ld ) >> %ld);\n",
+ UB4BITS-(highbit+1), UB4BITS-blog);
+ if (lowbit == 0) /* hng */
+ sprintf(final->line[6], " a = (val & 0x%lx);\n",
+ alen-1);
+ else /* hnh */
+ sprintf(final->line[6], " a = ((val >> %ld) & 0x%lx);\n",
+ lowbit, alen-1);
+
+ ++final->i;
+ return;
+
+ case 3:
+ /*
+ * cases 3,4,5:
+ * for (k=lowbit; k<=highbit; ++k)
+ * for (j=lowbit; j<=highbit; ++j)
+ * b = (val>>j)&3;
+ * a = (val<<k)>>30;
+ */
+ final->k = lowbit;
+ final->j = lowbit;
+ ++final->i;
+ break;
+
+ case 4:
+ if (!(final->j < highbit))
+ {
+ ++final->i;
+ break;
+ }
+ for (mykey=keys; mykey; mykey=mykey->next_k)
+ {
+ mykey->b_k = (mykey->hash_k >> (final->j)) & (blen-1);
+ mykey->a_k = (mykey->hash_k << (UB4BITS-final->k-1)) >> (UB4BITS-alog);
+ }
+ if (final->j == 0) /* hni */
+ sprintf(final->line[5], " b = val & 0x%lx;\n",
+ blen-1);
+ else if (blog+final->j == UB4BITS) /* hnja */
+ sprintf(final->line[5], " b = val >> %ld;\n",
+ final->j);
+ else
+ sprintf(final->line[5], " b = (val >> %ld) & 0x%lx;\n", /* hnj */
+ final->j, blen-1);
+ if (UB4BITS-final->k-1 == 0) /* hnk */
+ sprintf(final->line[6], " a = (val >> %ld);\n",
+ UB4BITS-alog);
+ else /* hnl */
+ sprintf(final->line[6], " a = ((val << %ld) >> %ld);\n",
+ UB4BITS-final->k-1, UB4BITS-alog);
+ while (++final->j < highbit)
+ {
+ if (((final->diffbits>>(final->j)) & (blen-1)) > 2)
+ break;
+ }
+ return;
+
+ case 5:
+ while (++final->k < highbit)
+ {
+ if ((((final->diffbits<<(UB4BITS-final->k-1))>>alog) & (alen-1)) > 0)
+ break;
+ }
+ if (!(final->k < highbit))
+ {
+ ++final->i;
+ break;
+ }
+ final->j = lowbit;
+ final->i = 4;
+ break;
+
+
+ case 6:
+ /*
+ * cases 6,7,8:
+ * for (k=0; k<UB4BITS-alog; ++k)
+ * for (j=0; j<UB4BITS-blog; ++j)
+ * val = val+f(salt);
+ * val ^= (val >> 16);
+ * val += (val << 8);
+ * val ^= (val >> 4);
+ * b = (val >> j) & 3;
+ * a = (val + (val << k)) >> 30;
+ */
+ final->k = 0;
+ final->j = 0;
+ ++final->i;
+ break;
+
+ case 7:
+ /* Just do something that will surely work */
+ {
+ ub4 addk = 0x9e3779b9*salt;
+
+ if (!(final->j <= UB4BITS-blog))
+ {
+ ++final->i;
+ break;
+ }
+ for (mykey=keys; mykey; mykey=mykey->next_k)
+ {
+ ub4 val = mykey->hash_k + addk;
+ if (final->highbit+1 - final->lowbit > 16)
+ val ^= (val >> 16);
+ if (final->highbit+1 - final->lowbit > 8)
+ val += (val << 8);
+ val ^= (val >> 4);
+ mykey->b_k = (val >> final->j) & (blen-1);
+ if (final->k == 0)
+ mykey->a_k = val >> (UB4BITS-alog);
+ else
+ mykey->a_k = (val + (val << final->k)) >> (UB4BITS-alog);
+ }
+ sprintf(final->line[1], " val += 0x%lx;\n", addk);
+ if (final->highbit+1 - final->lowbit > 16) /* hnm */
+ sprintf(final->line[2], " val ^= (val >> 16);\n");
+ if (final->highbit+1 - final->lowbit > 8) /* hnn */
+ sprintf(final->line[3], " val += (val << 8);\n");
+ sprintf(final->line[4], " val ^= (val >> 4);\n");
+ if (final->j == 0) /* hno: don't know how to reach this */
+ sprintf(final->line[5], " b = val & 0x%lx;\n", blen-1);
+ else /* hnp */
+ sprintf(final->line[5], " b = (val >> %ld) & 0x%lx;\n",
+ final->j, blen-1);
+ if (final->k == 0) /* hnq */
+ sprintf(final->line[6], " a = val >> %ld;\n", UB4BITS-alog);
+ else /* hnr */
+ sprintf(final->line[6], " a = (val + (val << %ld)) >> %ld;\n",
+ final->k, UB4BITS-alog);
+
+ ++final->j;
+ return;
+ }
+
+ case 8:
+ ++final->k;
+ if (!(final->k <= UB4BITS-alog))
+ {
+ ++final->i;
+ break;
+ }
+ final->j = 0;
+ final->i = 7;
+ break;
+
+ case 9:
+ final->i = 6;
+ break;
+ }
+ }
+}
+
+
+
+/* find the highest and lowest bit where any key differs */
+static void setlow(keys, final)
+key *keys;
+gencode *final;
+{
+ ub4 lowbit;
+ ub4 highbit;
+ ub4 i;
+ key *mykey;
+ ub4 firstkey;
+
+ /* mark the interesting bits in final->mask */
+ final->diffbits = (ub4)0;
+ if (keys) firstkey = keys->hash_k;
+ for (mykey=keys; mykey!=(key *)0; mykey=mykey->next_k)
+ final->diffbits |= (firstkey ^ mykey->hash_k);
+
+ /* find the lowest interesting bit */
+ for (i=0; i<UB4BITS; ++i)
+ if (final->diffbits & (((ub4)1)<<i))
+ break;
+ final->lowbit = i;
+
+ /* find the highest interesting bit */
+ for (i=UB4BITS; --i; )
+ if (final->diffbits & (((ub4)1)<<i))
+ break;
+ final->highbit = i;
+}
+
+/*
+ * Initialize (a,b) when keys are integers.
+ *
+ * Normally there's an initial hash which produces a number. That hash takes
+ * an initializer. Changing the initializer causes the initial hash to
+ * produce a different (uniformly distributed) number without any extra work.
+ *
+ * Well, here we start with a number. There's no initial hash. Any mixing
+ * costs extra work. So we go through a lot of special cases to minimize the
+ * mixing needed to get distinct (a,b). For small sets of keys, it's often
+ * fastest to skip the final hash and produce the perfect hash from the number
+ * directly.
+ *
+ * The target user for this is switch statement optimization. The common case
+ * is 3 to 16 keys, and instruction counts matter. The competition is a
+ * binary tree of branches.
+ *
+ * Return TRUE if we found a perfect hash and no more work is needed.
+ * Return FALSE if we just did an initial hash and more work is needed.
+ */
+int inithex(keys, nkeys, alen, blen, smax, salt, final, form)
+key *keys; /* list of all keys */
+ub4 nkeys; /* number of keys to hash */
+ub4 alen; /* (a,b) has a in 0..alen-1, a power of 2 */
+ub4 blen; /* (a,b) has b in 0..blen-1, a power of 2 */
+ub4 smax; /* maximum range of computable hash values */
+ub4 salt; /* used to initialize the hash function */
+gencode *final; /* output, code for the final hash */
+hashform *form; /* user directives */
+{
+ setlow(keys, final);
+
+ switch (nkeys)
+ {
+ case 1:
+ hexone(keys, final);
+ return TRUE;
+ case 2:
+ hextwo(keys, final);
+ return TRUE;
+ case 3:
+ hexthree(keys, final, form);
+ return TRUE;
+ case 4:
+ hexfour(keys, final);
+ return TRUE;
+ case 5: case 6: case 7: case 8:
+ if (salt == 1 && /* first time through */
+ hexeight(keys, nkeys, final, form)) /* get lucky, don't need tab[] ? */
+ return TRUE;
+ /* fall through */
+ default:
+ if (salt == 1)
+ {
+ final->used = 8;
+ final->i = 1;
+ final->j = final->k = final->l = final->m = final->n = final->o = 0;
+ sprintf(final->line[0], " ub4 a, b, rsl;\n");
+ sprintf(final->line[1], "\n");
+ sprintf(final->line[2], "\n");
+ sprintf(final->line[3], "\n");
+ sprintf(final->line[4], "\n");
+ sprintf(final->line[5], "\n");
+ sprintf(final->line[6], "\n");
+ if (blen < USE_SCRAMBLE)
+ { /* hns */
+ sprintf(final->line[7], " rsl = (a^tab[b]);\n");
+ }
+ else
+ { /* hnt */
+ sprintf(final->line[7], " rsl = (a^scramble[tab[b]]);\n");
+ }
+ }
+ hexn(keys, salt, alen, blen, final);
+ return FALSE;
+ }
+}
diff --git a/tools/codegen/core/perfect/recycle.c b/tools/codegen/core/perfect/recycle.c
new file mode 100644
index 0000000000..3f857cba7d
--- /dev/null
+++ b/tools/codegen/core/perfect/recycle.c
@@ -0,0 +1,87 @@
+/*
+--------------------------------------------------------------------
+By Bob Jenkins, September 1996. recycle.c
+You may use this code in any way you wish, and it is free. No warranty.
+
+This manages memory for commonly-allocated structures.
+It allocates RESTART to REMAX items at a time.
+Timings have shown that, if malloc is used for every new structure,
+ malloc will consume about 90% of the time in a program. This
+ module cuts down the number of mallocs by an order of magnitude.
+This also decreases memory fragmentation, and freeing structures
+ only requires freeing the root.
+--------------------------------------------------------------------
+*/
+
+#ifndef STANDARD
+# include "standard.h"
+#endif
+#ifndef RECYCLE
+# include "recycle.h"
+#endif
+
+reroot *remkroot(size)
+size_t size;
+{
+ reroot *r = (reroot *)remalloc(sizeof(reroot), "recycle.c, root");
+ r->list = (recycle *)0;
+ r->trash = (recycle *)0;
+ r->size = align(size);
+ r->logsize = RESTART;
+ r->numleft = 0;
+ return r;
+}
+
+void refree(r)
+struct reroot *r;
+{
+ recycle *temp;
+ if (temp = r->list) while (r->list)
+ {
+ temp = r->list->next;
+ free((char *)r->list);
+ r->list = temp;
+ }
+ free((char *)r);
+ return;
+}
+
+/* to be called from the macro renew only */
+char *renewx(r)
+struct reroot *r;
+{
+ recycle *temp;
+ if (r->trash)
+ { /* pull a node off the trash heap */
+ temp = r->trash;
+ r->trash = temp->next;
+ (void)memset((void *)temp, 0, r->size);
+ }
+ else
+ { /* allocate a new block of nodes */
+ r->numleft = r->size*((ub4)1<<r->logsize);
+ if (r->numleft < REMAX) ++r->logsize;
+ temp = (recycle *)remalloc(sizeof(recycle) + r->numleft,
+ "recycle.c, data");
+ temp->next = r->list;
+ r->list = temp;
+ r->numleft-=r->size;
+ temp = (recycle *)((char *)(r->list+1)+r->numleft);
+ }
+ return (char *)temp;
+}
+
+char *remalloc(len, purpose)
+size_t len;
+char *purpose;
+{
+ char *x = (char *)malloc(len);
+ if (!x)
+ {
+ fprintf(stderr, "malloc of %d failed for %s\n",
+ len, purpose);
+ exit(SUCCESS);
+ }
+ return x;
+}
+
diff --git a/tools/codegen/core/perfect/recycle.h b/tools/codegen/core/perfect/recycle.h
new file mode 100644
index 0000000000..7472495e84
--- /dev/null
+++ b/tools/codegen/core/perfect/recycle.h
@@ -0,0 +1,65 @@
+/*
+--------------------------------------------------------------------
+By Bob Jenkins, September 1996. recycle.h
+You may use this code in any way you wish, and it is free. No warranty.
+
+This manages memory for commonly-allocated structures.
+It allocates RESTART to REMAX items at a time.
+Timings have shown that, if malloc is used for every new structure,
+ malloc will consume about 90% of the time in a program. This
+ module cuts down the number of mallocs by an order of magnitude.
+This also decreases memory fragmentation, and freeing all structures
+ only requires freeing the root.
+--------------------------------------------------------------------
+*/
+
+#ifndef STANDARD
+#include "standard.h"
+#endif
+
+#ifndef RECYCLE
+#define RECYCLE
+
+#define RESTART 0
+#define REMAX 32000
+
+struct recycle
+{
+ struct recycle *next;
+};
+typedef struct recycle recycle;
+
+struct reroot
+{
+ struct recycle *list; /* list of malloced blocks */
+ struct recycle *trash; /* list of deleted items */
+ size_t size; /* size of an item */
+ size_t logsize; /* log_2 of number of items in a block */
+ word numleft; /* number of bytes left in this block */
+};
+typedef struct reroot reroot;
+
+/* make a new recycling root */
+reroot *remkroot(/*_ size_t mysize _*/);
+
+/* free a recycling root and all the items it has made */
+void refree(/*_ struct reroot *r _*/);
+
+/* get a new (cleared) item from the root */
+#define renew(r) ((r)->numleft ? \
+ (((char *)((r)->list+1))+((r)->numleft-=(r)->size)) : renewx(r))
+
+char *renewx(/*_ struct reroot *r _*/);
+
+/* delete an item; let the root recycle it */
+/* void redel(/o_ struct reroot *r, struct recycle *item _o/); */
+#define redel(root,item) { \
+ ((recycle *)item)->next=(root)->trash; \
+ (root)->trash=(recycle *)(item); \
+}
+
+/* malloc, but complain to stderr and exit program if no joy */
+/* use plain free() to free memory allocated by remalloc() */
+char *remalloc(/*_ size_t len, char *purpose _*/);
+
+#endif /* RECYCLE */
diff --git a/tools/codegen/core/perfect/run.sh b/tools/codegen/core/perfect/run.sh
new file mode 100755
index 0000000000..8dc5911cbd
--- /dev/null
+++ b/tools/codegen/core/perfect/run.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+set -e
+cd $(dirname $0)
+gcc -o perfect perfect.c recycle.c lookupa.c perfhex.c 2> compile.txt
+fn=$1
+shift
+./perfect $* < $fn &> hash.txt
diff --git a/tools/codegen/core/perfect/standard.h b/tools/codegen/core/perfect/standard.h
new file mode 100644
index 0000000000..202a5d658c
--- /dev/null
+++ b/tools/codegen/core/perfect/standard.h
@@ -0,0 +1,57 @@
+/*
+------------------------------------------------------------------------------
+Standard definitions and types, Bob Jenkins
+------------------------------------------------------------------------------
+*/
+#ifndef STANDARD
+# define STANDARD
+# ifndef STDIO
+# include <stdio.h>
+# define STDIO
+# endif
+# ifndef STDDEF
+# include <stddef.h>
+# define STDDEF
+# endif
+typedef unsigned long long ub8;
+#define UB8MAXVAL 0xffffffffffffffffLL
+#define UB8BITS 64
+typedef signed long long sb8;
+#define SB8MAXVAL 0x7fffffffffffffffLL
+typedef unsigned long int ub4; /* unsigned 4-byte quantities */
+#define UB4MAXVAL 0xffffffff
+typedef signed long int sb4;
+#define UB4BITS 32
+#define SB4MAXVAL 0x7fffffff
+typedef unsigned short int ub2;
+#define UB2MAXVAL 0xffff
+#define UB2BITS 16
+typedef signed short int sb2;
+#define SB2MAXVAL 0x7fff
+typedef unsigned char ub1;
+#define UB1MAXVAL 0xff
+#define UB1BITS 8
+typedef signed char sb1; /* signed 1-byte quantities */
+#define SB1MAXVAL 0x7f
+typedef int word; /* fastest type available */
+
+#define bis(target,mask) ((target) |= (mask))
+#define bic(target,mask) ((target) &= ~(mask))
+#define bit(target,mask) ((target) & (mask))
+#ifndef min
+# define min(a,b) (((a)<(b)) ? (a) : (b))
+#endif /* min */
+#ifndef max
+# define max(a,b) (((a)<(b)) ? (b) : (a))
+#endif /* max */
+#ifndef align
+# define align(a) (((ub4)a+(sizeof(void *)-1))&(~(sizeof(void *)-1)))
+#endif /* align */
+#ifndef abs
+# define abs(a) (((a)>0) ? (a) : -(a))
+#endif
+#define TRUE 1
+#define FALSE 0
+#define SUCCESS 0 /* 1 on VAX */
+
+#endif /* STANDARD */
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index 6c8020d203..6c40c0f2f6 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -863,6 +863,7 @@ src/core/lib/json/json_common.h \
src/core/lib/json/json_reader.h \
src/core/lib/json/json_writer.h \
src/core/lib/slice/percent_encoding.h \
+src/core/lib/slice/slice_hash_table.h \
src/core/lib/slice/slice_string_helpers.h \
src/core/lib/surface/api_trace.h \
src/core/lib/surface/call.h \
@@ -877,7 +878,6 @@ src/core/lib/surface/lame_client.h \
src/core/lib/surface/server.h \
src/core/lib/transport/byte_stream.h \
src/core/lib/transport/connectivity_state.h \
-src/core/lib/transport/mdstr_hash_table.h \
src/core/lib/transport/metadata.h \
src/core/lib/transport/metadata_batch.h \
src/core/lib/transport/method_config.h \
@@ -1049,6 +1049,7 @@ src/core/lib/json/json_writer.c \
src/core/lib/slice/percent_encoding.c \
src/core/lib/slice/slice.c \
src/core/lib/slice/slice_buffer.c \
+src/core/lib/slice/slice_hash_table.c \
src/core/lib/slice/slice_intern.c \
src/core/lib/slice/slice_string_helpers.c \
src/core/lib/surface/alarm.c \
@@ -1071,7 +1072,6 @@ src/core/lib/surface/validate_metadata.c \
src/core/lib/surface/version.c \
src/core/lib/transport/byte_stream.c \
src/core/lib/transport/connectivity_state.c \
-src/core/lib/transport/mdstr_hash_table.c \
src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/method_config.c \
diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json
index 0386587a2b..092c3cd65c 100644
--- a/tools/run_tests/sources_and_headers.json
+++ b/tools/run_tests/sources_and_headers.json
@@ -6746,6 +6746,7 @@
"src/core/lib/json/json_reader.h",
"src/core/lib/json/json_writer.h",
"src/core/lib/slice/percent_encoding.h",
+ "src/core/lib/slice/slice_hash_table.h",
"src/core/lib/slice/slice_string_helpers.h",
"src/core/lib/surface/api_trace.h",
"src/core/lib/surface/call.h",
@@ -6760,7 +6761,6 @@
"src/core/lib/surface/server.h",
"src/core/lib/transport/byte_stream.h",
"src/core/lib/transport/connectivity_state.h",
- "src/core/lib/transport/mdstr_hash_table.h",
"src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/method_config.h",
@@ -6939,6 +6939,8 @@
"src/core/lib/slice/percent_encoding.h",
"src/core/lib/slice/slice.c",
"src/core/lib/slice/slice_buffer.c",
+ "src/core/lib/slice/slice_hash_table.c",
+ "src/core/lib/slice/slice_hash_table.h",
"src/core/lib/slice/slice_intern.c",
"src/core/lib/slice/slice_string_helpers.c",
"src/core/lib/slice/slice_string_helpers.h",
@@ -6975,8 +6977,6 @@
"src/core/lib/transport/byte_stream.h",
"src/core/lib/transport/connectivity_state.c",
"src/core/lib/transport/connectivity_state.h",
- "src/core/lib/transport/mdstr_hash_table.c",
- "src/core/lib/transport/mdstr_hash_table.h",
"src/core/lib/transport/metadata.c",
"src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.c",
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj
index d33579a5f2..24b8cedef6 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj
@@ -372,6 +372,7 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_reader.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_writer.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.h" />
+ <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call.h" />
@@ -386,7 +387,6 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\server.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.h" />
- <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\method_config.h" />
@@ -643,6 +643,8 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_buffer.c">
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.c">
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_intern.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.c">
@@ -687,8 +689,6 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.c">
</ClCompile>
- <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.c">
- </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c">
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
index b4e8eefe02..0529f7d1fd 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
@@ -250,6 +250,9 @@
<ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_buffer.c">
<Filter>src\core\lib\slice</Filter>
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.c">
+ <Filter>src\core\lib\slice</Filter>
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_intern.c">
<Filter>src\core\lib\slice</Filter>
</ClCompile>
@@ -316,9 +319,6 @@
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.c">
<Filter>src\core\lib\transport</Filter>
</ClCompile>
- <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.c">
- <Filter>src\core\lib\transport</Filter>
- </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata.c">
<Filter>src\core\lib\transport</Filter>
</ClCompile>
@@ -956,6 +956,9 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.h">
<Filter>src\core\lib\slice</Filter>
</ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.h">
+ <Filter>src\core\lib\slice</Filter>
+ </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.h">
<Filter>src\core\lib\slice</Filter>
</ClInclude>
@@ -998,9 +1001,6 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.h">
<Filter>src\core\lib\transport</Filter>
</ClInclude>
- <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.h">
- <Filter>src\core\lib\transport</Filter>
- </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h">
<Filter>src\core\lib\transport</Filter>
</ClInclude>
diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
index 79a233a72b..b3e2be9650 100644
--- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
+++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
@@ -265,6 +265,7 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_reader.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_writer.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.h" />
+ <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call.h" />
@@ -279,7 +280,6 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\server.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.h" />
- <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\method_config.h" />
@@ -494,6 +494,8 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_buffer.c">
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.c">
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_intern.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.c">
@@ -538,8 +540,6 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.c">
</ClCompile>
- <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.c">
- </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c">
diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
index 1e70d60b24..4dbfa6b52a 100644
--- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
@@ -307,6 +307,9 @@
<ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_buffer.c">
<Filter>src\core\lib\slice</Filter>
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.c">
+ <Filter>src\core\lib\slice</Filter>
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_intern.c">
<Filter>src\core\lib\slice</Filter>
</ClCompile>
@@ -373,9 +376,6 @@
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.c">
<Filter>src\core\lib\transport</Filter>
</ClCompile>
- <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.c">
- <Filter>src\core\lib\transport</Filter>
- </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata.c">
<Filter>src\core\lib\transport</Filter>
</ClCompile>
@@ -752,6 +752,9 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.h">
<Filter>src\core\lib\slice</Filter>
</ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.h">
+ <Filter>src\core\lib\slice</Filter>
+ </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.h">
<Filter>src\core\lib\slice</Filter>
</ClInclude>
@@ -794,9 +797,6 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.h">
<Filter>src\core\lib\transport</Filter>
</ClInclude>
- <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.h">
- <Filter>src\core\lib\transport</Filter>
- </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h">
<Filter>src\core\lib\transport</Filter>
</ClInclude>
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
index bbc3fbd898..ead1eef561 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
@@ -362,6 +362,7 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_reader.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_writer.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.h" />
+ <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call.h" />
@@ -376,7 +377,6 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\server.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.h" />
- <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\method_config.h" />
@@ -611,6 +611,8 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_buffer.c">
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.c">
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_intern.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.c">
@@ -655,8 +657,6 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.c">
</ClCompile>
- <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.c">
- </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c">
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
index 0782c54aef..94b7fb379f 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
@@ -253,6 +253,9 @@
<ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_buffer.c">
<Filter>src\core\lib\slice</Filter>
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.c">
+ <Filter>src\core\lib\slice</Filter>
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_intern.c">
<Filter>src\core\lib\slice</Filter>
</ClCompile>
@@ -319,9 +322,6 @@
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.c">
<Filter>src\core\lib\transport</Filter>
</ClCompile>
- <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.c">
- <Filter>src\core\lib\transport</Filter>
- </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata.c">
<Filter>src\core\lib\transport</Filter>
</ClCompile>
@@ -869,6 +869,9 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.h">
<Filter>src\core\lib\slice</Filter>
</ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.h">
+ <Filter>src\core\lib\slice</Filter>
+ </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.h">
<Filter>src\core\lib\slice</Filter>
</ClInclude>
@@ -911,9 +914,6 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.h">
<Filter>src\core\lib\transport</Filter>
</ClInclude>
- <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.h">
- <Filter>src\core\lib\transport</Filter>
- </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h">
<Filter>src\core\lib\transport</Filter>
</ClInclude>