Coverage Report

Created: 2025-12-10 06:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wxwidgets/include/wx/unichar.h
Line
Count
Source
1
///////////////////////////////////////////////////////////////////////////////
2
// Name:        wx/unichar.h
3
// Purpose:     wxUniChar and wxUniCharRef classes
4
// Author:      Vaclav Slavik
5
// Created:     2007-03-19
6
// Copyright:   (c) 2007 REA Elektronik GmbH
7
// Licence:     wxWindows licence
8
///////////////////////////////////////////////////////////////////////////////
9
10
#ifndef _WX_UNICHAR_H_
11
#define _WX_UNICHAR_H_
12
13
#include "wx/defs.h"
14
#include "wx/chartype.h"
15
16
#include <string>
17
#include <utility>          // std::swap() which we specialize below
18
19
class WXDLLIMPEXP_FWD_BASE wxUniCharRef;
20
class WXDLLIMPEXP_FWD_BASE wxString;
21
22
// This class represents single Unicode character. It can be converted to
23
// and from char or wchar_t and implements commonly used character operations.
24
class WXDLLIMPEXP_BASE wxUniChar
25
{
26
public:
27
    // NB: this is not wchar_t on purpose, it needs to represent the entire
28
    //     Unicode code points range and wchar_t may be too small for that
29
    //     (e.g. on Win32 where wchar_t* is encoded in UTF-16)
30
    typedef wxUint32 value_type;
31
32
0
    wxUniChar() : m_value(0) {}
33
34
    // Create the character from 8bit character value encoded in the current
35
    // locale's charset.
36
4
    wxUniChar(char c) { m_value = From8bit(c); }
37
0
    wxUniChar(unsigned char c) { m_value = From8bit((char)c); }
38
39
#define wxUNICHAR_DEFINE_CTOR(type) \
40
0
    wxUniChar(type c) { m_value = (value_type)c; }
Unexecuted instantiation: wxUniChar::wxUniChar(short)
Unexecuted instantiation: wxUniChar::wxUniChar(unsigned short)
Unexecuted instantiation: wxUniChar::wxUniChar(int)
Unexecuted instantiation: wxUniChar::wxUniChar(unsigned int)
Unexecuted instantiation: wxUniChar::wxUniChar(long)
Unexecuted instantiation: wxUniChar::wxUniChar(unsigned long)
41
    wxDO_FOR_INT_TYPES(wxUNICHAR_DEFINE_CTOR)
42
#undef wxUNICHAR_DEFINE_CTOR
43
44
    wxUniChar(const wxUniCharRef& c);
45
46
    // Returns Unicode code point value of the character
47
0
    value_type GetValue() const { return m_value; }
48
49
#if wxUSE_UNICODE_UTF8
50
    // buffer for single UTF-8 character
51
    struct Utf8CharBuffer
52
    {
53
        char data[5];
54
        operator const char*() const { return data; }
55
    };
56
57
    // returns the character encoded as UTF-8
58
    // (NB: implemented in stringops.cpp)
59
    Utf8CharBuffer AsUTF8() const;
60
#endif // wxUSE_UNICODE_UTF8
61
62
    // Returns true if the character is an ASCII character:
63
0
    bool IsAscii() const { return m_value < 0x80; }
64
65
    // Returns true if the character is representable as a single byte in the
66
    // current locale encoding and return this byte in output argument c (which
67
    // must be non-null)
68
    bool GetAsChar(char *c) const
69
0
    {
70
0
        if ( !IsAscii() )
71
0
        {
72
0
#if !wxUSE_UTF8_LOCALE_ONLY
73
0
            if ( GetAsHi8bit(m_value, c) )
74
0
                return true;
75
0
#endif // !wxUSE_UTF8_LOCALE_ONLY
76
77
0
            return false;
78
0
        }
79
80
0
        *c = wx_truncate_cast(char, m_value);
81
0
        return true;
82
0
    }
83
84
    // Returns true if the character is a BMP character:
85
0
    static bool IsBMP(wxUint32 value) { return value < 0x10000; }
86
87
    // Returns true if the character is a supplementary character:
88
0
    static bool IsSupplementary(wxUint32 value) { return 0x10000 <= value && value < 0x110000; }
89
90
    // Returns the high surrogate code unit for the supplementary character
91
    static wxUint16 HighSurrogate(wxUint32 value)
92
0
    {
93
0
        wxASSERT_MSG(IsSupplementary(value), "wxUniChar::HighSurrogate() must be called on a supplementary character");
94
0
        return static_cast<wxUint16>(0xD800 | ((value - 0x10000) >> 10));
95
0
    }
96
97
    // Returns the low surrogate code unit for the supplementary character
98
    static wxUint16 LowSurrogate(wxUint32 value)
99
0
    {
100
0
        wxASSERT_MSG(IsSupplementary(value), "wxUniChar::LowSurrogate() must be called on a supplementary character");
101
0
        return static_cast<wxUint16>(0xDC00 | ((value - 0x10000) & 0x03FF));
102
0
    }
103
104
    // Returns true if the character is a BMP character:
105
0
    bool IsBMP() const { return IsBMP(m_value); }
106
107
    // Returns true if the character is a supplementary character:
108
0
    bool IsSupplementary() const { return IsSupplementary(m_value); }
109
110
    // Returns the high surrogate code unit for the supplementary character
111
0
    wxUint16 HighSurrogate() const { return HighSurrogate(m_value); }
112
113
    // Returns the low surrogate code unit for the supplementary character
114
0
    wxUint16 LowSurrogate() const { return LowSurrogate(m_value); }
115
116
    // Conversions to char and wchar_t types: all of those are needed to be
117
    // able to pass wxUniChars to various standard narrow and wide character
118
    // functions
119
0
    operator char() const { return To8bit(m_value); }
120
0
    operator unsigned char() const { return (unsigned char)To8bit(m_value); }
121
122
#define wxUNICHAR_DEFINE_OPERATOR_PAREN(type) \
123
0
    operator type() const { return (type)m_value; }
Unexecuted instantiation: wxUniChar::operator short() const
Unexecuted instantiation: wxUniChar::operator unsigned short() const
Unexecuted instantiation: wxUniChar::operator int() const
Unexecuted instantiation: wxUniChar::operator unsigned int() const
Unexecuted instantiation: wxUniChar::operator long() const
Unexecuted instantiation: wxUniChar::operator unsigned long() const
124
    wxDO_FOR_INT_TYPES(wxUNICHAR_DEFINE_OPERATOR_PAREN)
125
#undef wxUNICHAR_DEFINE_OPERATOR_PAREN
126
127
    // We need this operator for the "*p" part of expressions like "for (
128
    // const_iterator p = begin() + nStart; *p; ++p )". In this case,
129
    // compilation would fail without it because the conversion to bool would
130
    // be ambiguous (there are all these int types conversions...). (And adding
131
    // operator unspecified_bool_type() would only makes the ambiguity worse.)
132
0
    operator bool() const { return m_value != 0; }
133
0
    bool operator!() const { return !((bool)*this); }
134
135
    // And this one is needed by some (not all, but not using ifdefs makes the
136
    // code easier) compilers to parse "str[0] && *p" successfully
137
0
    bool operator&&(bool v) const { return (bool)*this && v; }
138
139
    // Assignment operators:
140
    wxUniChar& operator=(const wxUniCharRef& c);
141
0
    wxUniChar& operator=(char c) { m_value = From8bit(c); return *this; }
142
0
    wxUniChar& operator=(unsigned char c) { m_value = From8bit((char)c); return *this; }
143
144
#define wxUNICHAR_DEFINE_OPERATOR_EQUAL(type) \
145
0
    wxUniChar& operator=(type c) { m_value = (value_type)c; return *this; }
Unexecuted instantiation: wxUniChar::operator=(short)
Unexecuted instantiation: wxUniChar::operator=(unsigned short)
Unexecuted instantiation: wxUniChar::operator=(int)
Unexecuted instantiation: wxUniChar::operator=(unsigned int)
Unexecuted instantiation: wxUniChar::operator=(long)
Unexecuted instantiation: wxUniChar::operator=(unsigned long)
146
    wxDO_FOR_INT_TYPES(wxUNICHAR_DEFINE_OPERATOR_EQUAL)
147
#undef wxUNICHAR_DEFINE_OPERATOR_EQUAL
148
149
    // Comparison operators:
150
#define wxDEFINE_UNICHAR_CMP_WITH_INT(T, op) \
151
0
    bool operator op(T c) const { return m_value op (value_type)c; }
Unexecuted instantiation: wxUniChar::operator==(short) const
Unexecuted instantiation: wxUniChar::operator==(unsigned short) const
Unexecuted instantiation: wxUniChar::operator==(int) const
Unexecuted instantiation: wxUniChar::operator==(unsigned int) const
Unexecuted instantiation: wxUniChar::operator==(long) const
Unexecuted instantiation: wxUniChar::operator==(unsigned long) const
Unexecuted instantiation: wxUniChar::operator!=(short) const
Unexecuted instantiation: wxUniChar::operator!=(unsigned short) const
Unexecuted instantiation: wxUniChar::operator!=(int) const
Unexecuted instantiation: wxUniChar::operator!=(unsigned int) const
Unexecuted instantiation: wxUniChar::operator!=(long) const
Unexecuted instantiation: wxUniChar::operator!=(unsigned long) const
Unexecuted instantiation: wxUniChar::operator>=(short) const
Unexecuted instantiation: wxUniChar::operator>=(unsigned short) const
Unexecuted instantiation: wxUniChar::operator>=(int) const
Unexecuted instantiation: wxUniChar::operator>=(unsigned int) const
Unexecuted instantiation: wxUniChar::operator>=(long) const
Unexecuted instantiation: wxUniChar::operator>=(unsigned long) const
Unexecuted instantiation: wxUniChar::operator<=(short) const
Unexecuted instantiation: wxUniChar::operator<=(unsigned short) const
Unexecuted instantiation: wxUniChar::operator<=(int) const
Unexecuted instantiation: wxUniChar::operator<=(unsigned int) const
Unexecuted instantiation: wxUniChar::operator<=(long) const
Unexecuted instantiation: wxUniChar::operator<=(unsigned long) const
Unexecuted instantiation: wxUniChar::operator>(short) const
Unexecuted instantiation: wxUniChar::operator>(unsigned short) const
Unexecuted instantiation: wxUniChar::operator>(int) const
Unexecuted instantiation: wxUniChar::operator>(unsigned int) const
Unexecuted instantiation: wxUniChar::operator>(long) const
Unexecuted instantiation: wxUniChar::operator>(unsigned long) const
Unexecuted instantiation: wxUniChar::operator<(short) const
Unexecuted instantiation: wxUniChar::operator<(unsigned short) const
Unexecuted instantiation: wxUniChar::operator<(int) const
Unexecuted instantiation: wxUniChar::operator<(unsigned int) const
Unexecuted instantiation: wxUniChar::operator<(long) const
Unexecuted instantiation: wxUniChar::operator<(unsigned long) const
152
153
    // define the given comparison operator for all the types
154
#define wxDEFINE_UNICHAR_OPERATOR(op)                                         \
155
0
    bool operator op(const wxUniChar& c) const { return m_value op c.m_value; }\
Unexecuted instantiation: wxUniChar::operator==(wxUniChar const&) const
Unexecuted instantiation: wxUniChar::operator!=(wxUniChar const&) const
Unexecuted instantiation: wxUniChar::operator>=(wxUniChar const&) const
Unexecuted instantiation: wxUniChar::operator<=(wxUniChar const&) const
Unexecuted instantiation: wxUniChar::operator>(wxUniChar const&) const
Unexecuted instantiation: wxUniChar::operator<(wxUniChar const&) const
156
0
    bool operator op(char c) const { return m_value op From8bit(c); }         \
Unexecuted instantiation: wxUniChar::operator==(char) const
Unexecuted instantiation: wxUniChar::operator!=(char) const
Unexecuted instantiation: wxUniChar::operator>=(char) const
Unexecuted instantiation: wxUniChar::operator<=(char) const
Unexecuted instantiation: wxUniChar::operator>(char) const
Unexecuted instantiation: wxUniChar::operator<(char) const
157
0
    bool operator op(unsigned char c) const { return m_value op From8bit((char)c); } \
Unexecuted instantiation: wxUniChar::operator==(unsigned char) const
Unexecuted instantiation: wxUniChar::operator!=(unsigned char) const
Unexecuted instantiation: wxUniChar::operator>=(unsigned char) const
Unexecuted instantiation: wxUniChar::operator<=(unsigned char) const
Unexecuted instantiation: wxUniChar::operator>(unsigned char) const
Unexecuted instantiation: wxUniChar::operator<(unsigned char) const
158
    wxDO_FOR_INT_TYPES_1(wxDEFINE_UNICHAR_CMP_WITH_INT, op)
159
160
    wxFOR_ALL_COMPARISONS(wxDEFINE_UNICHAR_OPERATOR)
161
162
#undef wxDEFINE_UNICHAR_OPERATOR
163
#undef wxDEFINE_UNICHAR_CMP_WITH_INT
164
165
    wxDEFINE_COMPARISONS_BY_REV(char, const wxUniChar&)
166
    wxDEFINE_COMPARISONS_BY_REV(wchar_t, const wxUniChar&)
167
168
    // this is needed for expressions like 'Z'-c
169
0
    int operator-(const wxUniChar& c) const { return m_value - c.m_value; }
170
0
    int operator-(char c) const { return m_value - From8bit(c); }
171
0
    int operator-(unsigned char c) const { return m_value - From8bit((char)c); }
172
0
    int operator-(wchar_t c) const { return m_value - (value_type)c; }
173
174
175
private:
176
    // notice that we implement these functions inline for 7-bit ASCII
177
    // characters purely for performance reasons
178
    static value_type From8bit(char c)
179
4
    {
180
4
        if ( (unsigned char)c < 0x80 )
181
4
            return c;
182
183
0
        return FromHi8bit(c);
184
4
    }
185
186
    static char To8bit(value_type c)
187
0
    {
188
0
        if ( c < 0x80 )
189
0
            return wx_truncate_cast(char, c);
190
191
0
        return ToHi8bit(c);
192
0
    }
193
194
    // helpers of the functions above called to deal with non-ASCII chars
195
    static value_type FromHi8bit(char c);
196
    static char ToHi8bit(value_type v);
197
    static bool GetAsHi8bit(value_type v, char *c);
198
199
private:
200
    value_type m_value;
201
};
202
203
204
// Writeable reference to a character in wxString.
205
//
206
// This class can be used in the same way wxChar is used, except that changing
207
// its value updates the underlying string object.
208
class WXDLLIMPEXP_BASE wxUniCharRef
209
{
210
private:
211
#if wxUSE_UNICODE_UTF8
212
    typedef std::string::iterator iterator;
213
#else
214
    typedef std::wstring::iterator iterator;
215
#endif
216
217
    // create the reference
218
#if wxUSE_UNICODE_UTF8
219
    wxUniCharRef(wxString& str, iterator pos) : m_str(str), m_pos(pos) {}
220
#else
221
62.9k
    wxUniCharRef(iterator pos) : m_pos(pos) {}
222
#endif
223
224
public:
225
    // NB: we have to make this public, because we don't have wxString
226
    //     declaration available here and so can't declare wxString::iterator
227
    //     as friend; so at least don't use a ctor but a static function
228
    //     that must be used explicitly (this is more than using 'explicit'
229
    //     keyword on ctor!):
230
#if wxUSE_UNICODE_UTF8
231
    static wxUniCharRef CreateForString(wxString& str, iterator pos)
232
        { return wxUniCharRef(str, pos); }
233
#else
234
    static wxUniCharRef CreateForString(iterator pos)
235
62.9k
        { return wxUniCharRef(pos); }
236
#endif
237
238
0
    wxUniChar::value_type GetValue() const { return UniChar().GetValue(); }
239
240
#if wxUSE_UNICODE_UTF8
241
    wxUniChar::Utf8CharBuffer AsUTF8() const { return UniChar().AsUTF8(); }
242
#endif // wxUSE_UNICODE_UTF8
243
244
0
    bool IsAscii() const { return UniChar().IsAscii(); }
245
0
    bool GetAsChar(char *c) const { return UniChar().GetAsChar(c); }
246
247
0
    bool IsBMP() const { return UniChar().IsBMP(); }
248
0
    bool IsSupplementary() const { return UniChar().IsSupplementary(); }
249
0
    wxUint16 HighSurrogate() const { return UniChar().HighSurrogate(); }
250
0
    wxUint16 LowSurrogate() const { return UniChar().LowSurrogate(); }
251
252
    // Assignment operators:
253
#if wxUSE_UNICODE_UTF8
254
    wxUniCharRef& operator=(const wxUniChar& c);
255
#else
256
0
    wxUniCharRef& operator=(const wxUniChar& c) { *m_pos = c; return *this; }
257
#endif
258
259
    wxUniCharRef& operator=(const wxUniCharRef& c)
260
0
        { if (&c != this) *this = c.UniChar(); return *this; }
261
262
#ifdef wxHAS_MEMBER_DEFAULT
263
    wxUniCharRef(const wxUniCharRef&) = default;
264
#endif
265
266
#define wxUNICHAR_REF_DEFINE_OPERATOR_EQUAL(type) \
267
0
    wxUniCharRef& operator=(type c) { return *this = wxUniChar(c); }
Unexecuted instantiation: wxUniCharRef::operator=(char)
Unexecuted instantiation: wxUniCharRef::operator=(unsigned char)
Unexecuted instantiation: wxUniCharRef::operator=(short)
Unexecuted instantiation: wxUniCharRef::operator=(unsigned short)
Unexecuted instantiation: wxUniCharRef::operator=(int)
Unexecuted instantiation: wxUniCharRef::operator=(unsigned int)
Unexecuted instantiation: wxUniCharRef::operator=(long)
Unexecuted instantiation: wxUniCharRef::operator=(unsigned long)
268
    wxDO_FOR_CHAR_INT_TYPES(wxUNICHAR_REF_DEFINE_OPERATOR_EQUAL)
269
#undef wxUNICHAR_REF_DEFINE_OPERATOR_EQUAL
270
271
    // Conversions to the same types as wxUniChar is convertible too:
272
#define wxUNICHAR_REF_DEFINE_OPERATOR_PAREN(type) \
273
0
    operator type() const { return UniChar(); }
Unexecuted instantiation: wxUniCharRef::operator char() const
Unexecuted instantiation: wxUniCharRef::operator unsigned char() const
Unexecuted instantiation: wxUniCharRef::operator short() const
Unexecuted instantiation: wxUniCharRef::operator unsigned short() const
Unexecuted instantiation: wxUniCharRef::operator int() const
Unexecuted instantiation: wxUniCharRef::operator unsigned int() const
Unexecuted instantiation: wxUniCharRef::operator long() const
Unexecuted instantiation: wxUniCharRef::operator unsigned long() const
274
    wxDO_FOR_CHAR_INT_TYPES(wxUNICHAR_REF_DEFINE_OPERATOR_PAREN)
275
#undef wxUNICHAR_REF_DEFINE_OPERATOR_PAREN
276
277
    // see wxUniChar::operator bool etc. for explanation
278
0
    operator bool() const { return (bool)UniChar(); }
279
0
    bool operator!() const { return !UniChar(); }
280
0
    bool operator&&(bool v) const { return UniChar() && v; }
281
282
#define wxDEFINE_UNICHARREF_CMP_WITH_INT(T, op) \
283
0
    bool operator op(T c) const { return UniChar() op c; }
Unexecuted instantiation: wxUniCharRef::operator==(char) const
Unexecuted instantiation: wxUniCharRef::operator==(unsigned char) const
Unexecuted instantiation: wxUniCharRef::operator==(short) const
Unexecuted instantiation: wxUniCharRef::operator==(unsigned short) const
Unexecuted instantiation: wxUniCharRef::operator==(int) const
Unexecuted instantiation: wxUniCharRef::operator==(unsigned int) const
Unexecuted instantiation: wxUniCharRef::operator==(long) const
Unexecuted instantiation: wxUniCharRef::operator==(unsigned long) const
Unexecuted instantiation: wxUniCharRef::operator!=(char) const
Unexecuted instantiation: wxUniCharRef::operator!=(unsigned char) const
Unexecuted instantiation: wxUniCharRef::operator!=(short) const
Unexecuted instantiation: wxUniCharRef::operator!=(unsigned short) const
Unexecuted instantiation: wxUniCharRef::operator!=(int) const
Unexecuted instantiation: wxUniCharRef::operator!=(unsigned int) const
Unexecuted instantiation: wxUniCharRef::operator!=(long) const
Unexecuted instantiation: wxUniCharRef::operator!=(unsigned long) const
Unexecuted instantiation: wxUniCharRef::operator>=(char) const
Unexecuted instantiation: wxUniCharRef::operator>=(unsigned char) const
Unexecuted instantiation: wxUniCharRef::operator>=(short) const
Unexecuted instantiation: wxUniCharRef::operator>=(unsigned short) const
Unexecuted instantiation: wxUniCharRef::operator>=(int) const
Unexecuted instantiation: wxUniCharRef::operator>=(unsigned int) const
Unexecuted instantiation: wxUniCharRef::operator>=(long) const
Unexecuted instantiation: wxUniCharRef::operator>=(unsigned long) const
Unexecuted instantiation: wxUniCharRef::operator<=(char) const
Unexecuted instantiation: wxUniCharRef::operator<=(unsigned char) const
Unexecuted instantiation: wxUniCharRef::operator<=(short) const
Unexecuted instantiation: wxUniCharRef::operator<=(unsigned short) const
Unexecuted instantiation: wxUniCharRef::operator<=(int) const
Unexecuted instantiation: wxUniCharRef::operator<=(unsigned int) const
Unexecuted instantiation: wxUniCharRef::operator<=(long) const
Unexecuted instantiation: wxUniCharRef::operator<=(unsigned long) const
Unexecuted instantiation: wxUniCharRef::operator>(char) const
Unexecuted instantiation: wxUniCharRef::operator>(unsigned char) const
Unexecuted instantiation: wxUniCharRef::operator>(short) const
Unexecuted instantiation: wxUniCharRef::operator>(unsigned short) const
Unexecuted instantiation: wxUniCharRef::operator>(int) const
Unexecuted instantiation: wxUniCharRef::operator>(unsigned int) const
Unexecuted instantiation: wxUniCharRef::operator>(long) const
Unexecuted instantiation: wxUniCharRef::operator>(unsigned long) const
Unexecuted instantiation: wxUniCharRef::operator<(char) const
Unexecuted instantiation: wxUniCharRef::operator<(unsigned char) const
Unexecuted instantiation: wxUniCharRef::operator<(short) const
Unexecuted instantiation: wxUniCharRef::operator<(unsigned short) const
Unexecuted instantiation: wxUniCharRef::operator<(int) const
Unexecuted instantiation: wxUniCharRef::operator<(unsigned int) const
Unexecuted instantiation: wxUniCharRef::operator<(long) const
Unexecuted instantiation: wxUniCharRef::operator<(unsigned long) const
284
285
    // Comparison operators:
286
#define wxDEFINE_UNICHARREF_OPERATOR(op)                                      \
287
0
    bool operator op(const wxUniCharRef& c) const { return UniChar() op c.UniChar(); }\
Unexecuted instantiation: wxUniCharRef::operator==(wxUniCharRef const&) const
Unexecuted instantiation: wxUniCharRef::operator!=(wxUniCharRef const&) const
Unexecuted instantiation: wxUniCharRef::operator>=(wxUniCharRef const&) const
Unexecuted instantiation: wxUniCharRef::operator<=(wxUniCharRef const&) const
Unexecuted instantiation: wxUniCharRef::operator>(wxUniCharRef const&) const
Unexecuted instantiation: wxUniCharRef::operator<(wxUniCharRef const&) const
288
0
    bool operator op(const wxUniChar& c) const { return UniChar() op c; }     \
Unexecuted instantiation: wxUniCharRef::operator==(wxUniChar const&) const
Unexecuted instantiation: wxUniCharRef::operator!=(wxUniChar const&) const
Unexecuted instantiation: wxUniCharRef::operator>=(wxUniChar const&) const
Unexecuted instantiation: wxUniCharRef::operator<=(wxUniChar const&) const
Unexecuted instantiation: wxUniCharRef::operator>(wxUniChar const&) const
Unexecuted instantiation: wxUniCharRef::operator<(wxUniChar const&) const
289
    wxDO_FOR_CHAR_INT_TYPES_1(wxDEFINE_UNICHARREF_CMP_WITH_INT, op)
290
291
    wxFOR_ALL_COMPARISONS(wxDEFINE_UNICHARREF_OPERATOR)
292
293
#undef wxDEFINE_UNICHARREF_OPERATOR
294
#undef wxDEFINE_UNICHARREF_CMP_WITH_INT
295
296
    // Comparison operators for the case when wxUniChar(Ref) is the second
297
    // operand implemented in terms of member comparison functions
298
    wxDEFINE_COMPARISONS_BY_REV(char, const wxUniCharRef&)
299
    wxDEFINE_COMPARISONS_BY_REV(wchar_t, const wxUniCharRef&)
300
301
    wxDEFINE_COMPARISONS_BY_REV(const wxUniChar&, const wxUniCharRef&)
302
303
    // for expressions like c-'A':
304
0
    int operator-(const wxUniCharRef& c) const { return UniChar() - c.UniChar(); }
305
0
    int operator-(const wxUniChar& c) const { return UniChar() - c; }
306
0
    int operator-(char c) const { return UniChar() - c; }
307
0
    int operator-(unsigned char c) const { return UniChar() - c; }
308
0
    int operator-(wchar_t c) const { return UniChar() - c; }
309
0
    friend int operator-(char c1, const wxUniCharRef& c2) { return -(c2 - c1); }
310
0
    friend int operator-(const wxUniChar& c1, const wxUniCharRef& c2) { return -(c2 - c1); }
311
0
    friend int operator-(wchar_t c1, const wxUniCharRef& c2) { return -(c2 - c1); }
312
313
314
private:
315
#if wxUSE_UNICODE_UTF8
316
    wxUniChar UniChar() const;
317
#else
318
62.9k
    wxUniChar UniChar() const { return *m_pos; }
319
#endif
320
321
    friend class WXDLLIMPEXP_FWD_BASE wxUniChar;
322
323
private:
324
    // reference to the string and pointer to the character in string
325
#if wxUSE_UNICODE_UTF8
326
    wxString& m_str;
327
#endif
328
    iterator m_pos;
329
};
330
331
inline wxUniChar::wxUniChar(const wxUniCharRef& c)
332
44.4k
{
333
44.4k
    m_value = c.UniChar().m_value;
334
44.4k
}
335
336
inline wxUniChar& wxUniChar::operator=(const wxUniCharRef& c)
337
0
{
338
0
    m_value = c.UniChar().m_value;
339
0
    return *this;
340
0
}
341
342
// wxUniCharRef doesn't behave quite like a reference, notably because template
343
// deduction from wxUniCharRef doesn't yield wxUniChar as would have been the
344
// case if it were a real reference. This results in a number of problems and
345
// we can't fix all of them but we can at least provide a working swap() for
346
// it, instead of the default version which doesn't work because a "wrong" type
347
// is deduced.
348
namespace std
349
{
350
351
template <>
352
inline
353
void swap<wxUniCharRef>(wxUniCharRef& lhs, wxUniCharRef& rhs)
354
0
{
355
0
    if ( &lhs != &rhs )
356
0
    {
357
0
        // The use of wxUniChar here is the crucial difference: in the default
358
0
        // implementation, tmp would be wxUniCharRef and so assigning to lhs
359
0
        // would modify it too. Here we make a real copy, not affected by
360
0
        // changing lhs, instead.
361
0
        wxUniChar tmp = lhs;
362
0
        lhs = rhs;
363
0
        rhs = tmp;
364
0
    }
365
0
}
366
367
} // namespace std
368
369
// For std::iter_swap() to work with wxString::iterator, which uses
370
// wxUniCharRef as its reference type, we need to ensure that swap() works with
371
// wxUniCharRef objects by defining this overload.
372
//
373
// See https://bugs.llvm.org/show_bug.cgi?id=28559#c9
374
inline
375
void swap(wxUniCharRef&& lhs, wxUniCharRef&& rhs)
376
0
{
377
0
    wxUniChar tmp = lhs;
378
0
    lhs = rhs;
379
0
    rhs = tmp;
380
0
}
381
382
#endif /* _WX_UNICHAR_H_ */