Line data Source code
1 : /* SPDX-License-Identifier: BSD-3-Clause 2 : * Copyright (C) 2016 Intel Corporation. 3 : * All rights reserved. 4 : */ 5 : 6 : #ifndef SPDK_UTF_H_ 7 : #define SPDK_UTF_H_ 8 : 9 : #include "spdk/stdinc.h" 10 : 11 : #include "spdk/endian.h" 12 : #include "spdk/likely.h" 13 : #include "spdk/string.h" 14 : 15 : static inline bool 16 270 : utf8_tail(uint8_t c) 17 : { 18 : /* c >= 0x80 && c <= 0xBF, or binary 01xxxxxx */ 19 270 : return (c & 0xC0) == 0x80; 20 : } 21 : 22 : /* 23 : * Check for a valid UTF-8 encoding of a single codepoint. 24 : * 25 : * \return Length of valid UTF-8 byte sequence, or negative if invalid. 26 : */ 27 : static inline int 28 5954 : utf8_valid(const uint8_t *start, const uint8_t *end) 29 : { 30 5954 : const uint8_t *p = start; 31 5954 : uint8_t b0, b1, b2, b3; 32 : 33 5954 : if (p == end) { 34 0 : return 0; 35 : } 36 : 37 5954 : b0 = *p; 38 : 39 5954 : if (b0 <= 0x7F) { 40 5742 : return 1; 41 : } 42 : 43 212 : if (b0 <= 0xC1) { 44 : /* Invalid start byte */ 45 6 : return -1; 46 : } 47 : 48 206 : if (++p == end) { 49 : /* Not enough bytes left */ 50 8 : return -1; 51 : } 52 198 : b1 = *p; 53 : 54 198 : if (b0 <= 0xDF) { 55 : /* C2..DF 80..BF */ 56 21 : if (!utf8_tail(b1)) { 57 2 : return -1; 58 : } 59 19 : return 2; 60 : } 61 : 62 177 : if (++p == end) { 63 : /* Not enough bytes left */ 64 14 : return -1; 65 : } 66 163 : b2 = *p; 67 : 68 163 : if (b0 == 0xE0) { 69 : /* E0 A0..BF 80..BF */ 70 21 : if (b1 < 0xA0 || b1 > 0xBF || !utf8_tail(b2)) { 71 9 : return -1; 72 : } 73 12 : return 3; 74 142 : } else if (b0 == 0xED && b1 >= 0xA0) { 75 : /* 76 : * UTF-16 surrogate pairs use U+D800..U+DFFF, which would be encoded as 77 : * ED A0..BF 80..BF in UTF-8; however, surrogate pairs are not allowed in UTF-8. 78 : */ 79 10 : return -1; 80 132 : } else if (b0 <= 0xEF) { 81 : /* E1..EF 80..BF 80..BF */ 82 56 : if (!utf8_tail(b1) || !utf8_tail(b2)) { 83 9 : return -1; 84 : } 85 47 : return 3; 86 : } 87 : 88 76 : if (++p == end) { 89 : /* Not enough bytes left */ 90 8 : return -1; 91 : } 92 68 : b3 = *p; 93 : 94 68 : if (b0 == 0xF0) { 95 : /* F0 90..BF 80..BF 80..BF */ 96 26 : if (b1 < 0x90 || b1 > 0xBF || !utf8_tail(b2) || !utf8_tail(b3)) { 97 7 : return -1; 98 : } 99 19 : return 4; 100 42 : } else if (b0 <= 0xF3) { 101 : /* F1..F3 80..BF 80..BF 80..BF */ 102 24 : if (!utf8_tail(b1) || !utf8_tail(b2) || !utf8_tail(b3)) { 103 9 : return -1; 104 : } 105 15 : return 4; 106 18 : } else if (b0 == 0xF4) { 107 : /* F4 80..8F 80..BF 80..BF */ 108 12 : if (b1 < 0x80 || b1 > 0x8F || !utf8_tail(b2) || !utf8_tail(b3)) { 109 3 : return -1; 110 : } 111 9 : return 4; 112 : } 113 : 114 6 : return -1; 115 5954 : } 116 : 117 : static inline uint32_t 118 1421 : utf8_decode_unsafe_1(const uint8_t *data) 119 : { 120 1421 : return data[0]; 121 : } 122 : 123 : static inline uint32_t 124 6 : utf8_decode_unsafe_2(const uint8_t *data) 125 : { 126 6 : uint32_t codepoint; 127 : 128 6 : codepoint = ((data[0] & 0x1F) << 6); 129 6 : codepoint |= (data[1] & 0x3F); 130 : 131 12 : return codepoint; 132 6 : } 133 : 134 : static inline uint32_t 135 20 : utf8_decode_unsafe_3(const uint8_t *data) 136 : { 137 20 : uint32_t codepoint; 138 : 139 20 : codepoint = ((data[0] & 0x0F) << 12); 140 20 : codepoint |= (data[1] & 0x3F) << 6; 141 20 : codepoint |= (data[2] & 0x3F); 142 : 143 40 : return codepoint; 144 20 : } 145 : 146 : static inline uint32_t 147 15 : utf8_decode_unsafe_4(const uint8_t *data) 148 : { 149 15 : uint32_t codepoint; 150 : 151 15 : codepoint = ((data[0] & 0x07) << 18); 152 15 : codepoint |= (data[1] & 0x3F) << 12; 153 15 : codepoint |= (data[2] & 0x3F) << 6; 154 15 : codepoint |= (data[3] & 0x3F); 155 : 156 30 : return codepoint; 157 15 : } 158 : 159 : /* 160 : * Encode a single Unicode codepoint as UTF-8. 161 : * 162 : * buf must have at least 4 bytes of space available (hence unsafe). 163 : * 164 : * \return Number of bytes appended to buf, or negative if encoding failed. 165 : */ 166 : static inline int 167 7 : utf8_encode_unsafe(uint8_t *buf, uint32_t c) 168 : { 169 7 : if (c <= 0x7F) { 170 3 : buf[0] = c; 171 3 : return 1; 172 4 : } else if (c <= 0x7FF) { 173 0 : buf[0] = 0xC0 | (c >> 6); 174 0 : buf[1] = 0x80 | (c & 0x3F); 175 0 : return 2; 176 4 : } else if (c >= 0xD800 && c <= 0xDFFF) { 177 : /* UTF-16 surrogate pairs - invalid in UTF-8 */ 178 0 : return -1; 179 4 : } else if (c <= 0xFFFF) { 180 3 : buf[0] = 0xE0 | (c >> 12); 181 3 : buf[1] = 0x80 | ((c >> 6) & 0x3F); 182 3 : buf[2] = 0x80 | (c & 0x3F); 183 3 : return 3; 184 1 : } else if (c <= 0x10FFFF) { 185 1 : buf[0] = 0xF0 | (c >> 18); 186 1 : buf[1] = 0x80 | ((c >> 12) & 0x3F); 187 1 : buf[2] = 0x80 | ((c >> 6) & 0x3F); 188 1 : buf[3] = 0x80 | (c & 0x3F); 189 1 : return 4; 190 : } 191 0 : return -1; 192 7 : } 193 : 194 : static inline int 195 7 : utf8_codepoint_len(uint32_t c) 196 : { 197 7 : if (c <= 0x7F) { 198 3 : return 1; 199 4 : } else if (c <= 0x7FF) { 200 0 : return 2; 201 4 : } else if (c >= 0xD800 && c <= 0xDFFF) { 202 : /* UTF-16 surrogate pairs - invalid in UTF-8 */ 203 0 : return -1; 204 4 : } else if (c <= 0xFFFF) { 205 3 : return 3; 206 1 : } else if (c <= 0x10FFFF) { 207 1 : return 4; 208 : } 209 0 : return -1; 210 7 : } 211 : 212 : static inline bool 213 47 : utf16_valid_surrogate_high(uint32_t val) 214 : { 215 47 : return val >= 0xD800 && val <= 0xDBFF; 216 : } 217 : 218 : static inline bool 219 40 : utf16_valid_surrogate_low(uint32_t val) 220 : { 221 40 : return val >= 0xDC00 && val <= 0xDFFF; 222 : } 223 : 224 : /* 225 : * Check for a valid UTF-16LE encoding of a single codepoint. 226 : * 227 : * \return Length of valid UTF-16LE sequence in 16-bit code units, or negative if invalid. 228 : */ 229 : static inline int 230 13 : utf16le_valid(const uint16_t *start, const uint16_t *end) 231 : { 232 13 : const uint16_t *p = start; 233 13 : uint16_t high, low; 234 : 235 13 : if (p == end) { 236 0 : return 0; 237 : } 238 : 239 13 : high = from_le16(p); 240 : 241 13 : if (high <= 0xD7FF || high >= 0xE000) { 242 : /* Single code unit in BMP */ 243 9 : return 1; 244 : } 245 : 246 4 : if (high >= 0xDC00) { 247 : /* Low surrogate in first code unit - invalid */ 248 1 : return -1; 249 : } 250 : 251 3 : assert(utf16_valid_surrogate_high(high)); 252 : 253 3 : if (++p == end) { 254 : /* Not enough code units left */ 255 1 : return -1; 256 : } 257 2 : low = from_le16(p); 258 : 259 2 : if (!utf16_valid_surrogate_low(low)) { 260 1 : return -1; 261 : } 262 : 263 : /* Valid surrogate pair */ 264 1 : return 2; 265 13 : } 266 : 267 : static inline uint32_t 268 3 : utf16_decode_surrogate_pair(uint32_t high, uint32_t low) 269 : { 270 3 : uint32_t codepoint; 271 : 272 3 : assert(utf16_valid_surrogate_high(high)); 273 3 : assert(utf16_valid_surrogate_low(low)); 274 : 275 3 : codepoint = low; 276 3 : codepoint &= 0x3FF; 277 3 : codepoint |= ((high & 0x3FF) << 10); 278 3 : codepoint += 0x10000; 279 : 280 6 : return codepoint; 281 3 : } 282 : 283 : static inline void 284 16 : utf16_encode_surrogate_pair(uint32_t codepoint, uint16_t *high, uint16_t *low) 285 : { 286 16 : assert(codepoint >= 0x10000); 287 16 : assert(codepoint <= 0x10FFFF); 288 : 289 16 : codepoint -= 0x10000; 290 16 : *high = 0xD800 | (codepoint >> 10); 291 16 : *low = 0xDC00 | (codepoint & 0x3FF); 292 : 293 16 : assert(utf16_valid_surrogate_high(*high)); 294 16 : assert(utf16_valid_surrogate_low(*low)); 295 16 : } 296 : 297 : #endif