Coverage Report

Created: 2024-11-22 12:31

/root/doris/be/src/gutil/strings/substitute.h
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2008 Google Inc.  All rights reserved.
2
3
#pragma once
4
5
#include <string.h>
6
#include <string>
7
8
using std::string;
9
10
#include "gutil/strings/numbers.h"
11
#include "gutil/strings/stringpiece.h"
12
#include "gutil/stringprintf.h"
13
14
namespace strings {
15
16
// ----------------------------------------------------------------------
17
// strings::Substitute()
18
// strings::SubstituteAndAppend()
19
//   Kind of like StringPrintf, but different.
20
//
21
//   Example:
22
//     string GetMessage(string first_name, string last_name, int age) {
23
//       return strings::Substitute("My name is $0 $1 and I am $2 years old.",
24
//                                  first_name, last_name, age);
25
//     }
26
//
27
//   Differences from StringPrintf:
28
//   * The format string does not identify the types of arguments.
29
//     Instead, the magic of C++ deals with this for us.  See below
30
//     for a list of accepted types.
31
//   * Substitutions in the format string are identified by a '$'
32
//     followed by a digit.  So, you can use arguments out-of-order and
33
//     use the same argument multiple times.
34
//   * '$$' in the format string means output a literal '$' character.
35
//   * It's much faster than StringPrintf.
36
//
37
//   Supported types:
38
//   * StringPiece (const char*, const string&) (NULL is equivalent to "")
39
//     * Note that this means you do not have to add .c_str() to all of
40
//       your strings.  In fact, you shouldn't; it will be slower.
41
//   * int32, int64, uint32, uint64
42
//   * float, double
43
//   * bool:  Printed as "true" or "false".
44
//   * pointer types other than char*: Printed as "0x<lower case hex string>",
45
//             except that NULL is printed as "NULL".
46
//
47
//   If not enough arguments are supplied, a LOG(DFATAL) will be issued and
48
//   the empty string will be returned. If too many arguments are supplied,
49
//   just the first ones will be used (no warning).
50
//
51
//   SubstituteAndAppend() is like Substitute() but appends the result to
52
//   *output.  Example:
53
//
54
//     string str;
55
//     strings::SubstituteAndAppend(&str,
56
//                                  "My name is $0 $1 and I am $2 years old.",
57
//                                  first_name, last_name, age);
58
//
59
//   Substitute() is significantly faster than StringPrintf().  For very
60
//   large strings, it may be orders of magnitude faster.
61
// ----------------------------------------------------------------------
62
63
namespace internal { // Implementation details.
64
65
// This class has implicit constructors.
66
// Style guide exception granted:
67
// http://goto/style-guide-exception-20978288
68
69
class SubstituteArg {
70
public:
71
    // We must explicitly overload char* so that the compiler doesn't try to
72
    // cast it to bool to construct a DynamicSubstituteArg.  Might as well
73
    // overload const string& as well, since this allows us to avoid a temporary
74
    // object.
75
    inline SubstituteArg(const char* value) // NOLINT(runtime/explicit)
76
0
            : text_(value), size_(value == NULL ? 0 : strlen(text_)) {}
77
    inline SubstituteArg(const string& value) // NOLINT(runtime/explicit)
78
3.85k
            : text_(value.data()), size_(value.size()) {}
79
    inline SubstituteArg(const StringPiece& value) // NOLINT(runtime/explicit)
80
0
            : text_(value.data()), size_(value.size()) {}
81
82
    // Primitives
83
    // We don't overload for signed and unsigned char because if people are
84
    // explicitly declaring their chars as signed or unsigned then they are
85
    // probably actually using them as 8-bit integers and would probably
86
    // prefer an integer representation.  But, we don't really know.  So, we
87
    // make the caller decide what to do.
88
    inline SubstituteArg(char value) // NOLINT(runtime/explicit)
89
0
            : text_(scratch_), size_(1) {
90
0
        scratch_[0] = value;
91
0
    }
92
    inline SubstituteArg(short value) // NOLINT(runtime/explicit)
93
0
            : text_(scratch_), size_(FastInt32ToBufferLeft(value, scratch_) - scratch_) {}
94
    inline SubstituteArg(unsigned short value) // NOLINT(runtime/explicit)
95
0
            : text_(scratch_), size_(FastUInt32ToBufferLeft(value, scratch_) - scratch_) {}
96
    inline SubstituteArg(int value) // NOLINT(runtime/explicit)
97
332k
            : text_(scratch_), size_(FastInt32ToBufferLeft(value, scratch_) - scratch_) {}
98
    inline SubstituteArg(unsigned int value) // NOLINT(runtime/explicit)
99
0
            : text_(scratch_), size_(FastUInt32ToBufferLeft(value, scratch_) - scratch_) {}
100
    inline SubstituteArg(long value) // NOLINT(runtime/explicit)
101
            : text_(scratch_),
102
              size_((sizeof(value) == 4 ? FastInt32ToBufferLeft(value, scratch_)
103
                                        : FastInt64ToBufferLeft(value, scratch_)) -
104
2.45k
                    scratch_) {}
105
    inline SubstituteArg(unsigned long value) // NOLINT(runtime/explicit)
106
            : text_(scratch_),
107
              size_((sizeof(value) == 4 ? FastUInt32ToBufferLeft(value, scratch_)
108
                                        : FastUInt64ToBufferLeft(value, scratch_)) -
109
0
                    scratch_) {}
110
    inline SubstituteArg(long long value) // NOLINT(runtime/explicit)
111
0
            : text_(scratch_), size_(FastInt64ToBufferLeft(value, scratch_) - scratch_) {}
112
    inline SubstituteArg(unsigned long long value) // NOLINT(runtime/explicit)
113
0
            : text_(scratch_), size_(FastUInt64ToBufferLeft(value, scratch_) - scratch_) {}
114
    inline SubstituteArg(float value) // NOLINT(runtime/explicit)
115
0
            : text_(FloatToBuffer(value, scratch_)), size_(strlen(text_)) {}
116
    inline SubstituteArg(double value) // NOLINT(runtime/explicit)
117
0
            : text_(DoubleToBuffer(value, scratch_)), size_(strlen(text_)) {}
118
    inline SubstituteArg(bool value) // NOLINT(runtime/explicit)
119
0
            : text_(value ? "true" : "false"), size_(strlen(text_)) {}
120
    // void* values, with the exception of char*, are printed as
121
    // StringPrintf with format "%p" would ("0x<hex value>"), with the
122
    // exception of NULL, which is printed as "NULL".
123
    SubstituteArg(const void* value); // NOLINT(runtime/explicit)
124
125
339k
    inline const char* data() const { return text_; }
126
1.35M
    inline int size() const { return size_; }
127
128
    // Indicates that no argument was given.
129
    static const SubstituteArg NoArg;
130
131
private:
132
1
    inline SubstituteArg() : text_(NULL), size_(-1) {}
133
134
    const char* text_ = nullptr;
135
    int size_;
136
    char scratch_[kFastToBufferSize];
137
};
138
139
// Return the length of the resulting string after performing the given
140
// substitution.
141
int SubstitutedSize(StringPiece format, const SubstituteArg* const* args_array);
142
143
// Perform the given substitution into 'target'. 'target' must have
144
// space for the result -- use SubstitutedSize() to determine how many
145
// bytes are required.  Returns a pointer to the next byte following
146
// the result in 'target'.
147
char* SubstituteToBuffer(StringPiece format, const SubstituteArg* const* args_array, char* target);
148
149
} // namespace internal
150
151
void SubstituteAndAppend(string* output, StringPiece format,
152
                         const internal::SubstituteArg& arg0 = internal::SubstituteArg::NoArg,
153
                         const internal::SubstituteArg& arg1 = internal::SubstituteArg::NoArg,
154
                         const internal::SubstituteArg& arg2 = internal::SubstituteArg::NoArg,
155
                         const internal::SubstituteArg& arg3 = internal::SubstituteArg::NoArg,
156
                         const internal::SubstituteArg& arg4 = internal::SubstituteArg::NoArg,
157
                         const internal::SubstituteArg& arg5 = internal::SubstituteArg::NoArg,
158
                         const internal::SubstituteArg& arg6 = internal::SubstituteArg::NoArg,
159
                         const internal::SubstituteArg& arg7 = internal::SubstituteArg::NoArg,
160
                         const internal::SubstituteArg& arg8 = internal::SubstituteArg::NoArg,
161
                         const internal::SubstituteArg& arg9 = internal::SubstituteArg::NoArg);
162
163
inline string Substitute(StringPiece format,
164
                         const internal::SubstituteArg& arg0 = internal::SubstituteArg::NoArg,
165
                         const internal::SubstituteArg& arg1 = internal::SubstituteArg::NoArg,
166
                         const internal::SubstituteArg& arg2 = internal::SubstituteArg::NoArg,
167
                         const internal::SubstituteArg& arg3 = internal::SubstituteArg::NoArg,
168
                         const internal::SubstituteArg& arg4 = internal::SubstituteArg::NoArg,
169
                         const internal::SubstituteArg& arg5 = internal::SubstituteArg::NoArg,
170
                         const internal::SubstituteArg& arg6 = internal::SubstituteArg::NoArg,
171
                         const internal::SubstituteArg& arg7 = internal::SubstituteArg::NoArg,
172
                         const internal::SubstituteArg& arg8 = internal::SubstituteArg::NoArg,
173
114k
                         const internal::SubstituteArg& arg9 = internal::SubstituteArg::NoArg) {
174
114k
    string result;
175
114k
    SubstituteAndAppend(&result, format, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
176
114k
                        arg9);
177
114k
    return result;
178
114k
}
179
180
} // namespace strings