From 11933c038df81f57c0e7d15f5a8795b74e874843 Mon Sep 17 00:00:00 2001 From: Gil Date: Mon, 21 May 2018 13:17:29 -0700 Subject: Add a C++ native StringFormat (#1289) * Add StringFormat * Use StringFormat --- .../src/firebase/firestore/util/string_format.cc | 94 ++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 Firestore/core/src/firebase/firestore/util/string_format.cc (limited to 'Firestore/core/src/firebase/firestore/util/string_format.cc') diff --git a/Firestore/core/src/firebase/firestore/util/string_format.cc b/Firestore/core/src/firebase/firestore/util/string_format.cc new file mode 100644 index 0000000..bafdac2 --- /dev/null +++ b/Firestore/core/src/firebase/firestore/util/string_format.cc @@ -0,0 +1,94 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Firestore/core/src/firebase/firestore/util/string_format.h" + +namespace firebase { +namespace firestore { +namespace util { +namespace internal { + +static const char* kMissing = ""; +static const char* kInvalid = ""; + +std::string StringFormatPieces( + const char* format, std::initializer_list pieces) { + std::string result; + + const char* format_iter = format; + const char* format_end = format + strlen(format); + + auto pieces_iter = pieces.begin(); + auto pieces_end = pieces.end(); + auto append_next_piece = [&](std::string* dest) { + if (pieces_iter == pieces_end) { + dest->append(kMissing); + } else { + // Pass a piece through + dest->append(pieces_iter->data(), pieces_iter->size()); + ++pieces_iter; + } + }; + + auto append_specifier = [&](char spec) { + switch (spec) { + case '%': + // Pass through literal %. + result.push_back('%'); + break; + + case 's': { + append_next_piece(&result); + break; + } + + default: + result.append(kInvalid); + break; + } + }; + + // Iterate through the format string, advancing `format_iter` as we go. + while (true) { + const char* percent_ptr = std::find(format_iter, format_end, '%'); + + // percent either points to the next format specifier or the end of the + // format string. Either is safe to append here: + result.append(format_iter, percent_ptr); + if (percent_ptr == format_end) { + // No further pieces to format + break; + } + + // Examine the specifier: + const char* spec_ptr = percent_ptr + 1; + if (spec_ptr == format_end) { + // Incomplete specifier, treat as a literal "%" and be done. + append_specifier('%'); + break; + } + append_specifier(*spec_ptr); + + format_iter = spec_ptr + 1; + } + + return result; +} + +} // namespace internal +} // namespace util +} // namespace firestore +} // namespace firebase -- cgit v1.2.3