diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn index 60dda76f6d..a61ede4ac9 100644 --- a/rtc_base/BUILD.gn +++ b/rtc_base/BUILD.gn @@ -390,6 +390,8 @@ rtc_library("stringutils") { "string_utils.h", "strings/string_builder.cc", "strings/string_builder.h", + "strings/string_format.cc", + "strings/string_format.h", ] deps = [ ":checks", @@ -819,12 +821,12 @@ rtc_library("rtc_base") { "net_helpers.cc", "net_helpers.h", "network.cc", - "network_route.cc", "network.h", "network_constants.cc", "network_constants.h", "network_monitor.cc", "network_monitor.h", + "network_route.cc", "network_route.h", "null_socket_server.cc", "null_socket_server.h", @@ -1171,6 +1173,7 @@ if (rtc_include_tests) { "string_utils_unittest.cc", "stringize_macros_unittest.cc", "strings/string_builder_unittest.cc", + "strings/string_format_unittest.cc", "swap_queue_unittest.cc", "thread_annotations_unittest.cc", "thread_checker_unittest.cc", @@ -1307,8 +1310,8 @@ if (rtc_include_tests) { "memory_usage_unittest.cc", "message_digest_unittest.cc", "nat_unittest.cc", - "network_unittest.cc", "network_route_unittest.cc", + "network_unittest.cc", "proxy_unittest.cc", "rolling_accumulator_unittest.cc", "rtc_certificate_generator_unittest.cc", diff --git a/rtc_base/strings/string_format.cc b/rtc_base/strings/string_format.cc new file mode 100644 index 0000000000..f92be339ce --- /dev/null +++ b/rtc_base/strings/string_format.cc @@ -0,0 +1,41 @@ +/* + * Copyright 2020 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include + +#include "rtc_base/strings/string_format.h" + +#include "rtc_base/checks.h" + +namespace rtc { + +namespace { + +// This is an arbitrary limitation that can be changed if necessary, or removed +// if someone has the time and inclination to replicate the fancy logic from +// Chromium's base::StringPrinf(). +constexpr int kMaxSize = 512; + +} // namespace + +std::string StringFormat(const char* fmt, ...) { + char buffer[kMaxSize]; + va_list args; + va_start(args, fmt); + int result = vsnprintf(buffer, kMaxSize, fmt, args); + va_end(args); + RTC_DCHECK_GE(result, 0) << "ERROR: vsnprintf() failed with error " << result; + RTC_DCHECK_LT(result, kMaxSize) + << "WARNING: string was truncated from " << result << " to " + << (kMaxSize - 1) << " characters"; + return std::string(buffer); +} + +} // namespace rtc diff --git a/rtc_base/strings/string_format.h b/rtc_base/strings/string_format.h new file mode 100644 index 0000000000..13124d2925 --- /dev/null +++ b/rtc_base/strings/string_format.h @@ -0,0 +1,31 @@ +/* + * Copyright 2020 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef RTC_BASE_STRINGS_STRING_FORMAT_H_ +#define RTC_BASE_STRINGS_STRING_FORMAT_H_ + +#include + +namespace rtc { + +#if defined(__GNUC__) +#define RTC_PRINTF_FORMAT(format_param, dots_param) \ + __attribute__((format(printf, format_param, dots_param))) +#else +#define RTC_PRINTF_FORMAT(format_param, dots_param) +#endif + +// Return a C++ string given printf-like input. +// Based on base::StringPrintf() in Chrome but without its fancy dynamic memory +// allocation for any size of the input buffer. +std::string StringFormat(const char* fmt, ...) RTC_PRINTF_FORMAT(1, 2); +} // namespace rtc + +#endif // RTC_BASE_STRINGS_STRING_FORMAT_H_ diff --git a/rtc_base/strings/string_format_unittest.cc b/rtc_base/strings/string_format_unittest.cc new file mode 100644 index 0000000000..d0e8eb2d71 --- /dev/null +++ b/rtc_base/strings/string_format_unittest.cc @@ -0,0 +1,35 @@ +/* + * Copyright 2020 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "rtc_base/strings/string_format.h" + +#include "rtc_base/checks.h" +#include "test/gtest.h" + +namespace rtc { + +TEST(StringFormatTest, Empty) { + EXPECT_EQ("", StringFormat("%s", "")); +} + +TEST(StringFormatTest, Misc) { + EXPECT_EQ("123hello w", StringFormat("%3d%2s %1c", 123, "hello", 'w')); + EXPECT_EQ("3 = three", StringFormat("%d = %s", 1 + 2, "three")); +} + +TEST(StringFormatTest, MaxSizeShouldWork) { + const int kSrcLen = 512; + char str[kSrcLen]; + std::fill_n(str, kSrcLen, 'A'); + str[kSrcLen - 1] = 0; + EXPECT_EQ(str, StringFormat("%s", str)); +} + +} // namespace rtc