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. 24 // 25 // std::string_view name = "Volume"; 26 // ftl::Concat string(ftl::truncated<3>(name), ": ", -3, " dB"); 27 // 28 // assert(string.str() == "Vol: -3 dB"); 29 // assert(string.c_str()[string.size()] == '\0'); 30 // 31 template <std::size_t, typename... Ts> 32 struct Concat; 33 34 template <std::size_t N, typename T, typename... Ts> 35 struct Concat<N, T, Ts...> : Concat<N + details::StaticString<T>::N, Ts...> { 36 explicit constexpr Concat(T v, Ts... args) { append(v, args...); } 37 38 protected: 39 constexpr Concat() = default; 40 41 constexpr void append(T v, Ts... args) { 42 using Str = details::StaticString<T>; 43 const Str str(v); 44 45 // TODO: Replace with constexpr std::copy in C++20. 46 for (auto it = str.view.begin(); it != str.view.end();) { 47 *this->end_++ = *it++; 48 } 49 50 using Base = Concat<N + Str::N, Ts...>; 51 this->Base::append(args...); 52 } 53 }; 54 55 template <std::size_t N> 56 struct Concat<N> { 57 static constexpr std::size_t max_size() { return N; } 58 constexpr std::size_t size() const { return end_ - buffer_; } 59 60 constexpr const char* c_str() const { return buffer_; } 61 62 constexpr std::string_view str() const { 63 // TODO: Replace with {buffer_, end_} in C++20. 64 return {buffer_, size()}; 65 } 66 67 protected: 68 constexpr Concat() : end_(buffer_) {} 69 constexpr void append() { *end_ = '\0'; } 70 71 char buffer_[N + 1]; 72 char* end_; 73 }; 74 75 // Deduction guide. 76 template <typename... Ts> 77 Concat(Ts&&...) -> Concat<0, Ts...>; 78 79 template <std::size_t N> 80 constexpr auto truncated(std::string_view v) { 81 return details::Truncated<N>{v}; 82 } 83 84 } // namespace android::ftl 85