Fcitx
stringutils_details.h
1 /*
2  * SPDX-FileCopyrightText: 2017-2017 CSSlayer <wengxt@gmail.com>
3  *
4  * SPDX-License-Identifier: LGPL-2.1-or-later
5  *
6  */
7 #ifndef _FCITX_UTILS_STRINGUTILS_DETAIL_H_
8 #define _FCITX_UTILS_STRINGUTILS_DETAIL_H_
9 
10 // IWYU pragma: private, include <fcitx/stringutils.h>
11 
12 #include <cassert>
13 #include <cstdio>
14 #include <cstring>
15 #include <initializer_list>
16 #include <string>
17 #include <string_view>
18 #include <type_traits>
19 #include <utility>
20 #include <fcitx-utils/fcitxutils_export.h>
21 
23 
24 template <typename T>
26  static const T &forward(const T &t) { return t; }
27 };
28 
29 template <typename T, size_t TN>
30 struct UniversalPieceHelper<T[TN]> {
31  static std::pair<const char *, std::size_t> forward(const T (&t)[TN]) {
32  static_assert(TN > 0, "No char array but only literal");
33  return {t, TN - 1};
34  }
35 };
36 
37 template <typename T>
38 struct UniversalPieceHelper<T *> {
39  static std::pair<const char *, std::size_t> forward(T *t) {
40  return {t, std::char_traits<char>::length(t)};
41  }
42 };
43 
44 template <>
45 struct UniversalPieceHelper<std::string_view> {
46  static std::pair<const char *, std::size_t> forward(std::string_view t) {
47  return {t.data(), t.size()};
48  }
49 };
50 
52 public:
53  UniversalPiece(std::pair<const char *, std::size_t> p)
54  : piece_(p.first), size_(p.second) {}
55 
56  template <typename T,
57  typename = std::enable_if_t<std::is_same<T, char>::value>>
58  UniversalPiece(const T *p)
59  : piece_(p), size_(std::char_traits<T>::length(p)) {}
60 
61  UniversalPiece(const std::string &str)
62  : piece_(str.data()), size_(str.size()) {}
63 
64  UniversalPiece(char c) = delete;
65 #define UNIVERSAL_PIECE_NUMERIC_CONVERSION(TYPE, FORMAT_STRING) \
66  UniversalPiece(TYPE i) : piece_(buffer_) { \
67  auto size = snprintf(buffer_, sizeof(buffer_), FORMAT_STRING, i); \
68  assert(size >= 0 && static_cast<size_t>(size) + 1 <= sizeof(buffer_)); \
69  size_ = size; \
70  }
71  UNIVERSAL_PIECE_NUMERIC_CONVERSION(int, "%d");
72  UNIVERSAL_PIECE_NUMERIC_CONVERSION(unsigned int, "%u");
73  UNIVERSAL_PIECE_NUMERIC_CONVERSION(long, "%ld");
74  UNIVERSAL_PIECE_NUMERIC_CONVERSION(unsigned long, "%lu");
75  UNIVERSAL_PIECE_NUMERIC_CONVERSION(long long, "%lld");
76  UNIVERSAL_PIECE_NUMERIC_CONVERSION(unsigned long long, "%llu");
77  UNIVERSAL_PIECE_NUMERIC_CONVERSION(float, "%f");
78  UNIVERSAL_PIECE_NUMERIC_CONVERSION(double, "%lf");
79 
80  UniversalPiece(const UniversalPiece &) = delete;
81 
82  const char *piece() const { return piece_; }
83  std::size_t size() const { return size_; }
84 
85  std::pair<const char *, std::size_t> toPair() const {
86  return {piece_, size_};
87  }
88 
89  std::pair<const char *, std::size_t>
90  toPathPair(const bool removePrefixSlash = true) const {
91  const auto *piece = piece_;
92  auto size = size_;
93  // Consume prefix and suffix slash.
94  if (removePrefixSlash) {
95  while (size && piece[0] == '/') {
96  ++piece;
97  --size;
98  }
99  }
100  while (size && piece[size - 1] == '/') {
101  --size;
102  }
103  // If first component is all slash, keep all of them.
104  if (size_ && !removePrefixSlash && !size) {
105  return {piece_, size_};
106  }
107 
108  assert(size > 0);
109  return {piece, size};
110  }
111 
112 private:
113  static constexpr int IntegerBufferSize = 30;
114  const char *piece_;
115  std::size_t size_;
116  char buffer_[IntegerBufferSize];
117 };
118 
119 FCITXUTILS_EXPORT std::string
120 concatPieces(std::initializer_list<std::pair<const char *, std::size_t>> list);
121 
122 FCITXUTILS_EXPORT std::string concatPathPieces(
123  std::initializer_list<std::pair<const char *, std::size_t>> list);
124 
125 } // namespace fcitx::stringutils::details
126 
127 #endif // _FCITX_UTILS_STRINGUTILS_DETAIL_H_
size_t length(Iter start, Iter end)
Return the number UTF-8 characters in the string iterator range.
Definition: utf8.h:33
Definition: matchrule.h:78