abseil-cpp/absl/flags/internal/usage.cc
Go to the documentation of this file.
1 //
2 // Copyright 2019 The Abseil Authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // https://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #include "absl/flags/internal/usage.h"
17 
18 #include <stdint.h>
19 
20 #include <functional>
21 #include <map>
22 #include <ostream>
23 #include <string>
24 #include <utility>
25 #include <vector>
26 
27 #include "absl/base/config.h"
28 #include "absl/flags/commandlineflag.h"
29 #include "absl/flags/flag.h"
30 #include "absl/flags/internal/flag.h"
31 #include "absl/flags/internal/path_util.h"
32 #include "absl/flags/internal/private_handle_accessor.h"
33 #include "absl/flags/internal/program_name.h"
34 #include "absl/flags/internal/registry.h"
35 #include "absl/flags/usage_config.h"
36 #include "absl/strings/str_cat.h"
37 #include "absl/strings/str_split.h"
38 #include "absl/strings/string_view.h"
39 
40 // Dummy global variables to prevent anyone else defining these.
41 bool FLAGS_help = false;
42 bool FLAGS_helpfull = false;
43 bool FLAGS_helpshort = false;
44 bool FLAGS_helppackage = false;
45 bool FLAGS_version = false;
46 bool FLAGS_only_check_args = false;
47 bool FLAGS_helpon = false;
48 bool FLAGS_helpmatch = false;
49 
50 namespace absl {
52 namespace flags_internal {
53 namespace {
54 
55 using PerFlagFilter = std::function<bool(const absl::CommandLineFlag&)>;
56 
57 // Maximum length size in a human readable format.
58 constexpr size_t kHrfMaxLineLength = 80;
59 
60 // This class is used to emit an XML element with `tag` and `text`.
61 // It adds opening and closing tags and escapes special characters in the text.
62 // For example:
63 // std::cout << XMLElement("title", "Milk & Cookies");
64 // prints "<title>Milk &amp; Cookies</title>"
65 class XMLElement {
66  public:
67  XMLElement(absl::string_view tag, absl::string_view txt)
68  : tag_(tag), txt_(txt) {}
69 
70  friend std::ostream& operator<<(std::ostream& out,
71  const XMLElement& xml_elem) {
72  out << "<" << xml_elem.tag_ << ">";
73 
74  for (auto c : xml_elem.txt_) {
75  switch (c) {
76  case '"':
77  out << "&quot;";
78  break;
79  case '\'':
80  out << "&apos;";
81  break;
82  case '&':
83  out << "&amp;";
84  break;
85  case '<':
86  out << "&lt;";
87  break;
88  case '>':
89  out << "&gt;";
90  break;
91  default:
92  out << c;
93  break;
94  }
95  }
96 
97  return out << "</" << xml_elem.tag_ << ">";
98  }
99 
100  private:
103 };
104 
105 // --------------------------------------------------------------------
106 // Helper class to pretty-print info about a flag.
107 
108 class FlagHelpPrettyPrinter {
109  public:
110  // Pretty printer holds on to the std::ostream& reference to direct an output
111  // to that stream.
112  FlagHelpPrettyPrinter(size_t max_line_len, size_t min_line_len,
113  size_t wrapped_line_indent, std::ostream& out)
114  : out_(out),
115  max_line_len_(max_line_len),
116  min_line_len_(min_line_len),
117  wrapped_line_indent_(wrapped_line_indent),
118  line_len_(0),
119  first_line_(true) {}
120 
121  void Write(absl::string_view str, bool wrap_line = false) {
122  // Empty string - do nothing.
123  if (str.empty()) return;
124 
125  std::vector<absl::string_view> tokens;
126  if (wrap_line) {
127  for (auto line : absl::StrSplit(str, absl::ByAnyChar("\n\r"))) {
128  if (!tokens.empty()) {
129  // Keep line separators in the input string.
130  tokens.push_back("\n");
131  }
132  for (auto token :
134  tokens.push_back(token);
135  }
136  }
137  } else {
138  tokens.push_back(str);
139  }
140 
141  for (auto token : tokens) {
142  bool new_line = (line_len_ == 0);
143 
144  // Respect line separators in the input string.
145  if (token == "\n") {
146  EndLine();
147  continue;
148  }
149 
150  // Write the token, ending the string first if necessary/possible.
151  if (!new_line &&
152  (line_len_ + static_cast<int>(token.size()) >= max_line_len_)) {
153  EndLine();
154  new_line = true;
155  }
156 
157  if (new_line) {
158  StartLine();
159  } else {
160  out_ << ' ';
161  ++line_len_;
162  }
163 
164  out_ << token;
165  line_len_ += token.size();
166  }
167  }
168 
169  void StartLine() {
170  if (first_line_) {
172  first_line_ = false;
173  } else {
175  }
176  out_ << std::string(line_len_, ' ');
177  }
178  void EndLine() {
179  out_ << '\n';
180  line_len_ = 0;
181  }
182 
183  private:
184  std::ostream& out_;
185  const size_t max_line_len_;
186  const size_t min_line_len_;
187  const size_t wrapped_line_indent_;
188  size_t line_len_;
190 };
191 
192 void FlagHelpHumanReadable(const CommandLineFlag& flag, std::ostream& out) {
193  FlagHelpPrettyPrinter printer(kHrfMaxLineLength, 4, 2, out);
194 
195  // Flag name.
196  printer.Write(absl::StrCat("--", flag.Name()));
197 
198  // Flag help.
199  printer.Write(absl::StrCat("(", flag.Help(), ");"), /*wrap_line=*/true);
200 
201  // The listed default value will be the actual default from the flag
202  // definition in the originating source file, unless the value has
203  // subsequently been modified using SetCommandLineOption() with mode
204  // SET_FLAGS_DEFAULT.
205  std::string dflt_val = flag.DefaultValue();
206  std::string curr_val = flag.CurrentValue();
207  bool is_modified = curr_val != dflt_val;
208 
209  if (flag.IsOfType<std::string>()) {
210  dflt_val = absl::StrCat("\"", dflt_val, "\"");
211  }
212  printer.Write(absl::StrCat("default: ", dflt_val, ";"));
213 
214  if (is_modified) {
215  if (flag.IsOfType<std::string>()) {
216  curr_val = absl::StrCat("\"", curr_val, "\"");
217  }
218  printer.Write(absl::StrCat("currently: ", curr_val, ";"));
219  }
220 
221  printer.EndLine();
222 }
223 
224 // Shows help for every filename which matches any of the filters
225 // If filters are empty, shows help for every file.
226 // If a flag's help message has been stripped (e.g. by adding '#define
227 // STRIP_FLAG_HELP 1' then this flag will not be displayed by '--help'
228 // and its variants.
229 void FlagsHelpImpl(std::ostream& out, PerFlagFilter filter_cb,
230  HelpFormat format, absl::string_view program_usage_message) {
233  << program_usage_message << "\n\n";
234  } else {
235  // XML schema is not a part of our public API for now.
236  out << "<?xml version=\"1.0\"?>\n"
237  << "<!-- This output should be used with care. We do not report type "
238  "names for flags with user defined types -->\n"
239  << "<!-- Prefer flag only_check_args for validating flag inputs -->\n"
240  // The document.
241  << "<AllFlags>\n"
242  // The program name and usage.
243  << XMLElement("program", flags_internal::ShortProgramInvocationName())
244  << '\n'
245  << XMLElement("usage", program_usage_message) << '\n';
246  }
247 
248  // Ordered map of package name to
249  // map of file name to
250  // vector of flags in the file.
251  // This map is used to output matching flags grouped by package and file
252  // name.
254  std::map<std::string, std::vector<const absl::CommandLineFlag*>>>
255  matching_flags;
256 
258  // Ignore retired flags.
259  if (flag.IsRetired()) return;
260 
261  // If the flag has been stripped, pretend that it doesn't exist.
262  if (flag.Help() == flags_internal::kStrippedFlagHelp) return;
263 
264  // Make sure flag satisfies the filter
265  if (!filter_cb(flag)) return;
266 
267  std::string flag_filename = flag.Filename();
268 
269  matching_flags[std::string(flags_internal::Package(flag_filename))]
270  [flag_filename]
271  .push_back(&flag);
272  });
273 
274  absl::string_view package_separator; // controls blank lines between packages
275  absl::string_view file_separator; // controls blank lines between files
276  for (auto& package : matching_flags) {
278  out << package_separator;
279  package_separator = "\n\n";
280  }
281 
282  file_separator = "";
283  for (auto& flags_in_file : package.second) {
285  out << file_separator << " Flags from " << flags_in_file.first
286  << ":\n";
287  file_separator = "\n";
288  }
289 
290  std::sort(std::begin(flags_in_file.second),
291  std::end(flags_in_file.second),
292  [](const CommandLineFlag* lhs, const CommandLineFlag* rhs) {
293  return lhs->Name() < rhs->Name();
294  });
295 
296  for (const auto* flag : flags_in_file.second) {
298  }
299  }
300  }
301 
303  FlagHelpPrettyPrinter printer(kHrfMaxLineLength, 0, 0, out);
304 
305  if (filter_cb && matching_flags.empty()) {
306  printer.Write("No flags matched.\n", true);
307  }
308  printer.EndLine();
309  printer.Write(
310  "Try --helpfull to get a list of all flags or --help=substring "
311  "shows help for flags which include specified substring in either "
312  "in the name, or description or path.\n",
313  true);
314  } else {
315  // The end of the document.
316  out << "</AllFlags>\n";
317  }
318 }
319 
320 void FlagsHelpImpl(std::ostream& out,
321  flags_internal::FlagKindFilter filename_filter_cb,
322  HelpFormat format, absl::string_view program_usage_message) {
323  FlagsHelpImpl(
324  out,
325  [&](const absl::CommandLineFlag& flag) {
326  return filename_filter_cb && filename_filter_cb(flag.Filename());
327  },
328  format, program_usage_message);
329 }
330 
331 } // namespace
332 
333 // --------------------------------------------------------------------
334 // Produces the help message describing specific flag.
335 void FlagHelp(std::ostream& out, const CommandLineFlag& flag,
336  HelpFormat format) {
338  flags_internal::FlagHelpHumanReadable(flag, out);
339 }
340 
341 // --------------------------------------------------------------------
342 // Produces the help messages for all flags matching the filename filter.
343 // If filter is empty produces help messages for all flags.
344 void FlagsHelp(std::ostream& out, absl::string_view filter, HelpFormat format,
345  absl::string_view program_usage_message) {
347  return filter.empty() || filename.find(filter) != absl::string_view::npos;
348  };
349  flags_internal::FlagsHelpImpl(out, filter_cb, format, program_usage_message);
350 }
351 
352 // --------------------------------------------------------------------
353 // Checks all the 'usage' command line flags to see if any have been set.
354 // If so, handles them appropriately.
355 int HandleUsageFlags(std::ostream& out,
356  absl::string_view program_usage_message) {
357  switch (GetFlagsHelpMode()) {
358  case HelpMode::kNone:
359  break;
361  flags_internal::FlagsHelpImpl(
362  out, flags_internal::GetUsageConfig().contains_help_flags,
363  GetFlagsHelpFormat(), program_usage_message);
364  return 1;
365 
366  case HelpMode::kShort:
367  flags_internal::FlagsHelpImpl(
368  out, flags_internal::GetUsageConfig().contains_helpshort_flags,
369  GetFlagsHelpFormat(), program_usage_message);
370  return 1;
371 
372  case HelpMode::kFull:
374  program_usage_message);
375  return 1;
376 
377  case HelpMode::kPackage:
378  flags_internal::FlagsHelpImpl(
379  out, flags_internal::GetUsageConfig().contains_helppackage_flags,
380  GetFlagsHelpFormat(), program_usage_message);
381 
382  return 1;
383 
384  case HelpMode::kMatch: {
386  if (substr.empty()) {
387  // show all options
389  program_usage_message);
390  } else {
391  auto filter_cb = [&substr](const absl::CommandLineFlag& flag) {
392  if (absl::StrContains(flag.Name(), substr)) return true;
393  if (absl::StrContains(flag.Filename(), substr)) return true;
394  if (absl::StrContains(flag.Help(), substr)) return true;
395 
396  return false;
397  };
398  flags_internal::FlagsHelpImpl(
399  out, filter_cb, HelpFormat::kHumanReadable, program_usage_message);
400  }
401 
402  return 1;
403  }
404  case HelpMode::kVersion:
405  if (flags_internal::GetUsageConfig().version_string)
407  // Unlike help, we may be asking for version in a script, so return 0
408  return 0;
409 
411  return 0;
412  }
413 
414  return -1;
415 }
416 
417 // --------------------------------------------------------------------
418 // Globals representing usage reporting flags
419 
420 namespace {
421 
422 ABSL_CONST_INIT absl::Mutex help_attributes_guard(absl::kConstInit);
423 ABSL_CONST_INIT std::string* match_substr
424  ABSL_GUARDED_BY(help_attributes_guard) = nullptr;
425 ABSL_CONST_INIT HelpMode help_mode ABSL_GUARDED_BY(help_attributes_guard) =
427 ABSL_CONST_INIT HelpFormat help_format ABSL_GUARDED_BY(help_attributes_guard) =
429 
430 } // namespace
431 
433  absl::MutexLock l(&help_attributes_guard);
434  if (match_substr == nullptr) return "";
435  return *match_substr;
436 }
437 
439  absl::MutexLock l(&help_attributes_guard);
440  if (match_substr == nullptr) match_substr = new std::string;
441  match_substr->assign(substr.data(), substr.size());
442 }
443 
445  absl::MutexLock l(&help_attributes_guard);
446  return help_mode;
447 }
448 
450  absl::MutexLock l(&help_attributes_guard);
451  help_mode = mode;
452 }
453 
455  absl::MutexLock l(&help_attributes_guard);
456  return help_format;
457 }
458 
460  absl::MutexLock l(&help_attributes_guard);
461  help_format = format;
462 }
463 
464 // Deduces usage flags from the input argument in a form --name=value or
465 // --name. argument is already split into name and value before we call this
466 // function.
468  if (absl::ConsumePrefix(&name, "help")) {
469  if (name == "") {
470  if (value.empty()) {
472  } else {
475  }
476  return true;
477  }
478 
479  if (name == "match") {
482  return true;
483  }
484 
485  if (name == "on") {
488  return true;
489  }
490 
491  if (name == "full") {
493  return true;
494  }
495 
496  if (name == "short") {
498  return true;
499  }
500 
501  if (name == "package") {
503  return true;
504  }
505 
506  return false;
507  }
508 
509  if (name == "version") {
511  return true;
512  }
513 
514  if (name == "only_check_args") {
516  return true;
517  }
518 
519  return false;
520 }
521 
522 } // namespace flags_internal
524 } // namespace absl
absl::StrSplit
strings_internal::Splitter< typename strings_internal::SelectDelimiter< Delimiter >::type, AllowEmpty, absl::string_view > StrSplit(strings_internal::ConvertibleToStringView text, Delimiter d)
Definition: abseil-cpp/absl/strings/str_split.h:499
xds_interop_client.str
str
Definition: xds_interop_client.py:487
absl::flags_internal::HelpMode::kShort
@ kShort
flag
uint32_t flag
Definition: ssl_versions.cc:162
absl::flags_internal::HelpFormat
HelpFormat
Definition: abseil-cpp/absl/flags/internal/usage.h:35
absl::flags_internal::HelpMode::kMatch
@ kMatch
filename
const char * filename
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:135
line_len_
size_t line_len_
Definition: abseil-cpp/absl/flags/internal/usage.cc:188
FLAGS_helpfull
bool FLAGS_helpfull
Definition: abseil-cpp/absl/flags/internal/usage.cc:42
http2_test_server.format
format
Definition: http2_test_server.py:118
absl::flags_internal::HelpMode
HelpMode
Definition: abseil-cpp/absl/flags/internal/usage.h:72
absl::flags_internal::ShortProgramInvocationName
std::string ShortProgramInvocationName()
Definition: abseil-cpp/absl/flags/internal/program_name.cc:42
bool
bool
Definition: setup_once.h:312
ABSL_CONST_INIT
#define ABSL_CONST_INIT
Definition: abseil-cpp/absl/base/attributes.h:716
absl::StrCat
std::string StrCat(const AlphaNum &a, const AlphaNum &b)
Definition: abseil-cpp/absl/strings/str_cat.cc:98
begin
char * begin
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1007
FLAGS_help
bool FLAGS_help
Definition: abseil-cpp/absl/flags/internal/usage.cc:41
FLAGS_helpshort
bool FLAGS_helpshort
Definition: abseil-cpp/absl/flags/internal/usage.cc:43
absl::flags_internal::SetFlagsHelpMatchSubstr
void SetFlagsHelpMatchSubstr(absl::string_view substr)
Definition: abseil-cpp/absl/flags/internal/usage.cc:438
absl::operator<<
ABSL_NAMESPACE_BEGIN std::ostream & operator<<(std::ostream &os, absl::LogSeverity s)
Definition: abseil-cpp/absl/base/log_severity.cc:24
absl::Mutex
Definition: abseil-cpp/absl/synchronization/mutex.h:131
absl::string_view
Definition: abseil-cpp/absl/strings/string_view.h:167
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
absl::flags_internal::HandleUsageFlags
int HandleUsageFlags(std::ostream &out, absl::string_view program_usage_message)
Definition: abseil-cpp/absl/flags/internal/usage.cc:355
absl::flags_internal::SetFlagsHelpMode
void SetFlagsHelpMode(HelpMode mode)
Definition: abseil-cpp/absl/flags/internal/usage.cc:449
absl::flags_internal::FlagsHelp
void FlagsHelp(std::ostream &out, absl::string_view filter, HelpFormat format, absl::string_view program_usage_message)
Definition: abseil-cpp/absl/flags/internal/usage.cc:344
absl::flags_internal::SetFlagsHelpFormat
void SetFlagsHelpFormat(HelpFormat format)
Definition: abseil-cpp/absl/flags/internal/usage.cc:459
absl::flags_internal::kStrippedFlagHelp
const char kStrippedFlagHelp[]
Definition: abseil-cpp/absl/flags/internal/flag.cc:51
mode
const char int mode
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:135
setup.name
name
Definition: setup.py:542
absl::kConstInit
@ kConstInit
Definition: abseil-cpp/absl/base/const_init.h:70
absl::flags_internal::HelpMode::kNone
@ kNone
absl::CommandLineFlag
Definition: abseil-cpp/absl/flags/commandlineflag.h:62
ABSL_NAMESPACE_END
#define ABSL_NAMESPACE_END
Definition: third_party/abseil-cpp/absl/base/config.h:171
map
zval * map
Definition: php/ext/google/protobuf/encode_decode.c:480
max_line_len_
const size_t max_line_len_
Definition: abseil-cpp/absl/flags/internal/usage.cc:185
absl::flags_internal::DeduceUsageFlags
bool DeduceUsageFlags(absl::string_view name, absl::string_view value)
Definition: abseil-cpp/absl/flags/internal/usage.cc:467
min_line_len_
const size_t min_line_len_
Definition: abseil-cpp/absl/flags/internal/usage.cc:186
absl::MutexLock
Definition: abseil-cpp/absl/synchronization/mutex.h:525
ABSL_NAMESPACE_BEGIN
#define ABSL_NAMESPACE_BEGIN
Definition: third_party/abseil-cpp/absl/base/config.h:170
absl::flags_internal::FlagKindFilter
std::function< bool(absl::string_view)> FlagKindFilter
Definition: abseil-cpp/absl/flags/usage_config.h:61
absl::SkipEmpty
Definition: abseil-cpp/absl/strings/str_split.h:347
absl::flags_internal::ABSL_GUARDED_BY
static ABSL_CONST_INIT std::string *program_name ABSL_GUARDED_BY(program_name_guard)
absl::flags_internal::HelpMode::kOnlyCheckArgs
@ kOnlyCheckArgs
end
char * end
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1008
absl::flags_internal::FlagHelp
void FlagHelp(std::ostream &out, const CommandLineFlag &flag, HelpFormat format)
Definition: abseil-cpp/absl/flags/internal/usage.cc:335
FLAGS_helpmatch
bool FLAGS_helpmatch
Definition: abseil-cpp/absl/flags/internal/usage.cc:48
absl::string_view::size
constexpr size_type size() const noexcept
Definition: abseil-cpp/absl/strings/string_view.h:277
absl::FlagsUsageConfig::version_string
std::function< std::string()> version_string
Definition: abseil-cpp/absl/flags/usage_config.h:95
tag
static void * tag(intptr_t t)
Definition: bad_client.cc:318
absl::flags_internal::HelpMode::kImportant
@ kImportant
absl::flags_internal::ForEachFlag
void ForEachFlag(std::function< void(CommandLineFlag &)> visitor)
Definition: abseil-cpp/absl/flags/reflection.cc:178
first_line_
bool first_line_
Definition: abseil-cpp/absl/flags/internal/usage.cc:189
FLAGS_helppackage
bool FLAGS_helppackage
Definition: abseil-cpp/absl/flags/internal/usage.cc:44
absl::StrContains
ABSL_NAMESPACE_BEGIN bool StrContains(absl::string_view haystack, absl::string_view needle) noexcept
Definition: third_party/abseil-cpp/absl/strings/match.h:46
tag_
absl::string_view tag_
Definition: abseil-cpp/absl/flags/internal/usage.cc:101
absl::flags_internal::Package
absl::string_view Package(absl::string_view filename)
Definition: abseil-cpp/absl/flags/internal/path_util.h:50
absl::flags_internal::HelpMode::kPackage
@ kPackage
FLAGS_version
bool FLAGS_version
Definition: abseil-cpp/absl/flags/internal/usage.cc:45
wrapped_line_indent_
const size_t wrapped_line_indent_
Definition: abseil-cpp/absl/flags/internal/usage.cc:187
stdint.h
absl::flags_internal::GetFlagsHelpMode
HelpMode GetFlagsHelpMode()
Definition: abseil-cpp/absl/flags/internal/usage.cc:444
value
const char * value
Definition: hpack_parser_table.cc:165
absl::flags_internal::GetFlagsHelpMatchSubstr
std::string GetFlagsHelpMatchSubstr()
Definition: abseil-cpp/absl/flags/internal/usage.cc:432
absl::flags_internal::HelpMode::kVersion
@ kVersion
testing::internal::posix::Write
int Write(int fd, const void *buf, unsigned int count)
Definition: bloaty/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:2047
absl::flags_internal::GetFlagsHelpFormat
HelpFormat GetFlagsHelpFormat()
Definition: abseil-cpp/absl/flags/internal/usage.cc:454
txt_
absl::string_view txt_
Definition: abseil-cpp/absl/flags/internal/usage.cc:102
FLAGS_only_check_args
bool FLAGS_only_check_args
Definition: abseil-cpp/absl/flags/internal/usage.cc:46
FLAGS_helpon
bool FLAGS_helpon
Definition: abseil-cpp/absl/flags/internal/usage.cc:47
out_
std::ostream & out_
Definition: abseil-cpp/absl/flags/internal/usage.cc:184
absl::flags_internal::GetUsageConfig
FlagsUsageConfig GetUsageConfig()
Definition: abseil-cpp/absl/flags/usage_config.cc:113
regen-readme.line
line
Definition: regen-readme.py:30
absl::flags_internal::HelpFormat::kHumanReadable
@ kHumanReadable
absl::flags_internal::HelpMode::kFull
@ kFull
absl::string_view::empty
constexpr bool empty() const noexcept
Definition: abseil-cpp/absl/strings/string_view.h:292
absl
Definition: abseil-cpp/absl/algorithm/algorithm.h:31
absl::out
char * out
Definition: abseil-cpp/absl/synchronization/mutex.h:1048
absl::string_view::npos
static constexpr size_type npos
Definition: abseil-cpp/absl/strings/string_view.h:182
function
std::function< bool(GrpcTool *, int, const char **, const CliCredentials &, GrpcToolOutputCallback)> function
Definition: grpc_tool.cc:250
absl::string_view::data
constexpr const_pointer data() const noexcept
Definition: abseil-cpp/absl/strings/string_view.h:336
absl::ByAnyChar
Definition: abseil-cpp/absl/strings/str_split.h:182
if
if(p->owned &&p->wrapped !=NULL)
Definition: call.c:42
absl::ConsumePrefix
ABSL_NAMESPACE_BEGIN bool ConsumePrefix(absl::string_view *str, absl::string_view expected)
Definition: abseil-cpp/absl/strings/strip.h:46


grpc
Author(s):
autogenerated on Fri May 16 2025 03:00:48