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.h | 149 +++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 Firestore/core/src/firebase/firestore/util/string_format.h (limited to 'Firestore/core/src/firebase/firestore/util/string_format.h') diff --git a/Firestore/core/src/firebase/firestore/util/string_format.h b/Firestore/core/src/firebase/firestore/util/string_format.h new file mode 100644 index 0000000..3d7a1dc --- /dev/null +++ b/Firestore/core/src/firebase/firestore/util/string_format.h @@ -0,0 +1,149 @@ +/* + * 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. + */ + +#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_STRING_FORMAT_H_ +#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_STRING_FORMAT_H_ + +#include +#include +#include + +#include "absl/base/attributes.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/string_view.h" + +namespace firebase { +namespace firestore { +namespace util { + +namespace internal { + +std::string StringFormatPieces(const char* format, + std::initializer_list pieces); + +/** + * Explicit ranking for formatting choices. Only useful as an implementation + * detail of `FormatArg`. + */ +template +struct FormatChoice : FormatChoice {}; + +template <> +struct FormatChoice<4> {}; + +} // namespace internal + +/** + * Acts as the main value parameter to StringFormat and related functions. + * + * Chooses a conversion to a text form in this order: + * * If the value is exactly of `bool` type (without implicit conversions) + * the text will the "true" or "false". + * * If the value is of type `const char*`, the text will be the value + * interpreted as a C string. To show the address of a single char or to + * show the `const char*` as an address, cast to `void*`. + * * If the value is any other pointer type, the text will be the hexidecimal + * formatting of the value as an unsigned integer. + * * Otherwise the value is interpreted as anything absl::AlphaNum accepts. + */ +class FormatArg : public absl::AlphaNum { + public: + template + FormatArg(T&& value) // NOLINT(runtime/explicit) + : FormatArg{std::forward(value), internal::FormatChoice<0>{}} { + } + + private: + /** + * Creates a FormatArg from a boolean value, representing the string + * "true" or "false". + * + * This overload only applies if the type of the argument is exactly `bool`. + * No implicit conversions to bool are accepted. + */ + template {}>::type> + FormatArg(T bool_value, internal::FormatChoice<0>) + : AlphaNum{bool_value ? "true" : "false"} { + } + + /** + * Creates a FormatArg from a character string literal. This is + * handled specially to avoid ambiguity with generic pointers, which are + * handled differently. + */ + FormatArg(std::nullptr_t, internal::FormatChoice<1>) : AlphaNum{"null"} { + } + + /** + * Creates a FormatArg from a character string literal. This is + * handled specially to avoid ambiguity with generic pointers, which are + * handled differently. + */ + FormatArg(const char* string_value, internal::FormatChoice<2>) + : AlphaNum{string_value == nullptr ? "null" : string_value} { + } + + /** + * Creates a FormatArg from an arbitrary pointer, represented as a + * hexidecimal integer literal. + */ + template + FormatArg(T* pointer_value, internal::FormatChoice<3>) + : AlphaNum{absl::Hex{reinterpret_cast(pointer_value)}} { + } + + /** + * As a final fallback, creates a FormatArg from any type of value that + * absl::AlphaNum accepts. + */ + template + FormatArg(T&& value, internal::FormatChoice<4>) + : AlphaNum{std::forward(value)} { + } +}; + +/** + * Formats a string using a simplified printf-like formatting mechanism that + * does not rely on C varargs. + * + * The following format specifiers are recognized: + * * "%%" - A literal "%" + * * "%s" - The next parameter is copied through + * + * Note: + * * If you pass fewer arguments than the format requires, StringFormat will + * insert "". + * * If you pass more arguments than the format requires, any excess arguments + * are ignored. + * * If you use an invalid format specifier, StringFormat will insert + * . + */ +template +std::string StringFormat(const char* format, const FA&... args) { + return internal::StringFormatPieces( + format, {static_cast(args).Piece()...}); +} + +inline std::string StringFormat() { + return {}; +} + +} // namespace util +} // namespace firestore +} // namespace firebase + +#endif // FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_STRING_FORMAT_H_ -- cgit v1.2.3