utf8_checker.hpp
Go to the documentation of this file.
/*
* RESTinio
*/
#pragma once
#include <restinio/compiler_features.hpp>
#include <cstdint>
namespace restinio
{
namespace utils
{
//
// utf8_checker_t
//
class utf8_checker_t
{
public:
utf8_checker_t() = default;
RESTINIO_NODISCARD
bool
process_byte( std::uint8_t byte ) noexcept
{
check_overlong( byte );
if( m_current_symbol_rest_bytes > 0 )
{
// check byte is 10xxxxxx.
if( (byte & 0xC0) == 0x80 )
{
m_current_symbol <<= 6;
byte &= 0x3F;
m_current_symbol |= byte;
if( --m_current_symbol_rest_bytes == 0 )
{
validate_current_symbol();
}
}
else
{
m_state = state_t::invalid;
}
}
else
{
m_current_symbol = 0;
if( (byte & 0x80) == 0x00)
{
// mask 0xxxxxxx
m_current_symbol_rest_bytes = 0;
}
else if( (byte & 0xE0) == 0xC0)
{
// mask 110xxxxx
m_current_symbol_rest_bytes = 1;
byte &= 0x1F;
}
else if( (byte & 0xF0) == 0xE0)
{
// mask 1110xxxx
m_current_symbol_rest_bytes = 2;
byte &= 0xF;
}
else if( (byte & 0xF8) == 0xF0)
{
// mask 11110xxx
m_current_symbol_rest_bytes = 3;
byte &= 0x7;
}
else if( (byte & 0xFC) == 0xF8)
{
// mask 111110xx
m_current_symbol_rest_bytes = 4;
byte &= 0x3;
}
else if( (byte & 0xFE) == 0xFC)
{
// mask 1111110x
m_current_symbol_rest_bytes = 5;
byte &= 0x1;
}
else
{
m_state = state_t::invalid;
}
m_current_symbol = byte;
}
return m_state == state_t::valid || m_state == state_t::may_be_overlong;
}
RESTINIO_NODISCARD
bool
finalized() const noexcept
{
return m_current_symbol_rest_bytes == 0;
}
void
reset() noexcept
{
m_current_symbol = 0;
m_current_symbol_rest_bytes = 0;
}
RESTINIO_NODISCARD
std::uint32_t
current_symbol() const noexcept { return m_current_symbol; }
private:
void
validate_current_symbol() noexcept
{
if( (m_current_symbol >= 0xD800 && m_current_symbol <= 0xDFFF) ||
(m_current_symbol >= 0x110000) )
{
m_state = state_t::invalid;
}
}
void
check_overlong( std::uint8_t byte ) noexcept
{
if( m_current_symbol_rest_bytes > 0 &&
m_state == state_t::may_be_overlong )
{
if( m_current_symbol_rest_bytes == 2 &&
(byte & 0xE0) == 0x80 )
m_state = state_t::overlong;
else if( m_current_symbol_rest_bytes == 3 &&
(byte & 0xF0) == 0x80 )
m_state = state_t::overlong;
else if( m_current_symbol_rest_bytes == 4 &&
(byte & 0xF8) == 0x80 )
m_state = state_t::overlong;
else if( m_current_symbol_rest_bytes == 5 &&
(byte & 0xFC) == 0x80 )
m_state = state_t::overlong;
else
m_state = state_t::valid;
}
else
{
if( byte == 0xC0 || byte == 0xC1 )
{
m_state = state_t::overlong;
}
else if( byte == 0xE0 )
{
m_state = state_t::may_be_overlong;
}
else if( byte == 0xF0 )
{
m_state = state_t::may_be_overlong;
}
if( byte == 0xF8 )
{
m_state = state_t::may_be_overlong;
}
if( byte == 0xFC )
{
m_state = state_t::may_be_overlong;
}
}
}
std::uint32_t m_current_symbol = 0u;
std::size_t m_current_symbol_rest_bytes = 0u;
enum class state_t
{
valid,
invalid,
may_be_overlong,
overlong
};
state_t m_state = state_t::valid;
};
} /* namespace utils */
} /* namespace restinio */
restinio::utils::utf8_checker_t
Helper class for checking UTF-8 byte sequence during parsing URI or incoming byte stream.
Definition: utf8_checker.hpp:35
restinio::utils::utf8_checker_t::state_t
state_t
Definition: utf8_checker.hpp:199
restinio::utils::utf8_checker_t::state_t::valid
@ valid
restinio::utils::utf8_checker_t::state_t::may_be_overlong
@ may_be_overlong
restinio::utils::utf8_checker_t::state_t::invalid
@ invalid
restinio::utils::utf8_checker_t::state_t::overlong
@ overlong
restinio::utils::utf8_checker_t::validate_current_symbol
void validate_current_symbol() noexcept
Definition: utf8_checker.hpp:139
restinio::utils::utf8_checker_t::finalized
RESTINIO_NODISCARD bool finalized() const noexcept
Definition: utf8_checker.hpp:120
restinio::utils::utf8_checker_t::process_byte
RESTINIO_NODISCARD bool process_byte(std::uint8_t byte) noexcept
Definition: utf8_checker.hpp:41
restinio::utils::utf8_checker_t::m_current_symbol
std::uint32_t m_current_symbol
Definition: utf8_checker.hpp:194
restinio::utils::utf8_checker_t::check_overlong
void check_overlong(std::uint8_t byte) noexcept
Definition: utf8_checker.hpp:149
restinio::utils::utf8_checker_t::current_symbol
RESTINIO_NODISCARD std::uint32_t current_symbol() const noexcept
Definition: utf8_checker.hpp:134
restinio::utils::utf8_checker_t::utf8_checker_t
utf8_checker_t()=default
restinio::utils::utf8_checker_t::reset
void reset() noexcept
Definition: utf8_checker.hpp:126
restinio::utils::utf8_checker_t::m_current_symbol_rest_bytes
std::size_t m_current_symbol_rest_bytes
Definition: utf8_checker.hpp:196
restinio::utils::utf8_checker_t::m_state
state_t m_state
Definition: utf8_checker.hpp:206
compiler_features.hpp
Detection of compiler version and absence of various features.
RESTINIO_NODISCARD
#define RESTINIO_NODISCARD
Definition: compiler_features.hpp:33
restinio::utils::sha1::details::byte
unsigned int byte(digest_t::value_type v)
Definition: sha1.hpp:365
restinio
Definition: asio_include.hpp:21
const
#define const
Definition: zconf.h:230