1 /****************************************************************************
2 **
3 ** Copyright (C) 2018 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #ifndef QOFFSETSTRINGARRAY_P_H
41 #define QOFFSETSTRINGARRAY_P_H
42 
43 //
44 //  W A R N I N G
45 //  -------------
46 //
47 // This file is not part of the Qt API.  It exists purely as an
48 // implementation detail.  This header file may change from version to
49 // version without notice, or even be removed.
50 //
51 // We mean it.
52 //
53 
54 #include "private/qglobal_p.h"
55 
56 #include <tuple>
57 #include <array>
58 #include <limits>
59 
60 QT_BEGIN_NAMESPACE
61 
62 namespace QtPrivate {
63 template<int N, int O, int I, int ... Idx>
64 struct OffsetSequenceHelper : OffsetSequenceHelper<N - 1, O + I, Idx..., O> { };
65 
66 template<int Last, int I, int S, int ... Idx>
67 struct OffsetSequenceHelper<1, Last, I, S, Idx...> : IndexesList<Last + I, Idx..., Last>
68 {
69     static const constexpr auto Length = Last + I;
70     using Type = typename std::conditional<
71         Last <= std::numeric_limits<quint8>::max(),
72         quint8,
73         typename std::conditional<
74             Last <= std::numeric_limits<quint16>::max(),
75             quint16,
76             int>::type
77         >::type;
78 };
79 
80 template<int ... Idx>
81 struct OffsetSequence : OffsetSequenceHelper<sizeof ... (Idx), 0, Idx..., 0> { };
82 
83 template<int N>
84 struct StaticString
85 {
86     const char data[N];
87 };
88 
89 
90 template<>
91 struct StaticString<0>
92 {
93     static constexpr int size() noexcept
94     {
95         return 0;
96     }
97 };
98 
99 template<typename, typename>
100 struct StaticStringBuilder;
101 
102 template<int ... I1, int ... I2>
103 struct StaticStringBuilder<IndexesList<I1...>, IndexesList<I2...>>
104 {
105 
106 QT_WARNING_PUSH
107 QT_WARNING_DISABLE_MSVC(4100) // The formal parameter is not referenced in the body of the function.
108                               // The unreferenced parameter is ignored.
109                               // It happens when 'rs' is StaticString<0>
110     template<int N1, int N2>
111     static constexpr StaticString<N1 + N2> concatenate(
112         const char (&ls)[N1], const StaticString<N2> &rs) noexcept
113     {
114         return StaticString<N1 + N2>{{ls[I1]..., rs.data[I2]...}};
115     }
116 QT_WARNING_POP
117 };
118 
119 template<int Sum>
120 constexpr StaticString<0> staticString() noexcept
121 {
122     return StaticString<0>{};
123 }
124 
125 QT_WARNING_PUSH
126 QT_WARNING_DISABLE_MSVC(4503)
127 template<int Sum, int I, int ... Ix>
128 constexpr StaticString<Sum> staticString(const char (&s)[I], const char (&...sx)[Ix]) noexcept
129 {
130     return StaticStringBuilder<
131         makeIndexSequence<I>,
132         makeIndexSequence<Sum - I>>::concatenate(s, staticString<Sum - I>(sx...));
133 }
134 QT_WARNING_POP
135 } // namespace QtPrivate
136 
137 template<typename T, int SizeString, int SizeOffsets>
138 class QOffsetStringArray
139 {
140 public:
141     using Type = T;
142 
143     template<int ... Ox>
144     constexpr QOffsetStringArray(const QtPrivate::StaticString<SizeString> &str,
145                                  QtPrivate::IndexesList<SizeString, Ox...>) noexcept
146         : m_string(str),
147           m_offsets{Ox...}
148     { }
149 
150     constexpr inline const char *operator[](const int index) const noexcept
151     {
152         return m_string.data + m_offsets[qBound(int(0), index, SizeOffsets - 1)];
153     }
154 
155     constexpr inline const char *at(const int index) const noexcept
156     {
157         return m_string.data + m_offsets[index];
158     }
159 
160     constexpr inline const char *str() const { return m_string.data; }
161     constexpr inline const T *offsets() const { return m_offsets; }
162     constexpr inline int count() const { return SizeOffsets; };
163 
164     static constexpr const auto sizeString = SizeString;
165     static constexpr const auto sizeOffsets = SizeOffsets;
166 
167 private:
168     QtPrivate::StaticString<SizeString> m_string;
169     const T m_offsets[SizeOffsets];
170 };
171 
172 template<typename T, int N, int ... Ox>
173 constexpr QOffsetStringArray<T, N, sizeof ... (Ox)> qOffsetStringArray(
174     const QtPrivate::StaticString<N> &string,
175     QtPrivate::IndexesList<N, Ox...> offsets) noexcept
176 {
177     return QOffsetStringArray<T, N, sizeof ... (Ox)>(
178                string,
179                offsets);
180 }
181 
182 template<int ... Nx>
183 struct QOffsetStringArrayRet
184 {
185     using Offsets = QtPrivate::OffsetSequence<Nx...>;
186     using Type = QOffsetStringArray<typename Offsets::Type, Offsets::Length, sizeof ... (Nx)>;
187 };
188 
189 template<int ... Nx>
190 constexpr auto qOffsetStringArray(const char (&...strings)[Nx]) noexcept -> typename QOffsetStringArrayRet<Nx...>::Type
191 {
192     using Offsets = QtPrivate::OffsetSequence<Nx...>;
193     return qOffsetStringArray<typename Offsets::Type>(
194             QtPrivate::staticString<Offsets::Length>(strings...), Offsets{});
195 }
196 
197 QT_END_NAMESPACE
198 
199 #endif // QOFFSETSTRINGARRAY_P_H
200