git repos / blockattack-game

blame: source/code/Libs/include/utf8/core.h

normal view · raw

9f5ec0cc sago007 2015-12-05 08:01 1
// Copyright 2006 Nemanja Trifunovic
9f5ec0cc sago007 2015-12-05 08:01 2
9f5ec0cc sago007 2015-12-05 08:01 3
/*
9f5ec0cc sago007 2015-12-05 08:01 4
Permission is hereby granted, free of charge, to any person or organization
9f5ec0cc sago007 2015-12-05 08:01 5
obtaining a copy of the software and accompanying documentation covered by
9f5ec0cc sago007 2015-12-05 08:01 6
this license (the "Software") to use, reproduce, display, distribute,
9f5ec0cc sago007 2015-12-05 08:01 7
execute, and transmit the Software, and to prepare derivative works of the
9f5ec0cc sago007 2015-12-05 08:01 8
Software, and to permit third-parties to whom the Software is furnished to
9f5ec0cc sago007 2015-12-05 08:01 9
do so, all subject to the following:
9f5ec0cc sago007 2015-12-05 08:01 10
9f5ec0cc sago007 2015-12-05 08:01 11
The copyright notices in the Software and this entire statement, including
9f5ec0cc sago007 2015-12-05 08:01 12
the above license grant, this restriction and the following disclaimer,
9f5ec0cc sago007 2015-12-05 08:01 13
must be included in all copies of the Software, in whole or in part, and
9f5ec0cc sago007 2015-12-05 08:01 14
all derivative works of the Software, unless such copies or derivative
9f5ec0cc sago007 2015-12-05 08:01 15
works are solely in the form of machine-executable object code generated by
9f5ec0cc sago007 2015-12-05 08:01 16
a source language processor.
9f5ec0cc sago007 2015-12-05 08:01 17
9f5ec0cc sago007 2015-12-05 08:01 18
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
9f5ec0cc sago007 2015-12-05 08:01 19
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9f5ec0cc sago007 2015-12-05 08:01 20
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
9f5ec0cc sago007 2015-12-05 08:01 21
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
9f5ec0cc sago007 2015-12-05 08:01 22
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
9f5ec0cc sago007 2015-12-05 08:01 23
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
9f5ec0cc sago007 2015-12-05 08:01 24
DEALINGS IN THE SOFTWARE.
9f5ec0cc sago007 2015-12-05 08:01 25
*/
9f5ec0cc sago007 2015-12-05 08:01 26
9f5ec0cc sago007 2015-12-05 08:01 27
9f5ec0cc sago007 2015-12-05 08:01 28
#ifndef UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
9f5ec0cc sago007 2015-12-05 08:01 29
#define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
9f5ec0cc sago007 2015-12-05 08:01 30
9f5ec0cc sago007 2015-12-05 08:01 31
#include <iterator>
dbf0fff9 Poul Sander 2025-09-18 18:25 32
#include <cstring>
dbf0fff9 Poul Sander 2025-09-18 18:25 33
#include <string>
dbf0fff9 Poul Sander 2025-09-18 18:25 34
dbf0fff9 Poul Sander 2025-09-18 18:25 35
// Determine the C++ standard version.
dbf0fff9 Poul Sander 2025-09-18 18:25 36
// If the user defines UTF_CPP_CPLUSPLUS, use that.
dbf0fff9 Poul Sander 2025-09-18 18:25 37
// Otherwise, trust the unreliable predefined macro __cplusplus
dbf0fff9 Poul Sander 2025-09-18 18:25 38
dbf0fff9 Poul Sander 2025-09-18 18:25 39
#if !defined UTF_CPP_CPLUSPLUS
dbf0fff9 Poul Sander 2025-09-18 18:25 40
    #define UTF_CPP_CPLUSPLUS __cplusplus
dbf0fff9 Poul Sander 2025-09-18 18:25 41
#endif
dbf0fff9 Poul Sander 2025-09-18 18:25 42
dbf0fff9 Poul Sander 2025-09-18 18:25 43
#if UTF_CPP_CPLUSPLUS >= 201103L // C++ 11 or later
dbf0fff9 Poul Sander 2025-09-18 18:25 44
    #define UTF_CPP_OVERRIDE override
dbf0fff9 Poul Sander 2025-09-18 18:25 45
    #define UTF_CPP_NOEXCEPT noexcept
dbf0fff9 Poul Sander 2025-09-18 18:25 46
    #define UTF_CPP_STATIC_ASSERT(condition) static_assert(condition, "UTFCPP static assert");
dbf0fff9 Poul Sander 2025-09-18 18:25 47
#else // C++ 98/03
dbf0fff9 Poul Sander 2025-09-18 18:25 48
    #define UTF_CPP_OVERRIDE
dbf0fff9 Poul Sander 2025-09-18 18:25 49
    #define UTF_CPP_NOEXCEPT throw()
dbf0fff9 Poul Sander 2025-09-18 18:25 50
    // Simulate static_assert:
dbf0fff9 Poul Sander 2025-09-18 18:25 51
    template <bool Condition> struct StaticAssert {static void utf8_static_assert() {char static_assert_impl[Condition ? 1 : 0]; } };
dbf0fff9 Poul Sander 2025-09-18 18:25 52
    template <> struct StaticAssert<true> {static void utf8_static_assert() {}};
dbf0fff9 Poul Sander 2025-09-18 18:25 53
    #define UTF_CPP_STATIC_ASSERT(condition) StaticAssert<condition>::utf8_static_assert();
dbf0fff9 Poul Sander 2025-09-18 18:25 54
#endif // C++ 11 or later
dbf0fff9 Poul Sander 2025-09-18 18:25 55
9f5ec0cc sago007 2015-12-05 08:01 56
9f5ec0cc sago007 2015-12-05 08:01 57
namespace utf8
9f5ec0cc sago007 2015-12-05 08:01 58
{
dbf0fff9 Poul Sander 2025-09-18 18:25 59
// The typedefs for 8-bit, 16-bit and 32-bit code units
dbf0fff9 Poul Sander 2025-09-18 18:25 60
#if UTF_CPP_CPLUSPLUS >= 201103L // C++ 11 or later
dbf0fff9 Poul Sander 2025-09-18 18:25 61
    #if UTF_CPP_CPLUSPLUS >= 202002L // C++ 20 or later
dbf0fff9 Poul Sander 2025-09-18 18:25 62
        typedef char8_t         utfchar8_t;
dbf0fff9 Poul Sander 2025-09-18 18:25 63
    #else // C++ 11/14/17
dbf0fff9 Poul Sander 2025-09-18 18:25 64
        typedef unsigned char   utfchar8_t;
dbf0fff9 Poul Sander 2025-09-18 18:25 65
    #endif
dbf0fff9 Poul Sander 2025-09-18 18:25 66
    typedef char16_t        utfchar16_t;
dbf0fff9 Poul Sander 2025-09-18 18:25 67
    typedef char32_t        utfchar32_t;
dbf0fff9 Poul Sander 2025-09-18 18:25 68
#else // C++ 98/03
dbf0fff9 Poul Sander 2025-09-18 18:25 69
    typedef unsigned char   utfchar8_t;
dbf0fff9 Poul Sander 2025-09-18 18:25 70
    typedef unsigned short  utfchar16_t;
dbf0fff9 Poul Sander 2025-09-18 18:25 71
    typedef unsigned int    utfchar32_t;
dbf0fff9 Poul Sander 2025-09-18 18:25 72
#endif // C++ 11 or later
9f5ec0cc sago007 2015-12-05 08:01 73
9f5ec0cc sago007 2015-12-05 08:01 74
// Helper code - not intended to be directly called by the library users. May be changed at any time
9f5ec0cc sago007 2015-12-05 08:01 75
namespace internal
9f5ec0cc sago007 2015-12-05 08:01 76
{
9f5ec0cc sago007 2015-12-05 08:01 77
    // Unicode constants
9f5ec0cc sago007 2015-12-05 08:01 78
    // Leading (high) surrogates: 0xd800 - 0xdbff
9f5ec0cc sago007 2015-12-05 08:01 79
    // Trailing (low) surrogates: 0xdc00 - 0xdfff
dbf0fff9 Poul Sander 2025-09-18 18:25 80
    const utfchar16_t LEAD_SURROGATE_MIN  = 0xd800u;
dbf0fff9 Poul Sander 2025-09-18 18:25 81
    const utfchar16_t LEAD_SURROGATE_MAX  = 0xdbffu;
dbf0fff9 Poul Sander 2025-09-18 18:25 82
    const utfchar16_t TRAIL_SURROGATE_MIN = 0xdc00u;
dbf0fff9 Poul Sander 2025-09-18 18:25 83
    const utfchar16_t TRAIL_SURROGATE_MAX = 0xdfffu;
dbf0fff9 Poul Sander 2025-09-18 18:25 84
    const utfchar16_t LEAD_OFFSET         = 0xd7c0u;       // LEAD_SURROGATE_MIN - (0x10000 >> 10)
dbf0fff9 Poul Sander 2025-09-18 18:25 85
    const utfchar32_t SURROGATE_OFFSET    = 0xfca02400u;   // 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN
9f5ec0cc sago007 2015-12-05 08:01 86
9f5ec0cc sago007 2015-12-05 08:01 87
    // Maximum valid value for a Unicode code point
dbf0fff9 Poul Sander 2025-09-18 18:25 88
    const utfchar32_t CODE_POINT_MAX      = 0x0010ffffu;
9f5ec0cc sago007 2015-12-05 08:01 89
9f5ec0cc sago007 2015-12-05 08:01 90
    template<typename octet_type>
dbf0fff9 Poul Sander 2025-09-18 18:25 91
    inline utfchar8_t mask8(octet_type oc)
9f5ec0cc sago007 2015-12-05 08:01 92
    {
dbf0fff9 Poul Sander 2025-09-18 18:25 93
        return static_cast<utfchar8_t>(0xff & oc);
9f5ec0cc sago007 2015-12-05 08:01 94
    }
dbf0fff9 Poul Sander 2025-09-18 18:25 95
9f5ec0cc sago007 2015-12-05 08:01 96
    template<typename u16_type>
dbf0fff9 Poul Sander 2025-09-18 18:25 97
    inline utfchar16_t mask16(u16_type oc)
9f5ec0cc sago007 2015-12-05 08:01 98
    {
dbf0fff9 Poul Sander 2025-09-18 18:25 99
        return static_cast<utfchar16_t>(0xffff & oc);
9f5ec0cc sago007 2015-12-05 08:01 100
    }
dbf0fff9 Poul Sander 2025-09-18 18:25 101
9f5ec0cc sago007 2015-12-05 08:01 102
    template<typename octet_type>
9f5ec0cc sago007 2015-12-05 08:01 103
    inline bool is_trail(octet_type oc)
9f5ec0cc sago007 2015-12-05 08:01 104
    {
9f5ec0cc sago007 2015-12-05 08:01 105
        return ((utf8::internal::mask8(oc) >> 6) == 0x2);
9f5ec0cc sago007 2015-12-05 08:01 106
    }
9f5ec0cc sago007 2015-12-05 08:01 107
dbf0fff9 Poul Sander 2025-09-18 18:25 108
    inline bool is_lead_surrogate(utfchar32_t cp)
9f5ec0cc sago007 2015-12-05 08:01 109
    {
dbf0fff9 Poul Sander 2025-09-18 18:25 110
        return (cp >= static_cast<utfchar32_t>(LEAD_SURROGATE_MIN) && cp <= static_cast<utfchar32_t>(LEAD_SURROGATE_MAX));
9f5ec0cc sago007 2015-12-05 08:01 111
    }
9f5ec0cc sago007 2015-12-05 08:01 112
dbf0fff9 Poul Sander 2025-09-18 18:25 113
    inline bool is_trail_surrogate(utfchar32_t cp)
9f5ec0cc sago007 2015-12-05 08:01 114
    {
dbf0fff9 Poul Sander 2025-09-18 18:25 115
        return (cp >= static_cast<utfchar32_t>(TRAIL_SURROGATE_MIN) && cp <= static_cast<utfchar32_t>(TRAIL_SURROGATE_MAX));
9f5ec0cc sago007 2015-12-05 08:01 116
    }
9f5ec0cc sago007 2015-12-05 08:01 117
dbf0fff9 Poul Sander 2025-09-18 18:25 118
    inline bool is_surrogate(utfchar32_t cp)
9f5ec0cc sago007 2015-12-05 08:01 119
    {
dbf0fff9 Poul Sander 2025-09-18 18:25 120
        return (cp >= static_cast<utfchar32_t>(LEAD_SURROGATE_MIN) && cp <= static_cast<utfchar32_t>(TRAIL_SURROGATE_MAX));
9f5ec0cc sago007 2015-12-05 08:01 121
    }
9f5ec0cc sago007 2015-12-05 08:01 122
dbf0fff9 Poul Sander 2025-09-18 18:25 123
    inline bool is_code_point_valid(utfchar32_t cp)
9f5ec0cc sago007 2015-12-05 08:01 124
    {
9f5ec0cc sago007 2015-12-05 08:01 125
        return (cp <= CODE_POINT_MAX && !utf8::internal::is_surrogate(cp));
9f5ec0cc sago007 2015-12-05 08:01 126
    }
9f5ec0cc sago007 2015-12-05 08:01 127
dbf0fff9 Poul Sander 2025-09-18 18:25 128
    inline bool is_in_bmp(utfchar32_t cp)
dbf0fff9 Poul Sander 2025-09-18 18:25 129
    {
dbf0fff9 Poul Sander 2025-09-18 18:25 130
        return cp < utfchar32_t(0x10000);
dbf0fff9 Poul Sander 2025-09-18 18:25 131
    }
dbf0fff9 Poul Sander 2025-09-18 18:25 132
9f5ec0cc sago007 2015-12-05 08:01 133
    template <typename octet_iterator>
dbf0fff9 Poul Sander 2025-09-18 18:25 134
    int sequence_length(octet_iterator lead_it)
9f5ec0cc sago007 2015-12-05 08:01 135
    {
dbf0fff9 Poul Sander 2025-09-18 18:25 136
        const utfchar8_t lead = utf8::internal::mask8(*lead_it);
9f5ec0cc sago007 2015-12-05 08:01 137
        if (lead < 0x80)
9f5ec0cc sago007 2015-12-05 08:01 138
            return 1;
9f5ec0cc sago007 2015-12-05 08:01 139
        else if ((lead >> 5) == 0x6)
9f5ec0cc sago007 2015-12-05 08:01 140
            return 2;
9f5ec0cc sago007 2015-12-05 08:01 141
        else if ((lead >> 4) == 0xe)
9f5ec0cc sago007 2015-12-05 08:01 142
            return 3;
9f5ec0cc sago007 2015-12-05 08:01 143
        else if ((lead >> 3) == 0x1e)
9f5ec0cc sago007 2015-12-05 08:01 144
            return 4;
9f5ec0cc sago007 2015-12-05 08:01 145
        else
9f5ec0cc sago007 2015-12-05 08:01 146
            return 0;
9f5ec0cc sago007 2015-12-05 08:01 147
    }
9f5ec0cc sago007 2015-12-05 08:01 148
dbf0fff9 Poul Sander 2025-09-18 18:25 149
    inline bool is_overlong_sequence(utfchar32_t cp, int length)
9f5ec0cc sago007 2015-12-05 08:01 150
    {
9f5ec0cc sago007 2015-12-05 08:01 151
        if (cp < 0x80) {
dbf0fff9 Poul Sander 2025-09-18 18:25 152
            if (length != 1)
9f5ec0cc sago007 2015-12-05 08:01 153
                return true;
9f5ec0cc sago007 2015-12-05 08:01 154
        }
9f5ec0cc sago007 2015-12-05 08:01 155
        else if (cp < 0x800) {
dbf0fff9 Poul Sander 2025-09-18 18:25 156
            if (length != 2)
9f5ec0cc sago007 2015-12-05 08:01 157
                return true;
9f5ec0cc sago007 2015-12-05 08:01 158
        }
9f5ec0cc sago007 2015-12-05 08:01 159
        else if (cp < 0x10000) {
dbf0fff9 Poul Sander 2025-09-18 18:25 160
            if (length != 3)
9f5ec0cc sago007 2015-12-05 08:01 161
                return true;
9f5ec0cc sago007 2015-12-05 08:01 162
        }
9f5ec0cc sago007 2015-12-05 08:01 163
        return false;
9f5ec0cc sago007 2015-12-05 08:01 164
    }
9f5ec0cc sago007 2015-12-05 08:01 165
9f5ec0cc sago007 2015-12-05 08:01 166
    enum utf_error {UTF8_OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT};
9f5ec0cc sago007 2015-12-05 08:01 167
9f5ec0cc sago007 2015-12-05 08:01 168
    /// Helper for get_sequence_x
9f5ec0cc sago007 2015-12-05 08:01 169
    template <typename octet_iterator>
dbf0fff9 Poul Sander 2025-09-18 18:25 170
    utf_error increase_safely(octet_iterator& it, const octet_iterator end)
9f5ec0cc sago007 2015-12-05 08:01 171
    {
9f5ec0cc sago007 2015-12-05 08:01 172
        if (++it == end)
9f5ec0cc sago007 2015-12-05 08:01 173
            return NOT_ENOUGH_ROOM;
9f5ec0cc sago007 2015-12-05 08:01 174
9f5ec0cc sago007 2015-12-05 08:01 175
        if (!utf8::internal::is_trail(*it))
9f5ec0cc sago007 2015-12-05 08:01 176
            return INCOMPLETE_SEQUENCE;
dbf0fff9 Poul Sander 2025-09-18 18:25 177
9f5ec0cc sago007 2015-12-05 08:01 178
        return UTF8_OK;
9f5ec0cc sago007 2015-12-05 08:01 179
    }
9f5ec0cc sago007 2015-12-05 08:01 180
dbf0fff9 Poul Sander 2025-09-18 18:25 181
    #define UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(IT, END) {utf_error ret = increase_safely(IT, END); if (ret != UTF8_OK) return ret;}
9f5ec0cc sago007 2015-12-05 08:01 182
9f5ec0cc sago007 2015-12-05 08:01 183
    /// get_sequence_x functions decode utf-8 sequences of the length x
9f5ec0cc sago007 2015-12-05 08:01 184
    template <typename octet_iterator>
dbf0fff9 Poul Sander 2025-09-18 18:25 185
    utf_error get_sequence_1(octet_iterator& it, octet_iterator end, utfchar32_t& code_point)
9f5ec0cc sago007 2015-12-05 08:01 186
    {
9f5ec0cc sago007 2015-12-05 08:01 187
        if (it == end)
9f5ec0cc sago007 2015-12-05 08:01 188
            return NOT_ENOUGH_ROOM;
9f5ec0cc sago007 2015-12-05 08:01 189
dbf0fff9 Poul Sander 2025-09-18 18:25 190
        code_point = static_cast<utfchar32_t>(utf8::internal::mask8(*it));
9f5ec0cc sago007 2015-12-05 08:01 191
9f5ec0cc sago007 2015-12-05 08:01 192
        return UTF8_OK;
9f5ec0cc sago007 2015-12-05 08:01 193
    }
9f5ec0cc sago007 2015-12-05 08:01 194
9f5ec0cc sago007 2015-12-05 08:01 195
    template <typename octet_iterator>
dbf0fff9 Poul Sander 2025-09-18 18:25 196
    utf_error get_sequence_2(octet_iterator& it, octet_iterator end, utfchar32_t& code_point)
9f5ec0cc sago007 2015-12-05 08:01 197
    {
dbf0fff9 Poul Sander 2025-09-18 18:25 198
        if (it == end)
9f5ec0cc sago007 2015-12-05 08:01 199
            return NOT_ENOUGH_ROOM;
dbf0fff9 Poul Sander 2025-09-18 18:25 200
dbf0fff9 Poul Sander 2025-09-18 18:25 201
        code_point = static_cast<utfchar32_t>(utf8::internal::mask8(*it));
9f5ec0cc sago007 2015-12-05 08:01 202
9f5ec0cc sago007 2015-12-05 08:01 203
        UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
9f5ec0cc sago007 2015-12-05 08:01 204
9f5ec0cc sago007 2015-12-05 08:01 205
        code_point = ((code_point << 6) & 0x7ff) + ((*it) & 0x3f);
9f5ec0cc sago007 2015-12-05 08:01 206
9f5ec0cc sago007 2015-12-05 08:01 207
        return UTF8_OK;
9f5ec0cc sago007 2015-12-05 08:01 208
    }
9f5ec0cc sago007 2015-12-05 08:01 209
9f5ec0cc sago007 2015-12-05 08:01 210
    template <typename octet_iterator>
dbf0fff9 Poul Sander 2025-09-18 18:25 211
    utf_error get_sequence_3(octet_iterator& it, octet_iterator end, utfchar32_t& code_point)
9f5ec0cc sago007 2015-12-05 08:01 212
    {
9f5ec0cc sago007 2015-12-05 08:01 213
        if (it == end)
9f5ec0cc sago007 2015-12-05 08:01 214
            return NOT_ENOUGH_ROOM;
dbf0fff9 Poul Sander 2025-09-18 18:25 215
dbf0fff9 Poul Sander 2025-09-18 18:25 216
        code_point = static_cast<utfchar32_t>(utf8::internal::mask8(*it));
9f5ec0cc sago007 2015-12-05 08:01 217
9f5ec0cc sago007 2015-12-05 08:01 218
        UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
9f5ec0cc sago007 2015-12-05 08:01 219
9f5ec0cc sago007 2015-12-05 08:01 220
        code_point = ((code_point << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff);
9f5ec0cc sago007 2015-12-05 08:01 221
9f5ec0cc sago007 2015-12-05 08:01 222
        UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
9f5ec0cc sago007 2015-12-05 08:01 223
dbf0fff9 Poul Sander 2025-09-18 18:25 224
        code_point = static_cast<utfchar32_t>(code_point + ((*it) & 0x3f));
9f5ec0cc sago007 2015-12-05 08:01 225
9f5ec0cc sago007 2015-12-05 08:01 226
        return UTF8_OK;
9f5ec0cc sago007 2015-12-05 08:01 227
    }
9f5ec0cc sago007 2015-12-05 08:01 228
9f5ec0cc sago007 2015-12-05 08:01 229
    template <typename octet_iterator>
dbf0fff9 Poul Sander 2025-09-18 18:25 230
    utf_error get_sequence_4(octet_iterator& it, octet_iterator end, utfchar32_t& code_point)
9f5ec0cc sago007 2015-12-05 08:01 231
    {
9f5ec0cc sago007 2015-12-05 08:01 232
        if (it == end)
9f5ec0cc sago007 2015-12-05 08:01 233
           return NOT_ENOUGH_ROOM;
9f5ec0cc sago007 2015-12-05 08:01 234
dbf0fff9 Poul Sander 2025-09-18 18:25 235
        code_point = static_cast<utfchar32_t>(utf8::internal::mask8(*it));
9f5ec0cc sago007 2015-12-05 08:01 236
9f5ec0cc sago007 2015-12-05 08:01 237
        UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
9f5ec0cc sago007 2015-12-05 08:01 238
9f5ec0cc sago007 2015-12-05 08:01 239
        code_point = ((code_point << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff);
9f5ec0cc sago007 2015-12-05 08:01 240
9f5ec0cc sago007 2015-12-05 08:01 241
        UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
9f5ec0cc sago007 2015-12-05 08:01 242
dbf0fff9 Poul Sander 2025-09-18 18:25 243
        code_point = static_cast<utfchar32_t>(code_point + ((utf8::internal::mask8(*it) << 6) & 0xfff));
9f5ec0cc sago007 2015-12-05 08:01 244
9f5ec0cc sago007 2015-12-05 08:01 245
        UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
9f5ec0cc sago007 2015-12-05 08:01 246
dbf0fff9 Poul Sander 2025-09-18 18:25 247
        code_point = static_cast<utfchar32_t>(code_point + ((*it) & 0x3f));
9f5ec0cc sago007 2015-12-05 08:01 248
9f5ec0cc sago007 2015-12-05 08:01 249
        return UTF8_OK;
9f5ec0cc sago007 2015-12-05 08:01 250
    }
9f5ec0cc sago007 2015-12-05 08:01 251
9f5ec0cc sago007 2015-12-05 08:01 252
    #undef UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR
9f5ec0cc sago007 2015-12-05 08:01 253
9f5ec0cc sago007 2015-12-05 08:01 254
    template <typename octet_iterator>
dbf0fff9 Poul Sander 2025-09-18 18:25 255
    utf_error validate_next(octet_iterator& it, octet_iterator end, utfchar32_t& code_point)
9f5ec0cc sago007 2015-12-05 08:01 256
    {
dbf0fff9 Poul Sander 2025-09-18 18:25 257
        if (it == end)
dbf0fff9 Poul Sander 2025-09-18 18:25 258
            return NOT_ENOUGH_ROOM;
dbf0fff9 Poul Sander 2025-09-18 18:25 259
9f5ec0cc sago007 2015-12-05 08:01 260
        // Save the original value of it so we can go back in case of failure
9f5ec0cc sago007 2015-12-05 08:01 261
        // Of course, it does not make much sense with i.e. stream iterators
9f5ec0cc sago007 2015-12-05 08:01 262
        octet_iterator original_it = it;
9f5ec0cc sago007 2015-12-05 08:01 263
dbf0fff9 Poul Sander 2025-09-18 18:25 264
        utfchar32_t cp = 0;
9f5ec0cc sago007 2015-12-05 08:01 265
        // Determine the sequence length based on the lead octet
dbf0fff9 Poul Sander 2025-09-18 18:25 266
        const int length = utf8::internal::sequence_length(it);
9f5ec0cc sago007 2015-12-05 08:01 267
9f5ec0cc sago007 2015-12-05 08:01 268
        // Get trail octets and calculate the code point
9f5ec0cc sago007 2015-12-05 08:01 269
        utf_error err = UTF8_OK;
9f5ec0cc sago007 2015-12-05 08:01 270
        switch (length) {
dbf0fff9 Poul Sander 2025-09-18 18:25 271
            case 0:
9f5ec0cc sago007 2015-12-05 08:01 272
                return INVALID_LEAD;
9f5ec0cc sago007 2015-12-05 08:01 273
            case 1:
9f5ec0cc sago007 2015-12-05 08:01 274
                err = utf8::internal::get_sequence_1(it, end, cp);
9f5ec0cc sago007 2015-12-05 08:01 275
                break;
9f5ec0cc sago007 2015-12-05 08:01 276
            case 2:
9f5ec0cc sago007 2015-12-05 08:01 277
                err = utf8::internal::get_sequence_2(it, end, cp);
9f5ec0cc sago007 2015-12-05 08:01 278
            break;
9f5ec0cc sago007 2015-12-05 08:01 279
            case 3:
9f5ec0cc sago007 2015-12-05 08:01 280
                err = utf8::internal::get_sequence_3(it, end, cp);
9f5ec0cc sago007 2015-12-05 08:01 281
            break;
9f5ec0cc sago007 2015-12-05 08:01 282
            case 4:
9f5ec0cc sago007 2015-12-05 08:01 283
                err = utf8::internal::get_sequence_4(it, end, cp);
9f5ec0cc sago007 2015-12-05 08:01 284
            break;
9f5ec0cc sago007 2015-12-05 08:01 285
        }
9f5ec0cc sago007 2015-12-05 08:01 286
9f5ec0cc sago007 2015-12-05 08:01 287
        if (err == UTF8_OK) {
9f5ec0cc sago007 2015-12-05 08:01 288
            // Decoding succeeded. Now, security checks...
9f5ec0cc sago007 2015-12-05 08:01 289
            if (utf8::internal::is_code_point_valid(cp)) {
9f5ec0cc sago007 2015-12-05 08:01 290
                if (!utf8::internal::is_overlong_sequence(cp, length)){
9f5ec0cc sago007 2015-12-05 08:01 291
                    // Passed! Return here.
9f5ec0cc sago007 2015-12-05 08:01 292
                    code_point = cp;
9f5ec0cc sago007 2015-12-05 08:01 293
                    ++it;
9f5ec0cc sago007 2015-12-05 08:01 294
                    return UTF8_OK;
9f5ec0cc sago007 2015-12-05 08:01 295
                }
9f5ec0cc sago007 2015-12-05 08:01 296
                else
9f5ec0cc sago007 2015-12-05 08:01 297
                    err = OVERLONG_SEQUENCE;
9f5ec0cc sago007 2015-12-05 08:01 298
            }
dbf0fff9 Poul Sander 2025-09-18 18:25 299
            else
9f5ec0cc sago007 2015-12-05 08:01 300
                err = INVALID_CODE_POINT;
9f5ec0cc sago007 2015-12-05 08:01 301
        }
9f5ec0cc sago007 2015-12-05 08:01 302
9f5ec0cc sago007 2015-12-05 08:01 303
        // Failure branch - restore the original value of the iterator
9f5ec0cc sago007 2015-12-05 08:01 304
        it = original_it;
9f5ec0cc sago007 2015-12-05 08:01 305
        return err;
9f5ec0cc sago007 2015-12-05 08:01 306
    }
9f5ec0cc sago007 2015-12-05 08:01 307
9f5ec0cc sago007 2015-12-05 08:01 308
    template <typename octet_iterator>
9f5ec0cc sago007 2015-12-05 08:01 309
    inline utf_error validate_next(octet_iterator& it, octet_iterator end) {
dbf0fff9 Poul Sander 2025-09-18 18:25 310
        utfchar32_t ignored;
9f5ec0cc sago007 2015-12-05 08:01 311
        return utf8::internal::validate_next(it, end, ignored);
9f5ec0cc sago007 2015-12-05 08:01 312
    }
9f5ec0cc sago007 2015-12-05 08:01 313
dbf0fff9 Poul Sander 2025-09-18 18:25 314
    template <typename word_iterator>
dbf0fff9 Poul Sander 2025-09-18 18:25 315
    utf_error validate_next16(word_iterator& it, word_iterator end, utfchar32_t& code_point)
dbf0fff9 Poul Sander 2025-09-18 18:25 316
    {
dbf0fff9 Poul Sander 2025-09-18 18:25 317
        // Make sure the iterator dereferences a large enough type
dbf0fff9 Poul Sander 2025-09-18 18:25 318
        typedef typename std::iterator_traits<word_iterator>::value_type word_type;
dbf0fff9 Poul Sander 2025-09-18 18:25 319
        UTF_CPP_STATIC_ASSERT(sizeof(word_type) >= sizeof(utfchar16_t));
dbf0fff9 Poul Sander 2025-09-18 18:25 320
        // Check the edge case:
dbf0fff9 Poul Sander 2025-09-18 18:25 321
        if (it == end)
dbf0fff9 Poul Sander 2025-09-18 18:25 322
            return NOT_ENOUGH_ROOM;
dbf0fff9 Poul Sander 2025-09-18 18:25 323
        // Save the original value of it so we can go back in case of failure
dbf0fff9 Poul Sander 2025-09-18 18:25 324
        // Of course, it does not make much sense with i.e. stream iterators
dbf0fff9 Poul Sander 2025-09-18 18:25 325
        word_iterator original_it = it;
dbf0fff9 Poul Sander 2025-09-18 18:25 326
dbf0fff9 Poul Sander 2025-09-18 18:25 327
        utf_error err = UTF8_OK;
dbf0fff9 Poul Sander 2025-09-18 18:25 328
dbf0fff9 Poul Sander 2025-09-18 18:25 329
        const utfchar16_t first_word = *it++;
dbf0fff9 Poul Sander 2025-09-18 18:25 330
        if (!is_surrogate(first_word)) {
dbf0fff9 Poul Sander 2025-09-18 18:25 331
            code_point = first_word;
dbf0fff9 Poul Sander 2025-09-18 18:25 332
            return UTF8_OK;
dbf0fff9 Poul Sander 2025-09-18 18:25 333
        }
dbf0fff9 Poul Sander 2025-09-18 18:25 334
        else {
dbf0fff9 Poul Sander 2025-09-18 18:25 335
            if (it == end)
dbf0fff9 Poul Sander 2025-09-18 18:25 336
                err = NOT_ENOUGH_ROOM;
dbf0fff9 Poul Sander 2025-09-18 18:25 337
            else if (is_lead_surrogate(first_word)) {
dbf0fff9 Poul Sander 2025-09-18 18:25 338
                const utfchar16_t second_word = *it++;
dbf0fff9 Poul Sander 2025-09-18 18:25 339
                if (is_trail_surrogate(static_cast<utfchar32_t>(second_word))) {
dbf0fff9 Poul Sander 2025-09-18 18:25 340
                    code_point = static_cast<utfchar32_t>(first_word << 10) +  static_cast<utfchar32_t>(second_word) + SURROGATE_OFFSET;
dbf0fff9 Poul Sander 2025-09-18 18:25 341
                    return UTF8_OK;
dbf0fff9 Poul Sander 2025-09-18 18:25 342
                } else
dbf0fff9 Poul Sander 2025-09-18 18:25 343
                    err = INCOMPLETE_SEQUENCE;
dbf0fff9 Poul Sander 2025-09-18 18:25 344
dbf0fff9 Poul Sander 2025-09-18 18:25 345
            } else {
dbf0fff9 Poul Sander 2025-09-18 18:25 346
                err = INVALID_LEAD;
dbf0fff9 Poul Sander 2025-09-18 18:25 347
            }
dbf0fff9 Poul Sander 2025-09-18 18:25 348
        }
dbf0fff9 Poul Sander 2025-09-18 18:25 349
        // error branch
dbf0fff9 Poul Sander 2025-09-18 18:25 350
        it = original_it;
dbf0fff9 Poul Sander 2025-09-18 18:25 351
        return err;
dbf0fff9 Poul Sander 2025-09-18 18:25 352
    }
dbf0fff9 Poul Sander 2025-09-18 18:25 353
dbf0fff9 Poul Sander 2025-09-18 18:25 354
    // Internal implementation of both checked and unchecked append() function
dbf0fff9 Poul Sander 2025-09-18 18:25 355
    // This function will be invoked by the overloads below, as they will know
dbf0fff9 Poul Sander 2025-09-18 18:25 356
    // the octet_type.
dbf0fff9 Poul Sander 2025-09-18 18:25 357
    template <typename octet_iterator, typename octet_type>
dbf0fff9 Poul Sander 2025-09-18 18:25 358
    octet_iterator append(utfchar32_t cp, octet_iterator result) {
dbf0fff9 Poul Sander 2025-09-18 18:25 359
        if (cp < 0x80)                        // one octet
dbf0fff9 Poul Sander 2025-09-18 18:25 360
            *(result++) = static_cast<octet_type>(cp);
dbf0fff9 Poul Sander 2025-09-18 18:25 361
        else if (cp < 0x800) {                // two octets
dbf0fff9 Poul Sander 2025-09-18 18:25 362
            *(result++) = static_cast<octet_type>((cp >> 6)          | 0xc0);
dbf0fff9 Poul Sander 2025-09-18 18:25 363
            *(result++) = static_cast<octet_type>((cp & 0x3f)        | 0x80);
dbf0fff9 Poul Sander 2025-09-18 18:25 364
        }
dbf0fff9 Poul Sander 2025-09-18 18:25 365
        else if (cp < 0x10000) {              // three octets
dbf0fff9 Poul Sander 2025-09-18 18:25 366
            *(result++) = static_cast<octet_type>((cp >> 12)         | 0xe0);
dbf0fff9 Poul Sander 2025-09-18 18:25 367
            *(result++) = static_cast<octet_type>(((cp >> 6) & 0x3f) | 0x80);
dbf0fff9 Poul Sander 2025-09-18 18:25 368
            *(result++) = static_cast<octet_type>((cp & 0x3f)        | 0x80);
dbf0fff9 Poul Sander 2025-09-18 18:25 369
        }
dbf0fff9 Poul Sander 2025-09-18 18:25 370
        else {                                // four octets
dbf0fff9 Poul Sander 2025-09-18 18:25 371
            *(result++) = static_cast<octet_type>((cp >> 18)         | 0xf0);
dbf0fff9 Poul Sander 2025-09-18 18:25 372
            *(result++) = static_cast<octet_type>(((cp >> 12) & 0x3f)| 0x80);
dbf0fff9 Poul Sander 2025-09-18 18:25 373
            *(result++) = static_cast<octet_type>(((cp >> 6) & 0x3f) | 0x80);
dbf0fff9 Poul Sander 2025-09-18 18:25 374
            *(result++) = static_cast<octet_type>((cp & 0x3f)        | 0x80);
dbf0fff9 Poul Sander 2025-09-18 18:25 375
        }
dbf0fff9 Poul Sander 2025-09-18 18:25 376
        return result;
dbf0fff9 Poul Sander 2025-09-18 18:25 377
    }
dbf0fff9 Poul Sander 2025-09-18 18:25 378
dbf0fff9 Poul Sander 2025-09-18 18:25 379
    // One of the following overloads will be invoked from the API calls
dbf0fff9 Poul Sander 2025-09-18 18:25 380
dbf0fff9 Poul Sander 2025-09-18 18:25 381
    // A simple (but dangerous) case: the caller appends byte(s) to a char array
dbf0fff9 Poul Sander 2025-09-18 18:25 382
    inline char* append(utfchar32_t cp, char* result) {
dbf0fff9 Poul Sander 2025-09-18 18:25 383
        return append<char*, char>(cp, result);
dbf0fff9 Poul Sander 2025-09-18 18:25 384
    }
dbf0fff9 Poul Sander 2025-09-18 18:25 385
dbf0fff9 Poul Sander 2025-09-18 18:25 386
    // Hopefully, most common case: the caller uses back_inserter
dbf0fff9 Poul Sander 2025-09-18 18:25 387
    // i.e. append(cp, std::back_inserter(str));
dbf0fff9 Poul Sander 2025-09-18 18:25 388
    template<typename container_type>
dbf0fff9 Poul Sander 2025-09-18 18:25 389
    std::back_insert_iterator<container_type> append
dbf0fff9 Poul Sander 2025-09-18 18:25 390
            (utfchar32_t cp, std::back_insert_iterator<container_type> result) {
dbf0fff9 Poul Sander 2025-09-18 18:25 391
        return append<std::back_insert_iterator<container_type>,
dbf0fff9 Poul Sander 2025-09-18 18:25 392
            typename container_type::value_type>(cp, result);
dbf0fff9 Poul Sander 2025-09-18 18:25 393
    }
dbf0fff9 Poul Sander 2025-09-18 18:25 394
dbf0fff9 Poul Sander 2025-09-18 18:25 395
    // The caller uses some other kind of output operator - not covered above
dbf0fff9 Poul Sander 2025-09-18 18:25 396
    // Note that in this case we are not able to determine octet_type
dbf0fff9 Poul Sander 2025-09-18 18:25 397
    // so we assume it's utfchar8_t; that can cause a conversion warning if we are wrong.
dbf0fff9 Poul Sander 2025-09-18 18:25 398
    template <typename octet_iterator>
dbf0fff9 Poul Sander 2025-09-18 18:25 399
    octet_iterator append(utfchar32_t cp, octet_iterator result) {
dbf0fff9 Poul Sander 2025-09-18 18:25 400
        return append<octet_iterator, utfchar8_t>(cp, result);
dbf0fff9 Poul Sander 2025-09-18 18:25 401
    }
dbf0fff9 Poul Sander 2025-09-18 18:25 402
dbf0fff9 Poul Sander 2025-09-18 18:25 403
    // Internal implementation of both checked and unchecked append16() function
dbf0fff9 Poul Sander 2025-09-18 18:25 404
    // This function will be invoked by the overloads below, as they will know
dbf0fff9 Poul Sander 2025-09-18 18:25 405
    // the word_type.
dbf0fff9 Poul Sander 2025-09-18 18:25 406
    template <typename word_iterator, typename word_type>
dbf0fff9 Poul Sander 2025-09-18 18:25 407
    word_iterator append16(utfchar32_t cp, word_iterator result) {
dbf0fff9 Poul Sander 2025-09-18 18:25 408
        UTF_CPP_STATIC_ASSERT(sizeof(word_type) >= sizeof(utfchar16_t));
dbf0fff9 Poul Sander 2025-09-18 18:25 409
        if (is_in_bmp(cp))
dbf0fff9 Poul Sander 2025-09-18 18:25 410
            *(result++) = static_cast<word_type>(cp);
dbf0fff9 Poul Sander 2025-09-18 18:25 411
        else {
dbf0fff9 Poul Sander 2025-09-18 18:25 412
            // Code points from the supplementary planes are encoded via surrogate pairs
dbf0fff9 Poul Sander 2025-09-18 18:25 413
            *(result++) = static_cast<word_type>(LEAD_OFFSET + (cp >> 10));
dbf0fff9 Poul Sander 2025-09-18 18:25 414
            *(result++) = static_cast<word_type>(TRAIL_SURROGATE_MIN + (cp & 0x3FF));
dbf0fff9 Poul Sander 2025-09-18 18:25 415
        }
dbf0fff9 Poul Sander 2025-09-18 18:25 416
        return result;
dbf0fff9 Poul Sander 2025-09-18 18:25 417
    }
dbf0fff9 Poul Sander 2025-09-18 18:25 418
dbf0fff9 Poul Sander 2025-09-18 18:25 419
    // Hopefully, most common case: the caller uses back_inserter
dbf0fff9 Poul Sander 2025-09-18 18:25 420
    // i.e. append16(cp, std::back_inserter(str));
dbf0fff9 Poul Sander 2025-09-18 18:25 421
    template<typename container_type>
dbf0fff9 Poul Sander 2025-09-18 18:25 422
    std::back_insert_iterator<container_type> append16
dbf0fff9 Poul Sander 2025-09-18 18:25 423
            (utfchar32_t cp, std::back_insert_iterator<container_type> result) {
dbf0fff9 Poul Sander 2025-09-18 18:25 424
        return append16<std::back_insert_iterator<container_type>,
dbf0fff9 Poul Sander 2025-09-18 18:25 425
            typename container_type::value_type>(cp, result);
dbf0fff9 Poul Sander 2025-09-18 18:25 426
    }
dbf0fff9 Poul Sander 2025-09-18 18:25 427
dbf0fff9 Poul Sander 2025-09-18 18:25 428
    // The caller uses some other kind of output operator - not covered above
dbf0fff9 Poul Sander 2025-09-18 18:25 429
    // Note that in this case we are not able to determine word_type
dbf0fff9 Poul Sander 2025-09-18 18:25 430
    // so we assume it's utfchar16_t; that can cause a conversion warning if we are wrong.
dbf0fff9 Poul Sander 2025-09-18 18:25 431
    template <typename word_iterator>
dbf0fff9 Poul Sander 2025-09-18 18:25 432
    word_iterator append16(utfchar32_t cp, word_iterator result) {
dbf0fff9 Poul Sander 2025-09-18 18:25 433
        return append16<word_iterator, utfchar16_t>(cp, result);
dbf0fff9 Poul Sander 2025-09-18 18:25 434
    }
dbf0fff9 Poul Sander 2025-09-18 18:25 435
9f5ec0cc sago007 2015-12-05 08:01 436
} // namespace internal
9f5ec0cc sago007 2015-12-05 08:01 437
9f5ec0cc sago007 2015-12-05 08:01 438
    /// The library API - functions intended to be called by the users
9f5ec0cc sago007 2015-12-05 08:01 439
9f5ec0cc sago007 2015-12-05 08:01 440
    // Byte order mark
dbf0fff9 Poul Sander 2025-09-18 18:25 441
    const utfchar8_t bom[] = {0xef, 0xbb, 0xbf};
9f5ec0cc sago007 2015-12-05 08:01 442
9f5ec0cc sago007 2015-12-05 08:01 443
    template <typename octet_iterator>
9f5ec0cc sago007 2015-12-05 08:01 444
    octet_iterator find_invalid(octet_iterator start, octet_iterator end)
9f5ec0cc sago007 2015-12-05 08:01 445
    {
9f5ec0cc sago007 2015-12-05 08:01 446
        octet_iterator result = start;
9f5ec0cc sago007 2015-12-05 08:01 447
        while (result != end) {
9f5ec0cc sago007 2015-12-05 08:01 448
            utf8::internal::utf_error err_code = utf8::internal::validate_next(result, end);
9f5ec0cc sago007 2015-12-05 08:01 449
            if (err_code != internal::UTF8_OK)
9f5ec0cc sago007 2015-12-05 08:01 450
                return result;
9f5ec0cc sago007 2015-12-05 08:01 451
        }
9f5ec0cc sago007 2015-12-05 08:01 452
        return result;
9f5ec0cc sago007 2015-12-05 08:01 453
    }
9f5ec0cc sago007 2015-12-05 08:01 454
dbf0fff9 Poul Sander 2025-09-18 18:25 455
    inline const char* find_invalid(const char* str)
dbf0fff9 Poul Sander 2025-09-18 18:25 456
    {
dbf0fff9 Poul Sander 2025-09-18 18:25 457
        const char* end = str + std::strlen(str);
dbf0fff9 Poul Sander 2025-09-18 18:25 458
        return find_invalid(str, end);
dbf0fff9 Poul Sander 2025-09-18 18:25 459
    }
dbf0fff9 Poul Sander 2025-09-18 18:25 460
dbf0fff9 Poul Sander 2025-09-18 18:25 461
    inline std::size_t find_invalid(const std::string& s)
dbf0fff9 Poul Sander 2025-09-18 18:25 462
    {
dbf0fff9 Poul Sander 2025-09-18 18:25 463
        std::string::const_iterator invalid = find_invalid(s.begin(), s.end());
dbf0fff9 Poul Sander 2025-09-18 18:25 464
        return (invalid == s.end()) ? std::string::npos : static_cast<std::size_t>(invalid - s.begin());
dbf0fff9 Poul Sander 2025-09-18 18:25 465
    }
dbf0fff9 Poul Sander 2025-09-18 18:25 466
9f5ec0cc sago007 2015-12-05 08:01 467
    template <typename octet_iterator>
9f5ec0cc sago007 2015-12-05 08:01 468
    inline bool is_valid(octet_iterator start, octet_iterator end)
9f5ec0cc sago007 2015-12-05 08:01 469
    {
9f5ec0cc sago007 2015-12-05 08:01 470
        return (utf8::find_invalid(start, end) == end);
9f5ec0cc sago007 2015-12-05 08:01 471
    }
9f5ec0cc sago007 2015-12-05 08:01 472
dbf0fff9 Poul Sander 2025-09-18 18:25 473
    inline bool is_valid(const char* str)
dbf0fff9 Poul Sander 2025-09-18 18:25 474
    {
dbf0fff9 Poul Sander 2025-09-18 18:25 475
        return (*(utf8::find_invalid(str)) == '\0');
dbf0fff9 Poul Sander 2025-09-18 18:25 476
    }
dbf0fff9 Poul Sander 2025-09-18 18:25 477
dbf0fff9 Poul Sander 2025-09-18 18:25 478
    inline bool is_valid(const std::string& s)
dbf0fff9 Poul Sander 2025-09-18 18:25 479
    {
dbf0fff9 Poul Sander 2025-09-18 18:25 480
        return is_valid(s.begin(), s.end());
dbf0fff9 Poul Sander 2025-09-18 18:25 481
    }
dbf0fff9 Poul Sander 2025-09-18 18:25 482
dbf0fff9 Poul Sander 2025-09-18 18:25 483
dbf0fff9 Poul Sander 2025-09-18 18:25 484
9f5ec0cc sago007 2015-12-05 08:01 485
    template <typename octet_iterator>
9f5ec0cc sago007 2015-12-05 08:01 486
    inline bool starts_with_bom (octet_iterator it, octet_iterator end)
9f5ec0cc sago007 2015-12-05 08:01 487
    {
9f5ec0cc sago007 2015-12-05 08:01 488
        return (
9f5ec0cc sago007 2015-12-05 08:01 489
            ((it != end) && (utf8::internal::mask8(*it++)) == bom[0]) &&
9f5ec0cc sago007 2015-12-05 08:01 490
            ((it != end) && (utf8::internal::mask8(*it++)) == bom[1]) &&
9f5ec0cc sago007 2015-12-05 08:01 491
            ((it != end) && (utf8::internal::mask8(*it))   == bom[2])
9f5ec0cc sago007 2015-12-05 08:01 492
           );
9f5ec0cc sago007 2015-12-05 08:01 493
    }
dbf0fff9 Poul Sander 2025-09-18 18:25 494
dbf0fff9 Poul Sander 2025-09-18 18:25 495
    inline bool starts_with_bom(const std::string& s)
9f5ec0cc sago007 2015-12-05 08:01 496
    {
dbf0fff9 Poul Sander 2025-09-18 18:25 497
        return starts_with_bom(s.begin(), s.end());
9f5ec0cc sago007 2015-12-05 08:01 498
    }
9f5ec0cc sago007 2015-12-05 08:01 499
} // namespace utf8
9f5ec0cc sago007 2015-12-05 08:01 500
9f5ec0cc sago007 2015-12-05 08:01 501
#endif // header guard
9f5ec0cc sago007 2015-12-05 08:01 502
1970-01-01 00:00 503