Quelle nsUTF8Utils.h
Sprache: C
/* 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/. */
#ifndef nsUTF8Utils_h_
#define nsUTF8Utils_h_
// NB: This code may be used from non-XPCOM code, in particular, the
// standalone updater executable. That is, this file may be used in
// two ways: if MOZILLA_INTERNAL_API is defined, this file will
// provide signatures for the Mozilla abstract string types. It will
// use XPCOM assertion/debugging macros, etc.
#include <type_traits>
#include "mozilla/Assertions.h"
#include "nsCharTraits.h"
#ifdef MOZILLA_INTERNAL_API
# define UTF8UTILS_WARNING(msg) NS_WARNING(msg)
#else
# define UTF8UTILS_WARNING(msg)
#endif
class UTF8traits {
public :
static bool isASCII(
char aChar) {
return (aChar &
0 x80) ==
0 x00; }
static bool isInSeq(
char aChar) {
return (aChar &
0 xC0) ==
0 x80; }
static bool is2byte(
char aChar) {
return (aChar &
0 xE0) ==
0 xC0; }
static bool is3byte(
char aChar) {
return (aChar &
0 xF0) ==
0 xE0; }
static bool is4byte(
char aChar) {
return (aChar &
0 xF8) ==
0 xF0; }
static bool is5byte(
char aChar) {
return (aChar &
0 xFC) ==
0 xF8; }
static bool is6byte(
char aChar) {
return (aChar &
0 xFE) ==
0 xFC; }
// return the number of bytes in a sequence beginning with aChar
static int bytes(
char aChar) {
if (isASCII(aChar)) {
return 1 ;
}
if (is2byte(aChar)) {
return 2 ;
}
if (is3byte(aChar)) {
return 3 ;
}
if (is4byte(aChar)) {
return 4 ;
}
MOZ_ASSERT_UNREACHABLE(
"should not be used for in-sequence characters" );
return 1 ;
}
};
/**
* Extract the next Unicode scalar value from the buffer and return it . The
* pointer passed in is advanced to the start of the next character in the
* buffer . Upon error , the return value is 0 xFFFD , * aBuffer is advanced
* over the maximal valid prefix and * aErr is set to true ( if aErr is not
* null ) .
*
* Note : This method never sets * aErr to false to allow error accumulation
* across multiple calls .
*
* Precondition : * aBuffer < aEnd
*/
class UTF8CharEnumerator {
public :
static inline char32_t NextChar(
const char ** aBuffer,
const char * aEnd,
bool * aErr = nullptr) {
MOZ_ASSERT(aBuffer,
"null buffer pointer pointer" );
MOZ_ASSERT(aEnd,
"null end pointer" );
const unsigned char * p =
reinterpret_cast <
const unsigned char *>(*aBuffer);
const unsigned char * end =
reinterpret_cast <
const unsigned char *>(aEnd);
MOZ_ASSERT(p,
"null buffer" );
MOZ_ASSERT(p < end,
"Bogus range" );
unsigned char first = *p;
++p;
if (MOZ_LIKELY(first <
0 x80U)) {
*aBuffer =
reinterpret_cast <
const char *>(p);
return first;
}
// Unsigned underflow is defined behavior
if (MOZ_UNLIKELY((p == end) || ((first -
0 xC2U) >= (
0 xF5U -
0 xC2U)))) {
*aBuffer =
reinterpret_cast <
const char *>(p);
if (aErr) {
*aErr =
true ;
}
return 0 xFFFDU;
}
unsigned char second = *p;
if (first <
0 xE0U) {
// Two-byte
if (MOZ_LIKELY((second &
0 xC0U) ==
0 x80U)) {
++p;
*aBuffer =
reinterpret_cast <
const char *>(p);
return ((uint32_t(first) &
0 x1FU) <<
6 ) | (uint32_t(second) &
0 x3FU);
}
*aBuffer =
reinterpret_cast <
const char *>(p);
if (aErr) {
*aErr =
true ;
}
return 0 xFFFDU;
}
if (MOZ_LIKELY(first <
0 xF0U)) {
// Three-byte
unsigned char lower =
0 x80U;
unsigned char upper =
0 xBFU;
if (first ==
0 xE0U) {
lower =
0 xA0U;
}
else if (first ==
0 xEDU) {
upper =
0 x9FU;
}
if (MOZ_LIKELY(second >= lower && second <= upper)) {
++p;
if (MOZ_LIKELY(p != end)) {
unsigned char third = *p;
if (MOZ_LIKELY((third &
0 xC0U) ==
0 x80U)) {
++p;
*aBuffer =
reinterpret_cast <
const char *>(p);
return ((uint32_t(first) &
0 xFU) <<
12 ) |
((uint32_t(second) &
0 x3FU) <<
6 ) |
(uint32_t(third) &
0 x3FU);
}
}
}
*aBuffer =
reinterpret_cast <
const char *>(p);
if (aErr) {
*aErr =
true ;
}
return 0 xFFFDU;
}
// Four-byte
unsigned char lower =
0 x80U;
unsigned char upper =
0 xBFU;
if (first ==
0 xF0U) {
lower =
0 x90U;
}
else if (first ==
0 xF4U) {
upper =
0 x8FU;
}
if (MOZ_LIKELY(second >= lower && second <= upper)) {
++p;
if (MOZ_LIKELY(p != end)) {
unsigned char third = *p;
if (MOZ_LIKELY((third &
0 xC0U) ==
0 x80U)) {
++p;
if (MOZ_LIKELY(p != end)) {
unsigned char fourth = *p;
if (MOZ_LIKELY((fourth &
0 xC0U) ==
0 x80U)) {
++p;
*aBuffer =
reinterpret_cast <
const char *>(p);
return ((uint32_t(first) &
0 x7U) <<
18 ) |
((uint32_t(second) &
0 x3FU) <<
12 ) |
((uint32_t(third) &
0 x3FU) <<
6 ) |
(uint32_t(fourth) &
0 x3FU);
}
}
}
}
}
*aBuffer =
reinterpret_cast <
const char *>(p);
if (aErr) {
*aErr =
true ;
}
return 0 xFFFDU;
}
};
/**
* Extract the next Unicode scalar value from the buffer and return it . The
* pointer passed in is advanced to the start of the next character in the
* buffer . Upon error , the return value is 0 xFFFD , * aBuffer is advanced over
* the unpaired surrogate and * aErr is set to true ( if aErr is not null ) .
*
* Note : This method never sets * aErr to false to allow error accumulation
* across multiple calls .
*
* Precondition : * aBuffer < aEnd
*/
class UTF16CharEnumerator {
public :
static inline char32_t NextChar(
const char16_t** aBuffer,
const char16_t* aEnd,
bool * aErr = nullptr) {
MOZ_ASSERT(aBuffer,
"null buffer pointer pointer" );
MOZ_ASSERT(aEnd,
"null end pointer" );
const char16_t* p = *aBuffer;
MOZ_ASSERT(p,
"null buffer" );
MOZ_ASSERT(p < aEnd,
"Bogus range" );
char16_t c = *p++;
// Let's use encoding_rs-style code golf here.
// Unsigned underflow is defined behavior
char16_t cMinusSurrogateStart = c -
0 xD800U;
if (MOZ_LIKELY(cMinusSurrogateStart > (
0 xDFFFU -
0 xD800U))) {
*aBuffer = p;
return c;
}
if (MOZ_LIKELY(cMinusSurrogateStart <= (
0 xDBFFU -
0 xD800U))) {
// High surrogate
if (MOZ_LIKELY(p != aEnd)) {
char16_t second = *p;
// Unsigned underflow is defined behavior
if (MOZ_LIKELY((second -
0 xDC00U) <= (
0 xDFFFU -
0 xDC00U))) {
*aBuffer = ++p;
return (uint32_t(c) <<
10 ) + uint32_t(second) -
(((
0 xD800U <<
10 ) -
0 x10000U) +
0 xDC00U);
}
}
}
// Unpaired surrogate
*aBuffer = p;
if (aErr) {
*aErr =
true ;
}
return 0 xFFFDU;
}
};
template <
typename Char ,
typename UnsignedT>
inline UnsignedT RewindToPriorUTF8Codepoint(
const Char * utf8Chars,
UnsignedT index) {
static_assert(std::is_same_v<
Char ,
char > ||
std::is_same_v<
Char ,
unsigned char > ||
std::is_same_v<
Char ,
signed char >,
"UTF-8 data must be in 8-bit units" );
static_assert(std::is_unsigned_v<UnsignedT>,
"index type must be unsigned" );
while (index >
0 && (utf8Chars[index] &
0 xC0) ==
0 x80) --index;
return index;
}
#undef UTF8UTILS_WARNING
#endif /* !defined(nsUTF8Utils_h_) */
Messung V0.5 in Prozent C=94 H=96 G=94
¤ Dauer der Verarbeitung: 0.20 Sekunden
(vorverarbeitet am 2026-09-28)
¤
*© Formatika GbR, Deutschland
2026-10-10
Neuigkeiten
Aktuelles
Motto des Tages
Open Source Software
Jenseits des Üblichen ....
Besucherstatistik
Statistik
#Sources=1126864
#Domains=1897691