blob: ded48f7c8c7bf762ddd0b85cf496d4c88d2ccd9b [file] [log] [blame]
Dominik Laskowskic74e9e22021-12-02 09:49:12 -08001/*
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
21namespace 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//
31template <std::size_t, typename... Ts>
32struct Concat;
33
34template <std::size_t N, typename T, typename... Ts>
35struct 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
55template <std::size_t N>
56struct 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.
76template <typename... Ts>
77Concat(Ts&&...) -> Concat<0, Ts...>;
78
79template <std::size_t N>
80constexpr auto truncated(std::string_view v) {
81 return details::Truncated<N>{v};
82}
83
84} // namespace android::ftl