mirror of
https://github.com/open62541/open62541.git
synced 2026-10-16 20:33:18 +08:00
feat(deps): Add lightweight utf8 de/encoding as a standalone implementation
This commit is contained in:
committed by
Julius Pfrommer
parent
4f9c75e372
commit
ba1810606f
Vendored
+1
@@ -21,3 +21,4 @@ The following third party libraries may be included -- depending on the activate
|
||||
| mqtt-c | MIT | a portable MQTT client in C |
|
||||
| dtoa | BSL (Boost) | Printing of float numbers |
|
||||
| mp_printf | MIT | Our version of github:mpaland/printf |
|
||||
| utf8 | MPL 2.0 | Lightweight utf8 de/encoding |
|
||||
|
||||
Vendored
+67
@@ -0,0 +1,67 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 2024 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
|
||||
*/
|
||||
|
||||
#include "utf8.h"
|
||||
|
||||
#define UTF_PARSE_BYTE(pos) do { \
|
||||
byte = str[pos]; \
|
||||
if(UTF_UNLIKELY(byte < 0x80 || byte > 0xBF)) \
|
||||
return 0; /* Not a continuation byte */ \
|
||||
*codepoint = (*codepoint << 6) + (byte & 0x3F); \
|
||||
} while(0)
|
||||
|
||||
unsigned
|
||||
utf8_to_codepoint(const unsigned char *str, size_t len, unsigned *codepoint) {
|
||||
/* Ensure there is a character to read */
|
||||
if(UTF_UNLIKELY(len == 0))
|
||||
return 0;
|
||||
|
||||
*codepoint = str[0];
|
||||
if(UTF_LIKELY(*codepoint < 0x80))
|
||||
return 1; /* Normal ASCII */
|
||||
|
||||
if(UTF_UNLIKELY(*codepoint <= 0xC1))
|
||||
return 0; /* Continuation byte not allowed here */
|
||||
|
||||
unsigned count;
|
||||
unsigned char byte;
|
||||
if(*codepoint <= 0xDF) { /* 2-byte sequence */
|
||||
if(len < 2)
|
||||
return 0;
|
||||
count = 2;
|
||||
*codepoint &= 0x1F;
|
||||
UTF_PARSE_BYTE(1);
|
||||
if(UTF_UNLIKELY(*codepoint < 0x80))
|
||||
return 0; /* Too small for the encoding length */
|
||||
} else if(*codepoint <= 0xEF) { /* 3-byte sequence */
|
||||
if(len < 3)
|
||||
return 0;
|
||||
count = 3;
|
||||
*codepoint &= 0xF;
|
||||
UTF_PARSE_BYTE(1);
|
||||
UTF_PARSE_BYTE(2);
|
||||
if(UTF_UNLIKELY(*codepoint < 0x800))
|
||||
return 0; /* Too small for the encoding length */
|
||||
} else if(*codepoint <= 0xF4) { /* 4-byte sequence */
|
||||
if(len < 4)
|
||||
return 0;
|
||||
count = 4;
|
||||
*codepoint &= 0x7;
|
||||
UTF_PARSE_BYTE(1);
|
||||
UTF_PARSE_BYTE(2);
|
||||
UTF_PARSE_BYTE(3);
|
||||
if(UTF_UNLIKELY(*codepoint < 0x10000))
|
||||
return 0; /* Too small for the encoding length */
|
||||
} else {
|
||||
return 0; /* Invalid utf8 encoding */
|
||||
}
|
||||
|
||||
if(UTF_UNLIKELY(*codepoint > 0x10FFFF))
|
||||
return 0; /* Not in the Unicode range */
|
||||
|
||||
return count;
|
||||
}
|
||||
Vendored
+83
@@ -0,0 +1,83 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 2024 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
|
||||
*/
|
||||
|
||||
#ifndef UTF8_H_
|
||||
#define UTF8_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define UTF_INLINE __inline
|
||||
#else
|
||||
# define UTF_INLINE inline
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
# define UTF_LIKELY(x) __builtin_expect((x), 1)
|
||||
# define UTF_UNLIKELY(x) __builtin_expect((x), 0)
|
||||
#else
|
||||
# define UTF_LIKELY(x) (x)
|
||||
# define UTF_UNLIKELY(x) (x)
|
||||
#endif
|
||||
|
||||
/* Extract the next utf8 codepoint from the buffer. Returns the length (1-4) of
|
||||
* the codepoint encoding or 0 upon an error. */
|
||||
unsigned
|
||||
utf8_to_codepoint(const unsigned char *str, size_t len, unsigned *codepoint);
|
||||
|
||||
/* Encodes the codepoint in utf8. The string needs to have enough space (at most
|
||||
* four byte) available. Returns the encoding length. */
|
||||
static UTF_INLINE unsigned
|
||||
utf8_from_codepoint(unsigned char *str, unsigned codepoint) {
|
||||
if(UTF_LIKELY(codepoint <= 0x7F)) { /* Plain ASCII */
|
||||
str[0] = (unsigned char)codepoint;
|
||||
return 1;
|
||||
}
|
||||
if(UTF_LIKELY(codepoint <= 0x07FF)) { /* 2-byte unicode */
|
||||
str[0] = (unsigned char)(((codepoint >> 6) & 0x1F) | 0xC0);
|
||||
str[1] = (unsigned char)(((codepoint >> 0) & 0x3F) | 0x80);
|
||||
return 2;
|
||||
}
|
||||
if(UTF_LIKELY(codepoint <= 0xFFFF)) { /* 3-byte unicode */
|
||||
str[0] = (unsigned char)(((codepoint >> 12) & 0x0F) | 0xE0);
|
||||
str[1] = (unsigned char)(((codepoint >> 6) & 0x3F) | 0x80);
|
||||
str[2] = (unsigned char)(((codepoint >> 0) & 0x3F) | 0x80);
|
||||
return 3;
|
||||
}
|
||||
if(UTF_LIKELY(codepoint <= 0x10FFFF)) { /* 4-byte unicode */
|
||||
str[0] = (unsigned char)(((codepoint >> 18) & 0x07) | 0xF0);
|
||||
str[1] = (unsigned char)(((codepoint >> 12) & 0x3F) | 0x80);
|
||||
str[2] = (unsigned char)(((codepoint >> 6) & 0x3F) | 0x80);
|
||||
str[3] = (unsigned char)(((codepoint >> 0) & 0x3F) | 0x80);
|
||||
return 4;
|
||||
}
|
||||
return 0; /* Not a unicode codepoint */
|
||||
}
|
||||
|
||||
/* Returns the encoding length of the codepoint */
|
||||
static UTF_INLINE unsigned
|
||||
utf8_length(unsigned codepoint) {
|
||||
if(UTF_LIKELY(codepoint <= 0x7F))
|
||||
return 1; /* Plain ASCII */
|
||||
if(UTF_LIKELY(codepoint <= 0x07FF))
|
||||
return 2; /* 2-byte unicode */
|
||||
if(UTF_LIKELY(codepoint <= 0xFFFF))
|
||||
return 3; /* 3-byte unicode */
|
||||
if(UTF_LIKELY(codepoint <= 0x10FFFF))
|
||||
return 4; /* 4-byte unicode */
|
||||
return 0; /* Not a unicode codepoint */
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* UTF8_H_ */
|
||||
Reference in New Issue
Block a user