1 /** @file
2 
3     Forward definitions for BufferWriter formatting.
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 <cstdlib>
27 #include <utility>
28 #include <cstring>
29 #include <vector>
30 #include <map>
31 
32 #include "tscpp/util/TextView.h"
33 #include "tscore/ink_assert.h"
34 
35 namespace ts
36 {
37 /** A parsed version of a format specifier.
38  */
39 struct BWFSpec {
40   using self_type                    = BWFSpec; ///< Self reference type.
41   static constexpr char DEFAULT_TYPE = 'g';     ///< Default format type.
42 
43   /// Constructor a default instance.
BWFSpects::BWFSpec44   constexpr BWFSpec() {}
45 
46   /// Construct by parsing @a fmt.
47   BWFSpec(TextView fmt);
48 
49   char _fill = ' '; ///< Fill character.
50   char _sign = '-'; ///< Numeric sign style, space + -
51   enum class Align : char {
52     NONE,                            ///< No alignment.
53     LEFT,                            ///< Left alignment '<'.
54     RIGHT,                           ///< Right alignment '>'.
55     CENTER,                          ///< Center alignment '^'.
56     SIGN                             ///< Align plus/minus sign before numeric fill. '='
57   } _align           = Align::NONE;  ///< Output field alignment.
58   char _type         = DEFAULT_TYPE; ///< Type / radix indicator.
59   bool _radix_lead_p = false;        ///< Print leading radix indication.
60   // @a _min is unsigned because there's no point in an invalid default, 0 works fine.
61   unsigned int _min = 0;                                        ///< Minimum width.
62   int _prec         = -1;                                       ///< Precision
63   unsigned int _max = std::numeric_limits<unsigned int>::max(); ///< Maximum width
64   int _idx          = -1;                                       ///< Positional "name" of the specification.
65   std::string_view _name;                                       ///< Name of the specification.
66   std::string_view _ext;                                        ///< Extension if provided.
67 
68   static const self_type DEFAULT;
69 
70   /// Validate @a c is a specifier type indicator.
71   static bool is_type(char c);
72   /// Check if the type flag is numeric.
73   static bool is_numeric_type(char c);
74   /// Check if the type is an upper case variant.
75   static bool is_upper_case_type(char c);
76   /// Check if the type @a in @a this is numeric.
77   bool has_numeric_type() const;
78   /// Check if the type in @a this is an upper case variant.
79   bool has_upper_case_type() const;
80   /// Check if the type is a raw pointer.
81   bool has_pointer_type() const;
82 
83 protected:
84   /// Validate character is alignment character and return the appropriate enum value.
85   Align align_of(char c);
86 
87   /// Validate is sign indicator.
88   bool is_sign(char c);
89 
90   /// Handrolled initialization the character syntactic property data.
91   static const struct Property {
92     Property(); ///< Default constructor, creates initialized flag set.
93     /// Flag storage, indexed by character value.
94     uint8_t _data[0x100];
95     /// Flag mask values.
96     static constexpr uint8_t ALIGN_MASK        = 0x0F; ///< Alignment type.
97     static constexpr uint8_t TYPE_CHAR         = 0x10; ///< A valid type character.
98     static constexpr uint8_t UPPER_TYPE_CHAR   = 0x20; ///< Upper case flag.
99     static constexpr uint8_t NUMERIC_TYPE_CHAR = 0x40; ///< Numeric output.
100     static constexpr uint8_t SIGN_CHAR         = 0x80; ///< Is sign character.
101   } _prop;
102 };
103 
104 inline BWFSpec::Align
align_of(char c)105 BWFSpec::align_of(char c)
106 {
107   return static_cast<Align>(_prop._data[static_cast<unsigned>(c)] & Property::ALIGN_MASK);
108 }
109 
110 inline bool
is_sign(char c)111 BWFSpec::is_sign(char c)
112 {
113   return _prop._data[static_cast<unsigned>(c)] & Property::SIGN_CHAR;
114 }
115 
116 inline bool
is_type(char c)117 BWFSpec::is_type(char c)
118 {
119   return _prop._data[static_cast<unsigned>(c)] & Property::TYPE_CHAR;
120 }
121 
122 inline bool
is_upper_case_type(char c)123 BWFSpec::is_upper_case_type(char c)
124 {
125   return _prop._data[static_cast<unsigned>(c)] & Property::UPPER_TYPE_CHAR;
126 }
127 
128 inline bool
has_numeric_type() const129 BWFSpec::has_numeric_type() const
130 {
131   return _prop._data[static_cast<unsigned>(_type)] & Property::NUMERIC_TYPE_CHAR;
132 }
133 
134 inline bool
has_upper_case_type() const135 BWFSpec::has_upper_case_type() const
136 {
137   return _prop._data[static_cast<unsigned>(_type)] & Property::UPPER_TYPE_CHAR;
138 }
139 
140 inline bool
has_pointer_type() const141 BWFSpec::has_pointer_type() const
142 {
143   return _type == 'p' || _type == 'P';
144 }
145 
146 class BWFormat;
147 
148 class BufferWriter;
149 
150 } // namespace ts
151