mirror of
				https://github.com/boostorg/mqtt5.git
				synced 2025-11-03 17:31:37 +01:00 
			
		
		
		
	Summary: related to T13318 Reviewers: ivica Reviewed By: ivica Subscribers: miljen, iljazovic Differential Revision: https://repo.mireo.local/D26975
		
			
				
	
	
		
			100 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			100 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#ifndef ASYNC_MQTT5_UTF8_MQTT_HPP
 | 
						|
#define ASYNC_MQTT5_UTF8_MQTT_HPP
 | 
						|
 | 
						|
#include <string>
 | 
						|
 | 
						|
namespace async_mqtt5::detail {
 | 
						|
 | 
						|
enum class validation_result : uint8_t {
 | 
						|
	valid = 0,
 | 
						|
	has_wildcard_character,
 | 
						|
	invalid
 | 
						|
};
 | 
						|
 | 
						|
inline int pop_front_unichar(std::string_view& s) {
 | 
						|
	// assuming that s.length() is > 0
 | 
						|
 | 
						|
	int n = s[0] & 0xF0;
 | 
						|
	int ch = -1;
 | 
						|
 | 
						|
	if ((n & 0x80) == 0) {
 | 
						|
		ch = s[0];
 | 
						|
		s.remove_prefix(1);
 | 
						|
	}
 | 
						|
	else if ((n == 0xC0 || n == 0xD0) && s.size() > 1) {
 | 
						|
		ch = ((s[0] & 0x1F) << 6) | (s[1] & 0x3F);
 | 
						|
		s.remove_prefix(2);
 | 
						|
	}
 | 
						|
	else if ((n == 0xE0) && s.size() > 2) {
 | 
						|
		ch = ((s[0] & 0x1F) << 12) | ((s[1] & 0x3F) << 6) | (s[2] & 0x3F);
 | 
						|
		s.remove_prefix(3);
 | 
						|
	}
 | 
						|
	else if ((n == 0xF0) && s.size() > 3) {
 | 
						|
		ch = ((s[0] & 0x1F) << 18) | ((s[1] & 0x3F) << 12) |
 | 
						|
			((s[2] & 0x3F) << 6) | (s[3] & 0x3F);
 | 
						|
		s.remove_prefix(4);
 | 
						|
	}
 | 
						|
 | 
						|
	return ch;
 | 
						|
}
 | 
						|
 | 
						|
inline validation_result validate_mqtt_utf8_char(int c) {
 | 
						|
	constexpr int fe_flag = 0xFE;
 | 
						|
	constexpr int ff_flag = 0xFF;
 | 
						|
 | 
						|
	constexpr int multi_lvl_wildcard = '#';
 | 
						|
	constexpr int single_lvl_wildcard = '+';
 | 
						|
 | 
						|
	if (c == multi_lvl_wildcard || c == single_lvl_wildcard)
 | 
						|
		return validation_result::has_wildcard_character;
 | 
						|
 | 
						|
	if (c > 0x001F && // U+0000...U+001F control characters
 | 
						|
		(c < 0x007F || c > 0x009F) && // U+007F...0+009F control characters
 | 
						|
		(c < 0xD800 || c > 0xDFFF) && // U+D800...U+DFFF surrogates
 | 
						|
		(c < 0xFDD0 || c > 0xFDEF) && // U+FDD0...U+FDEF non-characters
 | 
						|
		(c & fe_flag) != fe_flag && // non-characters
 | 
						|
		(c & ff_flag) != ff_flag
 | 
						|
	)
 | 
						|
		return validation_result::valid;
 | 
						|
 | 
						|
	return validation_result::invalid;
 | 
						|
}
 | 
						|
 | 
						|
inline bool is_valid_string_size(size_t sz) {
 | 
						|
	constexpr size_t max_sz = 65535;
 | 
						|
	return sz <= max_sz;
 | 
						|
}
 | 
						|
 | 
						|
inline bool is_utf8(validation_result result) {
 | 
						|
	return result == validation_result::valid ||
 | 
						|
		result == validation_result::has_wildcard_character;
 | 
						|
}
 | 
						|
 | 
						|
template <typename ValidSizeCondition, typename ValidCondition>
 | 
						|
validation_result validate_impl(
 | 
						|
	std::string_view str,
 | 
						|
	ValidSizeCondition&& size_condition, ValidCondition&& condition
 | 
						|
) {
 | 
						|
	if (!size_condition(str.size()))
 | 
						|
		return validation_result::invalid;
 | 
						|
 | 
						|
	validation_result result;
 | 
						|
	while (!str.empty()) {
 | 
						|
		int c = pop_front_unichar(str);
 | 
						|
 | 
						|
		result = validate_mqtt_utf8_char(c);
 | 
						|
		if (!condition(result))
 | 
						|
			return result;
 | 
						|
	}
 | 
						|
 | 
						|
	return validation_result::valid;
 | 
						|
}
 | 
						|
 | 
						|
inline validation_result validate_mqtt_utf8(std::string_view str) {
 | 
						|
	return validate_impl(str, is_valid_string_size, is_utf8);
 | 
						|
}
 | 
						|
 | 
						|
} // namespace async_mqtt5::detail
 | 
						|
 | 
						|
#endif //ASYNC_MQTT5_UTF8_MQTT_HPP
 |