| 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 | |