diff --git a/src/core/lib/compression/compression_internal.cc b/src/core/lib/compression/compression_internal.cc index df7646d0f03..e1a7a290109 100644 --- a/src/core/lib/compression/compression_internal.cc +++ b/src/core/lib/compression/compression_internal.cc @@ -52,6 +52,48 @@ const char* CompressionAlgorithmAsString(grpc_compression_algorithm algorithm) { } } +namespace { +class CommaSeparatedLists { + public: + CommaSeparatedLists() : lists_{}, text_buffer_{} { + char* text_buffer = text_buffer_; + auto add_char = [&text_buffer, this](char c) { + if (text_buffer - text_buffer_ == kTextBufferSize) abort(); + *text_buffer++ = c; + }; + for (size_t list = 0; list < kNumLists; ++list) { + char* start = text_buffer; + for (size_t algorithm = 0; algorithm < GRPC_COMPRESS_ALGORITHMS_COUNT; + ++algorithm) { + if ((list & (1 << algorithm)) == 0) continue; + if (start != text_buffer) { + add_char(','); + add_char(' '); + } + const char* name = CompressionAlgorithmAsString( + static_cast(algorithm)); + for (const char* p = name; *p != '\0'; ++p) { + add_char(*p); + } + } + lists_[list] = absl::string_view(start, text_buffer - start); + } + if (text_buffer - text_buffer_ != kTextBufferSize) abort(); + } + + absl::string_view operator[](size_t list) const { return lists_[list]; } + + private: + static constexpr size_t kNumLists = 1 << GRPC_COMPRESS_ALGORITHMS_COUNT; + // Experimentally determined (tweak things until it runs). + static constexpr size_t kTextBufferSize = 86; + absl::string_view lists_[kNumLists]; + char text_buffer_[kTextBufferSize]; +}; + +const CommaSeparatedLists kCommaSeparatedLists; +} // namespace + absl::optional ParseCompressionAlgorithm( absl::string_view algorithm) { if (algorithm == "identity") { @@ -165,19 +207,12 @@ void CompressionAlgorithmSet::Set(grpc_compression_algorithm algorithm) { } } -std::string CompressionAlgorithmSet::ToString() const { - absl::InlinedVector segments; - for (size_t i = 0; i < GRPC_COMPRESS_ALGORITHMS_COUNT; i++) { - if (set_.is_set(i)) { - segments.push_back(CompressionAlgorithmAsString( - static_cast(i))); - } - } - return absl::StrJoin(segments, ", "); +absl::string_view CompressionAlgorithmSet::ToString() const { + return kCommaSeparatedLists[ToLegacyBitmask()]; } Slice CompressionAlgorithmSet::ToSlice() const { - return Slice::FromCopiedString(ToString()); + return Slice::FromStaticString(ToString()); } CompressionAlgorithmSet CompressionAlgorithmSet::FromString( diff --git a/src/core/lib/compression/compression_internal.h b/src/core/lib/compression/compression_internal.h index 7a676b744f6..4673266a27a 100644 --- a/src/core/lib/compression/compression_internal.h +++ b/src/core/lib/compression/compression_internal.h @@ -73,7 +73,7 @@ class CompressionAlgorithmSet { void Set(grpc_compression_algorithm algorithm); // Return a comma separated string of the algorithms in this set. - std::string ToString() const; + absl::string_view ToString() const; Slice ToSlice() const; // Return a bitmask of the algorithms in this set. diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index f6627cf6e75..df705744a81 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -1257,7 +1257,8 @@ void FilterStackCall::HandleCompressionAlgorithmNotAccepted( gpr_log(GPR_ERROR, "Compression algorithm ('%s') not present in the " "accepted encodings (%s)", - algo_name, encodings_accepted_by_peer_.ToString().c_str()); + algo_name, + std::string(encodings_accepted_by_peer_.ToString()).c_str()); } void FilterStackCall::BatchControl::ValidateFilteredMetadata() { diff --git a/src/core/lib/transport/metadata_batch.h b/src/core/lib/transport/metadata_batch.h index afafa3378bb..79afb4014bf 100644 --- a/src/core/lib/transport/metadata_batch.h +++ b/src/core/lib/transport/metadata_batch.h @@ -194,7 +194,7 @@ struct GrpcAcceptEncodingMetadata { } static ValueType MementoToValue(MementoType x) { return x; } static Slice Encode(ValueType x) { return x.ToSlice(); } - static std::string DisplayValue(MementoType x) { return x.ToString(); } + static absl::string_view DisplayValue(MementoType x) { return x.ToString(); } }; struct SimpleSliceBasedMetadata {