extension.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. //
  2. // Copyright 2017 The Abseil Authors.
  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. // https://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. #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
  17. #define ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
  18. #include <cstddef>
  19. #include <cstdint>
  20. #include <cstring>
  21. #include <ostream>
  22. #include <string>
  23. #include "absl/base/config.h"
  24. #include "absl/strings/internal/str_format/output.h"
  25. #include "absl/strings/string_view.h"
  26. namespace absl {
  27. ABSL_NAMESPACE_BEGIN
  28. enum class FormatConversionChar : uint8_t;
  29. enum class FormatConversionCharSet : uint64_t;
  30. enum class LengthMod : std::uint8_t { h, hh, l, ll, L, j, z, t, q, none };
  31. namespace str_format_internal {
  32. class FormatRawSinkImpl {
  33. public:
  34. // Implicitly convert from any type that provides the hook function as
  35. // described above.
  36. template <typename T, decltype(str_format_internal::InvokeFlush(
  37. std::declval<T*>(), string_view()))* = nullptr>
  38. FormatRawSinkImpl(T* raw) // NOLINT
  39. : sink_(raw), write_(&FormatRawSinkImpl::Flush<T>) {}
  40. void Write(string_view s) { write_(sink_, s); }
  41. template <typename T>
  42. static FormatRawSinkImpl Extract(T s) {
  43. return s.sink_;
  44. }
  45. private:
  46. template <typename T>
  47. static void Flush(void* r, string_view s) {
  48. str_format_internal::InvokeFlush(static_cast<T*>(r), s);
  49. }
  50. void* sink_;
  51. void (*write_)(void*, string_view);
  52. };
  53. // An abstraction to which conversions write their string data.
  54. class FormatSinkImpl {
  55. public:
  56. explicit FormatSinkImpl(FormatRawSinkImpl raw) : raw_(raw) {}
  57. ~FormatSinkImpl() { Flush(); }
  58. void Flush() {
  59. raw_.Write(string_view(buf_, static_cast<size_t>(pos_ - buf_)));
  60. pos_ = buf_;
  61. }
  62. void Append(size_t n, char c) {
  63. if (n == 0) return;
  64. size_ += n;
  65. auto raw_append = [&](size_t count) {
  66. memset(pos_, c, count);
  67. pos_ += count;
  68. };
  69. while (n > Avail()) {
  70. n -= Avail();
  71. if (Avail() > 0) {
  72. raw_append(Avail());
  73. }
  74. Flush();
  75. }
  76. raw_append(n);
  77. }
  78. void Append(string_view v) {
  79. size_t n = v.size();
  80. if (n == 0) return;
  81. size_ += n;
  82. if (n >= Avail()) {
  83. Flush();
  84. raw_.Write(v);
  85. return;
  86. }
  87. memcpy(pos_, v.data(), n);
  88. pos_ += n;
  89. }
  90. size_t size() const { return size_; }
  91. // Put 'v' to 'sink' with specified width, precision, and left flag.
  92. bool PutPaddedString(string_view v, int width, int precision, bool left);
  93. template <typename T>
  94. T Wrap() {
  95. return T(this);
  96. }
  97. template <typename T>
  98. static FormatSinkImpl* Extract(T* s) {
  99. return s->sink_;
  100. }
  101. private:
  102. size_t Avail() const {
  103. return static_cast<size_t>(buf_ + sizeof(buf_) - pos_);
  104. }
  105. FormatRawSinkImpl raw_;
  106. size_t size_ = 0;
  107. char* pos_ = buf_;
  108. char buf_[1024];
  109. };
  110. enum class Flags : uint8_t {
  111. kBasic = 0,
  112. kLeft = 1 << 0,
  113. kShowPos = 1 << 1,
  114. kSignCol = 1 << 2,
  115. kAlt = 1 << 3,
  116. kZero = 1 << 4,
  117. // This is not a real flag. It just exists to turn off kBasic when no other
  118. // flags are set. This is for when width/precision are specified, or a length
  119. // modifier affects the behavior ("%lc").
  120. kNonBasic = 1 << 5,
  121. };
  122. constexpr Flags operator|(Flags a, Flags b) {
  123. return static_cast<Flags>(static_cast<uint8_t>(a) | static_cast<uint8_t>(b));
  124. }
  125. constexpr bool FlagsContains(Flags haystack, Flags needle) {
  126. return (static_cast<uint8_t>(haystack) & static_cast<uint8_t>(needle)) ==
  127. static_cast<uint8_t>(needle);
  128. }
  129. std::string FlagsToString(Flags v);
  130. inline std::ostream& operator<<(std::ostream& os, Flags v) {
  131. return os << FlagsToString(v);
  132. }
  133. // clang-format off
  134. #define ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(X_VAL, X_SEP) \
  135. /* text */ \
  136. X_VAL(c) X_SEP X_VAL(s) X_SEP \
  137. /* ints */ \
  138. X_VAL(d) X_SEP X_VAL(i) X_SEP X_VAL(o) X_SEP \
  139. X_VAL(u) X_SEP X_VAL(x) X_SEP X_VAL(X) X_SEP \
  140. /* floats */ \
  141. X_VAL(f) X_SEP X_VAL(F) X_SEP X_VAL(e) X_SEP X_VAL(E) X_SEP \
  142. X_VAL(g) X_SEP X_VAL(G) X_SEP X_VAL(a) X_SEP X_VAL(A) X_SEP \
  143. /* misc */ \
  144. X_VAL(n) X_SEP X_VAL(p) X_SEP X_VAL(v)
  145. // clang-format on
  146. // This type should not be referenced, it exists only to provide labels
  147. // internally that match the values declared in FormatConversionChar in
  148. // str_format.h. This is meant to allow internal libraries to use the same
  149. // declared interface type as the public interface
  150. // (absl::StrFormatConversionChar) while keeping the definition in a public
  151. // header.
  152. // Internal libraries should use the form
  153. // `FormatConversionCharInternal::c`, `FormatConversionCharInternal::kNone` for
  154. // comparisons. Use in switch statements is not recommended due to a bug in how
  155. // gcc 4.9 -Wswitch handles declared but undefined enums.
  156. struct FormatConversionCharInternal {
  157. FormatConversionCharInternal() = delete;
  158. private:
  159. // clang-format off
  160. enum class Enum : uint8_t {
  161. c, s, // text
  162. d, i, o, u, x, X, // int
  163. f, F, e, E, g, G, a, A, // float
  164. n, p, v, // misc
  165. kNone
  166. };
  167. // clang-format on
  168. public:
  169. #define ABSL_INTERNAL_X_VAL(id) \
  170. static constexpr FormatConversionChar id = \
  171. static_cast<FormatConversionChar>(Enum::id);
  172. ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )
  173. #undef ABSL_INTERNAL_X_VAL
  174. static constexpr FormatConversionChar kNone =
  175. static_cast<FormatConversionChar>(Enum::kNone);
  176. };
  177. // clang-format on
  178. inline FormatConversionChar FormatConversionCharFromChar(char c) {
  179. switch (c) {
  180. #define ABSL_INTERNAL_X_VAL(id) \
  181. case #id[0]: \
  182. return FormatConversionCharInternal::id;
  183. ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )
  184. #undef ABSL_INTERNAL_X_VAL
  185. }
  186. return FormatConversionCharInternal::kNone;
  187. }
  188. inline bool FormatConversionCharIsUpper(FormatConversionChar c) {
  189. if (c == FormatConversionCharInternal::X ||
  190. c == FormatConversionCharInternal::F ||
  191. c == FormatConversionCharInternal::E ||
  192. c == FormatConversionCharInternal::G ||
  193. c == FormatConversionCharInternal::A) {
  194. return true;
  195. } else {
  196. return false;
  197. }
  198. }
  199. inline bool FormatConversionCharIsFloat(FormatConversionChar c) {
  200. if (c == FormatConversionCharInternal::a ||
  201. c == FormatConversionCharInternal::e ||
  202. c == FormatConversionCharInternal::f ||
  203. c == FormatConversionCharInternal::g ||
  204. c == FormatConversionCharInternal::A ||
  205. c == FormatConversionCharInternal::E ||
  206. c == FormatConversionCharInternal::F ||
  207. c == FormatConversionCharInternal::G) {
  208. return true;
  209. } else {
  210. return false;
  211. }
  212. }
  213. inline char FormatConversionCharToChar(FormatConversionChar c) {
  214. if (c == FormatConversionCharInternal::kNone) {
  215. return '\0';
  216. #define ABSL_INTERNAL_X_VAL(e) \
  217. } else if (c == FormatConversionCharInternal::e) { \
  218. return #e[0];
  219. #define ABSL_INTERNAL_X_SEP
  220. ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL,
  221. ABSL_INTERNAL_X_SEP)
  222. } else {
  223. return '\0';
  224. }
  225. #undef ABSL_INTERNAL_X_VAL
  226. #undef ABSL_INTERNAL_X_SEP
  227. }
  228. // The associated char.
  229. inline std::ostream& operator<<(std::ostream& os, FormatConversionChar v) {
  230. char c = FormatConversionCharToChar(v);
  231. if (!c) c = '?';
  232. return os << c;
  233. }
  234. struct FormatConversionSpecImplFriend;
  235. class FormatConversionSpecImpl {
  236. public:
  237. // Width and precision are not specified, no flags are set.
  238. bool is_basic() const { return flags_ == Flags::kBasic; }
  239. bool has_left_flag() const { return FlagsContains(flags_, Flags::kLeft); }
  240. bool has_show_pos_flag() const {
  241. return FlagsContains(flags_, Flags::kShowPos);
  242. }
  243. bool has_sign_col_flag() const {
  244. return FlagsContains(flags_, Flags::kSignCol);
  245. }
  246. bool has_alt_flag() const { return FlagsContains(flags_, Flags::kAlt); }
  247. bool has_zero_flag() const { return FlagsContains(flags_, Flags::kZero); }
  248. LengthMod length_mod() const { return length_mod_; }
  249. FormatConversionChar conversion_char() const {
  250. // Keep this field first in the struct . It generates better code when
  251. // accessing it when ConversionSpec is passed by value in registers.
  252. static_assert(offsetof(FormatConversionSpecImpl, conv_) == 0, "");
  253. return conv_;
  254. }
  255. void set_conversion_char(FormatConversionChar c) { conv_ = c; }
  256. // Returns the specified width. If width is unspecfied, it returns a negative
  257. // value.
  258. int width() const { return width_; }
  259. // Returns the specified precision. If precision is unspecfied, it returns a
  260. // negative value.
  261. int precision() const { return precision_; }
  262. template <typename T>
  263. T Wrap() {
  264. return T(*this);
  265. }
  266. private:
  267. friend struct str_format_internal::FormatConversionSpecImplFriend;
  268. FormatConversionChar conv_ = FormatConversionCharInternal::kNone;
  269. Flags flags_;
  270. LengthMod length_mod_ = LengthMod::none;
  271. int width_;
  272. int precision_;
  273. };
  274. struct FormatConversionSpecImplFriend final {
  275. static void SetFlags(Flags f, FormatConversionSpecImpl* conv) {
  276. conv->flags_ = f;
  277. }
  278. static void SetLengthMod(LengthMod l, FormatConversionSpecImpl* conv) {
  279. conv->length_mod_ = l;
  280. }
  281. static void SetConversionChar(FormatConversionChar c,
  282. FormatConversionSpecImpl* conv) {
  283. conv->conv_ = c;
  284. }
  285. static void SetWidth(int w, FormatConversionSpecImpl* conv) {
  286. conv->width_ = w;
  287. }
  288. static void SetPrecision(int p, FormatConversionSpecImpl* conv) {
  289. conv->precision_ = p;
  290. }
  291. static std::string FlagsToString(const FormatConversionSpecImpl& spec) {
  292. return str_format_internal::FlagsToString(spec.flags_);
  293. }
  294. };
  295. // Type safe OR operator.
  296. // We need this for two reasons:
  297. // 1. operator| on enums makes them decay to integers and the result is an
  298. // integer. We need the result to stay as an enum.
  299. // 2. We use "enum class" which would not work even if we accepted the decay.
  300. constexpr FormatConversionCharSet FormatConversionCharSetUnion(
  301. FormatConversionCharSet a) {
  302. return a;
  303. }
  304. template <typename... CharSet>
  305. constexpr FormatConversionCharSet FormatConversionCharSetUnion(
  306. FormatConversionCharSet a, CharSet... rest) {
  307. return static_cast<FormatConversionCharSet>(
  308. static_cast<uint64_t>(a) |
  309. static_cast<uint64_t>(FormatConversionCharSetUnion(rest...)));
  310. }
  311. constexpr uint64_t FormatConversionCharToConvInt(FormatConversionChar c) {
  312. return uint64_t{1} << (1 + static_cast<uint8_t>(c));
  313. }
  314. constexpr uint64_t FormatConversionCharToConvInt(char conv) {
  315. return
  316. #define ABSL_INTERNAL_CHAR_SET_CASE(c) \
  317. conv == #c[0] \
  318. ? FormatConversionCharToConvInt(FormatConversionCharInternal::c) \
  319. :
  320. ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, )
  321. #undef ABSL_INTERNAL_CHAR_SET_CASE
  322. conv == '*'
  323. ? 1
  324. : 0;
  325. }
  326. constexpr FormatConversionCharSet FormatConversionCharToConvValue(char conv) {
  327. return static_cast<FormatConversionCharSet>(
  328. FormatConversionCharToConvInt(conv));
  329. }
  330. struct FormatConversionCharSetInternal {
  331. #define ABSL_INTERNAL_CHAR_SET_CASE(c) \
  332. static constexpr FormatConversionCharSet c = \
  333. FormatConversionCharToConvValue(#c[0]);
  334. ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, )
  335. #undef ABSL_INTERNAL_CHAR_SET_CASE
  336. // Used for width/precision '*' specification.
  337. static constexpr FormatConversionCharSet kStar =
  338. FormatConversionCharToConvValue('*');
  339. static constexpr FormatConversionCharSet kIntegral =
  340. FormatConversionCharSetUnion(d, i, u, o, x, X);
  341. static constexpr FormatConversionCharSet kFloating =
  342. FormatConversionCharSetUnion(a, e, f, g, A, E, F, G);
  343. static constexpr FormatConversionCharSet kNumeric =
  344. FormatConversionCharSetUnion(kIntegral, kFloating);
  345. static constexpr FormatConversionCharSet kPointer = p;
  346. };
  347. // Type safe OR operator.
  348. // We need this for two reasons:
  349. // 1. operator| on enums makes them decay to integers and the result is an
  350. // integer. We need the result to stay as an enum.
  351. // 2. We use "enum class" which would not work even if we accepted the decay.
  352. constexpr FormatConversionCharSet operator|(FormatConversionCharSet a,
  353. FormatConversionCharSet b) {
  354. return FormatConversionCharSetUnion(a, b);
  355. }
  356. // Overloaded conversion functions to support absl::ParsedFormat.
  357. // Get a conversion with a single character in it.
  358. constexpr FormatConversionCharSet ToFormatConversionCharSet(char c) {
  359. return static_cast<FormatConversionCharSet>(
  360. FormatConversionCharToConvValue(c));
  361. }
  362. // Get a conversion with a single character in it.
  363. constexpr FormatConversionCharSet ToFormatConversionCharSet(
  364. FormatConversionCharSet c) {
  365. return c;
  366. }
  367. template <typename T>
  368. void ToFormatConversionCharSet(T) = delete;
  369. // Checks whether `c` exists in `set`.
  370. constexpr bool Contains(FormatConversionCharSet set, char c) {
  371. return (static_cast<uint64_t>(set) &
  372. static_cast<uint64_t>(FormatConversionCharToConvValue(c))) != 0;
  373. }
  374. // Checks whether all the characters in `c` are contained in `set`
  375. constexpr bool Contains(FormatConversionCharSet set,
  376. FormatConversionCharSet c) {
  377. return (static_cast<uint64_t>(set) & static_cast<uint64_t>(c)) ==
  378. static_cast<uint64_t>(c);
  379. }
  380. // Checks whether all the characters in `c` are contained in `set`
  381. constexpr bool Contains(FormatConversionCharSet set, FormatConversionChar c) {
  382. return (static_cast<uint64_t>(set) & FormatConversionCharToConvInt(c)) != 0;
  383. }
  384. // Return capacity - used, clipped to a minimum of 0.
  385. inline size_t Excess(size_t used, size_t capacity) {
  386. return used < capacity ? capacity - used : 0;
  387. }
  388. } // namespace str_format_internal
  389. ABSL_NAMESPACE_END
  390. } // namespace absl
  391. #endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_