1 /** @file
2 
3     BufferWriter formatters for types in the std namespace.
4 
5     @section license License
6 
7     Licensed to the Apache Software Foundation (ASF) under one
8     or more contributor license agreements.  See the NOTICE file
9     distributed with this work for additional information
10     regarding copyright ownership.  The ASF licenses this file
11     to you under the Apache License, Version 2.0 (the
12     "License"); you may not use this file except in compliance
13     with the License.  You may obtain a copy of the License at
14 
15     http://www.apache.org/licenses/LICENSE-2.0
16 
17     Unless required by applicable law or agreed to in writing, software
18     distributed under the License is distributed on an "AS IS" BASIS,
19     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20     See the License for the specific language governing permissions and
21     limitations under the License.
22  */
23 
24 #pragma once
25 
26 #include <atomic>
27 #include <array>
28 #include <string_view>
29 #include "tscpp/util/TextView.h"
30 #include "tscore/BufferWriterForward.h"
31 
32 namespace std
33 {
34 template <typename T>
35 ts::BufferWriter &
bwformat(ts::BufferWriter & w,ts::BWFSpec const & spec,atomic<T> const & v)36 bwformat(ts::BufferWriter &w, ts::BWFSpec const &spec, atomic<T> const &v)
37 {
38   return ts::bwformat(w, spec, v.load());
39 }
40 } // end namespace std
41 
42 namespace ts
43 {
44 namespace bwf
45 {
46   using namespace std::literals; // enable ""sv
47 
48   /** Format wrapper for @c errno.
49    * This stores a copy of the argument or @c errno if an argument isn't provided. The output
50    * is then formatted with the short, long, and numeric value of @c errno. If the format specifier
51    * is type 'd' then just the numeric value is printed.
52    */
53   struct Errno {
54     int _e;
Errnots::bwf::Errno55     explicit Errno(int e = errno) : _e(e) {}
56   };
57 
58   /** Format wrapper for time stamps.
59    * If the time isn't provided, the current epoch time is used. If the format string isn't
60    * provided a format like "2017 Jun 29 14:11:29" is used.
61    */
62   struct Date {
63     static constexpr std::string_view DEFAULT_FORMAT{"%Y %b %d %H:%M:%S"_sv};
64     time_t _epoch;
65     std::string_view _fmt;
Datets::bwf::Date66     Date(time_t t, std::string_view fmt = DEFAULT_FORMAT) : _epoch(t), _fmt(fmt) {}
67     Date(std::string_view fmt = DEFAULT_FORMAT);
68   };
69 
70   namespace detail
71   {
72     // Special case conversions - these handle nullptr because the @c std::string_view spec is stupid.
FirstOfConverter(std::nullptr_t)73     inline std::string_view FirstOfConverter(std::nullptr_t) { return std::string_view{}; }
74     inline std::string_view
FirstOfConverter(char const * s)75     FirstOfConverter(char const *s)
76     {
77       return std::string_view{s ? s : ""};
78     }
79     // Otherwise do any compliant conversion.
80     template <typename T>
81     std::string_view
FirstOfConverter(T && t)82     FirstOfConverter(T &&t)
83     {
84       return t;
85     }
86   } // namespace detail
87   /// Print the first of a list of strings that is not an empty string.
88   /// All arguments must be convertible to @c std::string.
89   template <typename... Args>
90   std::string_view
FirstOf(Args &&...args)91   FirstOf(Args &&... args)
92   {
93     std::array<std::string_view, sizeof...(args)> strings{{detail::FirstOfConverter(args)...}};
94     for (auto &s : strings) {
95       if (!s.empty())
96         return s;
97     }
98     return std::string_view{};
99   };
100   /** For optional printing strings along with suffixes and prefixes.
101    *  If the wrapped string is null or empty, nothing is printed. Otherwise the prefix, string,
102    *  and suffix are printed. The default are a single space for suffix and nothing for the prefix.
103    */
104   struct OptionalAffix {
105     std::string_view _text;
106     std::string_view _suffix;
107     std::string_view _prefix;
108 
OptionalAffixts::bwf::OptionalAffix109     OptionalAffix(const char *text, std::string_view suffix = " "sv, std::string_view prefix = ""sv)
110       : OptionalAffix(std::string_view(text ? text : ""), suffix, prefix)
111     {
112     }
113 
OptionalAffixts::bwf::OptionalAffix114     OptionalAffix(std::string_view text, std::string_view suffix = " "sv, std::string_view prefix = ""sv)
115     {
116       // If text is null or empty, leave the members empty too.
117       if (!text.empty()) {
118         _text   = text;
119         _prefix = prefix;
120         _suffix = suffix;
121       }
122     }
123   };
124 
125 }; // namespace bwf
126 
127 BufferWriter &bwformat(BufferWriter &w, BWFSpec const &spec, bwf::Errno const &e);
128 BufferWriter &bwformat(BufferWriter &w, BWFSpec const &spec, bwf::Date const &date);
129 BufferWriter &bwformat(BufferWriter &w, BWFSpec const &spec, bwf::OptionalAffix const &opts);
130 
131 } // namespace ts
132