blob: 528f0995605e3bf18f5923444fffcb622bf7f9e9 [file] [log] [blame]
Karl Wiberg881f1682018-03-08 15:03:23 +01001/*
2 * Copyright 2018 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "rtc_base/strings/string_builder.h"
12
13namespace rtc {
14
15SimpleStringBuilder::SimpleStringBuilder(rtc::ArrayView<char> buffer)
16 : buffer_(buffer) {
17 buffer_[0] = '\0';
18 RTC_DCHECK(IsConsistent());
19}
20
Karl Wibergabff7dd2018-03-09 15:26:24 +010021SimpleStringBuilder& SimpleStringBuilder::operator<<(const char* str) {
22 return Append(str);
23}
24
25SimpleStringBuilder& SimpleStringBuilder::operator<<(char ch) {
26 return Append(&ch, 1);
27}
28
29SimpleStringBuilder& SimpleStringBuilder::operator<<(const std::string& str) {
30 return Append(str.c_str(), str.length());
31}
32
33// Numeric conversion routines.
34//
35// We use std::[v]snprintf instead of std::to_string because:
36// * std::to_string relies on the current locale for formatting purposes,
37// and therefore concurrent calls to std::to_string from multiple threads
38// may result in partial serialization of calls
39// * snprintf allows us to print the number directly into our buffer.
40// * avoid allocating a std::string (potential heap alloc).
41// TODO(tommi): Switch to std::to_chars in C++17.
42
43SimpleStringBuilder& SimpleStringBuilder::operator<<(int i) {
44 return AppendFormat("%d", i);
45}
46
47SimpleStringBuilder& SimpleStringBuilder::operator<<(unsigned i) {
48 return AppendFormat("%u", i);
49}
50
51SimpleStringBuilder& SimpleStringBuilder::operator<<(long i) { // NOLINT
52 return AppendFormat("%ld", i);
53}
54
55SimpleStringBuilder& SimpleStringBuilder::operator<<(long long i) { // NOLINT
56 return AppendFormat("%lld", i);
57}
58
59SimpleStringBuilder& SimpleStringBuilder::operator<<(
60 unsigned long i) { // NOLINT
61 return AppendFormat("%lu", i);
62}
63
64SimpleStringBuilder& SimpleStringBuilder::operator<<(
65 unsigned long long i) { // NOLINT
66 return AppendFormat("%llu", i);
67}
68
69SimpleStringBuilder& SimpleStringBuilder::operator<<(float f) {
70 return AppendFormat("%f", f);
71}
72
73SimpleStringBuilder& SimpleStringBuilder::operator<<(double f) {
74 return AppendFormat("%f", f);
75}
76
77SimpleStringBuilder& SimpleStringBuilder::operator<<(long double f) {
78 return AppendFormat("%Lf", f);
79}
80
81SimpleStringBuilder& SimpleStringBuilder::AppendFormat(const char* fmt, ...) {
82 va_list args;
83 va_start(args, fmt);
84 const int len =
85 std::vsnprintf(&buffer_[size_], buffer_.size() - size_, fmt, args);
86 if (len >= 0) {
87 const size_t chars_added = rtc::SafeMin(len, buffer_.size() - 1 - size_);
88 size_ += chars_added;
89 RTC_DCHECK_EQ(len, chars_added) << "Buffer size was insufficient";
90 } else {
91 // This should never happen, but we're paranoid, so re-write the
92 // terminator in case vsnprintf() overwrote it.
93 RTC_NOTREACHED();
94 buffer_[size_] = '\0';
95 }
96 va_end(args);
97 RTC_DCHECK(IsConsistent());
98 return *this;
99}
100
101SimpleStringBuilder& SimpleStringBuilder::Append(const char* str,
102 size_t length) {
103 const size_t chars_added =
104 rtc::strcpyn(&buffer_[size_], buffer_.size() - size_, str, length);
105 size_ += chars_added;
106 RTC_DCHECK_EQ(chars_added, length == SIZE_UNKNOWN ? std::strlen(str) : length)
107 << "Buffer size was insufficient";
108 RTC_DCHECK(IsConsistent());
109 return *this;
110}
111
Karl Wiberg881f1682018-03-08 15:03:23 +0100112} // namespace rtc