1 | // Protocol Buffers - Google's data interchange format |
2 | // Copyright 2008 Google Inc. All rights reserved. |
3 | // https://developers.google.com/protocol-buffers/ |
4 | // |
5 | // Redistribution and use in source and binary forms, with or without |
6 | // modification, are permitted provided that the following conditions are |
7 | // met: |
8 | // |
9 | // * Redistributions of source code must retain the above copyright |
10 | // notice, this list of conditions and the following disclaimer. |
11 | // * Redistributions in binary form must reproduce the above |
12 | // copyright notice, this list of conditions and the following disclaimer |
13 | // in the documentation and/or other materials provided with the |
14 | // distribution. |
15 | // * Neither the name of Google Inc. nor the names of its |
16 | // contributors may be used to endorse or promote products derived from |
17 | // this software without specific prior written permission. |
18 | // |
19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
30 | |
31 | // Author: kenton@google.com (Kenton Varda) |
32 | // from google3/strings/substitute.h |
33 | |
34 | #include <google/protobuf/stubs/common.h> |
35 | #include <google/protobuf/stubs/stringpiece.h> |
36 | #include <google/protobuf/stubs/strutil.h> |
37 | |
38 | #include <string> |
39 | |
40 | #ifndef GOOGLE_PROTOBUF_STUBS_SUBSTITUTE_H_ |
41 | #define GOOGLE_PROTOBUF_STUBS_SUBSTITUTE_H_ |
42 | |
43 | #include <google/protobuf/port_def.inc> |
44 | |
45 | namespace google { |
46 | namespace protobuf { |
47 | namespace strings { |
48 | |
49 | // ---------------------------------------------------------------------- |
50 | // strings::Substitute() |
51 | // strings::SubstituteAndAppend() |
52 | // Kind of like StringPrintf, but different. |
53 | // |
54 | // Example: |
55 | // string GetMessage(string first_name, string last_name, int age) { |
56 | // return strings::Substitute("My name is $0 $1 and I am $2 years old.", |
57 | // first_name, last_name, age); |
58 | // } |
59 | // |
60 | // Differences from StringPrintf: |
61 | // * The format string does not identify the types of arguments. |
62 | // Instead, the magic of C++ deals with this for us. See below |
63 | // for a list of accepted types. |
64 | // * Substitutions in the format string are identified by a '$' |
65 | // followed by a digit. So, you can use arguments out-of-order and |
66 | // use the same argument multiple times. |
67 | // * It's much faster than StringPrintf. |
68 | // |
69 | // Supported types: |
70 | // * Strings (const char*, const string&) |
71 | // * Note that this means you do not have to add .c_str() to all of |
72 | // your strings. In fact, you shouldn't; it will be slower. |
73 | // * int32, int64, uint32, uint64: Formatted using SimpleItoa(). |
74 | // * float, double: Formatted using SimpleFtoa() and SimpleDtoa(). |
75 | // * bool: Printed as "true" or "false". |
76 | // |
77 | // SubstituteAndAppend() is like Substitute() but appends the result to |
78 | // *output. Example: |
79 | // |
80 | // string str; |
81 | // strings::SubstituteAndAppend(&str, |
82 | // "My name is $0 $1 and I am $2 years old.", |
83 | // first_name, last_name, age); |
84 | // |
85 | // Substitute() is significantly faster than StringPrintf(). For very |
86 | // large strings, it may be orders of magnitude faster. |
87 | // ---------------------------------------------------------------------- |
88 | |
89 | namespace internal { // Implementation details. |
90 | |
91 | class SubstituteArg { |
92 | public: |
93 | inline SubstituteArg(const char* value) |
94 | : text_(value), size_(strlen(s: text_)) {} |
95 | inline SubstituteArg(const std::string& value) |
96 | : text_(value.data()), size_(value.size()) {} |
97 | inline SubstituteArg(const StringPiece value) |
98 | : text_(value.data()), size_(value.size()) {} |
99 | |
100 | // Indicates that no argument was given. |
101 | inline explicit SubstituteArg() |
102 | : text_(nullptr), size_(-1) {} |
103 | |
104 | // Primitives |
105 | // We don't overload for signed and unsigned char because if people are |
106 | // explicitly declaring their chars as signed or unsigned then they are |
107 | // probably actually using them as 8-bit integers and would probably |
108 | // prefer an integer representation. But, we don't really know. So, we |
109 | // make the caller decide what to do. |
110 | inline SubstituteArg(char value) |
111 | : text_(scratch_), size_(1) { scratch_[0] = value; } |
112 | inline SubstituteArg(short value) |
113 | : text_(FastInt32ToBuffer(i: value, buffer: scratch_)), size_(strlen(s: text_)) {} |
114 | inline SubstituteArg(unsigned short value) |
115 | : text_(FastUInt32ToBuffer(i: value, buffer: scratch_)), size_(strlen(s: text_)) {} |
116 | inline SubstituteArg(int value) |
117 | : text_(FastInt32ToBuffer(i: value, buffer: scratch_)), size_(strlen(s: text_)) {} |
118 | inline SubstituteArg(unsigned int value) |
119 | : text_(FastUInt32ToBuffer(i: value, buffer: scratch_)), size_(strlen(s: text_)) {} |
120 | inline SubstituteArg(long value) |
121 | : text_(FastLongToBuffer(i: value, buffer: scratch_)), size_(strlen(s: text_)) {} |
122 | inline SubstituteArg(unsigned long value) |
123 | : text_(FastULongToBuffer(i: value, buffer: scratch_)), size_(strlen(s: text_)) {} |
124 | inline SubstituteArg(long long value) |
125 | : text_(FastInt64ToBuffer(i: value, buffer: scratch_)), size_(strlen(s: text_)) {} |
126 | inline SubstituteArg(unsigned long long value) |
127 | : text_(FastUInt64ToBuffer(i: value, buffer: scratch_)), size_(strlen(s: text_)) {} |
128 | inline SubstituteArg(float value) |
129 | : text_(FloatToBuffer(i: value, buffer: scratch_)), size_(strlen(s: text_)) {} |
130 | inline SubstituteArg(double value) |
131 | : text_(DoubleToBuffer(i: value, buffer: scratch_)), size_(strlen(s: text_)) {} |
132 | inline SubstituteArg(bool value) |
133 | : text_(value ? "true" : "false" ), size_(strlen(s: text_)) {} |
134 | |
135 | inline const char* data() const { return text_; } |
136 | inline int size() const { return size_; } |
137 | |
138 | private: |
139 | const char* text_; |
140 | int size_; |
141 | char scratch_[kFastToBufferSize]; |
142 | }; |
143 | |
144 | } // namespace internal |
145 | |
146 | PROTOBUF_EXPORT std::string Substitute( |
147 | const std::string& format, |
148 | const internal::SubstituteArg& arg0 = internal::SubstituteArg(), |
149 | const internal::SubstituteArg& arg1 = internal::SubstituteArg(), |
150 | const internal::SubstituteArg& arg2 = internal::SubstituteArg(), |
151 | const internal::SubstituteArg& arg3 = internal::SubstituteArg(), |
152 | const internal::SubstituteArg& arg4 = internal::SubstituteArg(), |
153 | const internal::SubstituteArg& arg5 = internal::SubstituteArg(), |
154 | const internal::SubstituteArg& arg6 = internal::SubstituteArg(), |
155 | const internal::SubstituteArg& arg7 = internal::SubstituteArg(), |
156 | const internal::SubstituteArg& arg8 = internal::SubstituteArg(), |
157 | const internal::SubstituteArg& arg9 = internal::SubstituteArg()); |
158 | |
159 | PROTOBUF_EXPORT void SubstituteAndAppend( |
160 | std::string* output, const char* format, |
161 | const internal::SubstituteArg& arg0 = internal::SubstituteArg(), |
162 | const internal::SubstituteArg& arg1 = internal::SubstituteArg(), |
163 | const internal::SubstituteArg& arg2 = internal::SubstituteArg(), |
164 | const internal::SubstituteArg& arg3 = internal::SubstituteArg(), |
165 | const internal::SubstituteArg& arg4 = internal::SubstituteArg(), |
166 | const internal::SubstituteArg& arg5 = internal::SubstituteArg(), |
167 | const internal::SubstituteArg& arg6 = internal::SubstituteArg(), |
168 | const internal::SubstituteArg& arg7 = internal::SubstituteArg(), |
169 | const internal::SubstituteArg& arg8 = internal::SubstituteArg(), |
170 | const internal::SubstituteArg& arg9 = internal::SubstituteArg()); |
171 | |
172 | } // namespace strings |
173 | } // namespace protobuf |
174 | } // namespace google |
175 | |
176 | #include <google/protobuf/port_undef.inc> |
177 | |
178 | #endif // GOOGLE_PROTOBUF_STUBS_SUBSTITUTE_H_ |
179 | |