1 /* 2 * Copyright 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <ftl/details/concat.h> 20 21 namespace android::ftl { 22 23 // Lightweight (not allocating nor sprintf-based) concatenation. The variadic arguments can be 24 // values of integral type (including bool and char), string literals, or strings whose length 25 // is constrained: 26 // 27 // std::string_view name = "Volume"; 28 // ftl::Concat string(ftl::truncated<3>(name), ": ", -3, " dB"); 29 // 30 // assert(string.str() == "Vol: -3 dB"); 31 // assert(string.c_str()[string.size()] == '\0'); 32 // 33 template <std::size_t, typename... Ts> 34 struct Concat; 35 36 template <std::size_t N, typename T, typename... Ts> 37 struct Concat<N, T, Ts...> : Concat<N + details::StaticString<T>::N, Ts...> { 38 explicit constexpr Concat(T v, Ts... args) { append(v, args...); } 39 40 protected: 41 constexpr Concat() = default; 42 43 constexpr void append(T v, Ts... args) { 44 using Str = details::StaticString<T>; 45 const Str str(v); 46 47 // TODO: Replace with constexpr std::copy in C++20. 48 for (auto it = str.view.begin(); it != str.view.end();) { 49 *this->end_++ = *it++; 50 } 51 52 using Base = Concat<N + Str::N, Ts...>; 53 this->Base::append(args...); 54 } 55 }; 56 57 template <std::size_t N> 58 struct Concat<N> { 59 static constexpr std::size_t max_size() { return N; } 60 constexpr std::size_t size() const { return end_ - buffer_; } 61 62 constexpr const char* c_str() const { return buffer_; } 63 64 constexpr std::string_view str() const { 65 // TODO: Replace with {buffer_, end_} in C++20. 66 return {buffer_, size()}; 67 } 68 69 protected: 70 constexpr Concat() : end_(buffer_) {} 71 constexpr void append() { *end_ = '\0'; } 72 73 char buffer_[N + 1]; 74 char* end_; 75 }; 76 77 // Deduction guide. 78 template <typename... Ts> 79 Concat(Ts&&...) -> Concat<0, Ts...>; 80 81 template <std::size_t N> 82 constexpr auto truncated(std::string_view v) { 83 return details::Truncated<N>{v}; 84 } 85 86 } // namespace android::ftl 87