827b79f766
- C3d aggiornamento delle librerie ( 117987).
289 lines
9.7 KiB
C++
289 lines
9.7 KiB
C++
////////////////////////////////////////////////////////////////////////////////
|
|
/**
|
|
\file
|
|
\brief \ru Глобально уникальный идентификатор.
|
|
\en Global unique identifier. \~
|
|
|
|
*/
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifndef _TOOL_UUID_H_
|
|
#define _TOOL_UUID_H_
|
|
|
|
#include <memory.h>
|
|
#include <math_define.h>
|
|
#include <templ_three_states.h>
|
|
#include <string>
|
|
#include <cstring>
|
|
|
|
class reader;
|
|
class writer;
|
|
|
|
|
|
constexpr uint8 uuidSize = 16;
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
/** \brief \ru Глобально уникальный идентификатор.
|
|
\en Global unique identifier. \~
|
|
\details \ru Глобально уникальный идентификатор - используется как идентификатор
|
|
типа пользовательского атрибута.
|
|
\en Global unique identifier - it is used as an identifier
|
|
of a type of user attribute. \~
|
|
\ingroup Model_Attributes
|
|
*/
|
|
struct MbUuid
|
|
{
|
|
protected:
|
|
uint8 data[uuidSize];
|
|
private:
|
|
mutable ThreeStates isEmpty;
|
|
|
|
public:
|
|
typedef uint8 * iterator;
|
|
typedef uint8 const * const_iterator;
|
|
public:
|
|
MbUuid() : isEmpty( ts_positive ) { ::memset( data, 0, uuidSize ); }
|
|
MbUuid( const MbUuid & id ) : isEmpty( id.isEmpty ) { ::memcpy( data, id.data, uuidSize ); }
|
|
public:
|
|
iterator begin() { isEmpty = ts_neutral; return data; }
|
|
iterator end() { isEmpty = ts_neutral; return data + uuidSize; }
|
|
|
|
const_iterator cbegin() const { return data; }
|
|
const_iterator cend() const { return data + uuidSize; }
|
|
|
|
size_t size() const { return uuidSize; }
|
|
|
|
bool is_nil() const
|
|
{
|
|
if ( isEmpty == ts_neutral ) {
|
|
isEmpty = ts_positive;
|
|
for ( uint8 i = 0; i < uuidSize; i++ ) {
|
|
if ( data[i] != 0U ) {
|
|
isEmpty = ts_negative;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return (isEmpty == ts_positive);
|
|
}
|
|
void swap( MbUuid & id )
|
|
{
|
|
uint8 temp[16];
|
|
::memcpy( temp, data, uuidSize );
|
|
::memcpy( data, id.data, uuidSize );
|
|
::memcpy( id.data, temp, uuidSize );
|
|
std::swap( isEmpty, id.isEmpty );
|
|
}
|
|
|
|
public:
|
|
MbUuid & operator = ( const MbUuid & id )
|
|
{
|
|
::memcpy( data, id.data, uuidSize );
|
|
isEmpty = id.isEmpty;
|
|
return *this;
|
|
}
|
|
bool operator == ( const MbUuid & id ) const
|
|
{
|
|
//return std::equal( cbegin(), cend(), id.cbegin() );
|
|
MbUuid::const_iterator first1 = cbegin(), last1 = cend(), first2 = id.cbegin();
|
|
while ( first1 != last1 )
|
|
{
|
|
if ( !(*first1 == *first2) )
|
|
return false;
|
|
++first1; ++first2;
|
|
}
|
|
return true;
|
|
}
|
|
bool operator != ( const MbUuid & id ) const { return !(*this == id); }
|
|
bool operator < ( const MbUuid & id ) const { return std::lexicographical_compare( cbegin(), cend(), id.cbegin(), id.cend() ); }
|
|
bool operator > ( const MbUuid & id ) const { return (id < *this); }
|
|
bool operator <= ( const MbUuid & id ) const { return !(id < *this); }
|
|
bool operator >= ( const MbUuid & id ) const { return !(*this < id); }
|
|
|
|
public:
|
|
friend struct string_generator;
|
|
friend reader & CALL_DECLARATION operator >> ( reader & in, MbUuid & ref );
|
|
friend writer & CALL_DECLARATION operator << ( writer & out, const MbUuid & ref );
|
|
friend writer & CALL_DECLARATION operator << ( writer & out, MbUuid & ref ) { return operator << ( out, const_cast<const MbUuid &>(ref) ); }
|
|
};
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
/** \brief \ru Генератор MbUuid из string.
|
|
\en Generator of MbUuid from string. \~
|
|
\details \ru Генератор MbUuid из string. Принимает следующие формы: \n
|
|
0123456789abcdef0123456789abcdef, \n
|
|
01234567-89ab-cdef-0123456789abcdef, \n
|
|
{01234567-89ab-cdef-0123456789abcdef}, \n
|
|
{0123456789abcdef0123456789abcdef}. \n
|
|
\en Generator of MbUuid from string. It accepts the next format: \n
|
|
0123456789abcdef0123456789abcdef, \n
|
|
01234567-89ab-cdef-0123456789abcdef, \n
|
|
{01234567-89ab-cdef-0123456789abcdef}, \n
|
|
{0123456789abcdef0123456789abcdef}. \n
|
|
\~
|
|
\ingroup Model_Attributes
|
|
*/
|
|
//---
|
|
struct string_generator
|
|
{
|
|
template <typename ch, typename char_traits, typename alloc>
|
|
MbUuid operator()( std::basic_string<ch, char_traits, alloc> const & s ) const {
|
|
return operator()( s.begin(), s.end() );
|
|
};
|
|
|
|
MbUuid operator()( char const * const s ) const {
|
|
return operator()( s, s+std::strlen(s) );
|
|
}
|
|
|
|
MbUuid operator()( wchar_t const * const s ) const {
|
|
return operator()( s, s+std::wcslen(s) );
|
|
}
|
|
|
|
template <typename CharIterator>
|
|
MbUuid operator()( CharIterator begin, CharIterator end ) const
|
|
{
|
|
typedef typename std::iterator_traits<CharIterator>::value_type char_type;
|
|
|
|
// \ru Проверяем открывающую скобку \en Check an opening parenthesis.
|
|
char_type c = get_next_char( begin, end );
|
|
bool has_open_brace = is_open_brace(c);
|
|
char_type open_brace_char = c;
|
|
if ( has_open_brace ) {
|
|
c = get_next_char( begin, end );
|
|
}
|
|
|
|
bool has_dashes = false;
|
|
|
|
MbUuid u;
|
|
bool isEmpty = true;
|
|
|
|
int i = 0;
|
|
for ( MbUuid::iterator it_byte = u.begin(); it_byte != u.end(); ++it_byte, ++i ) {
|
|
if ( it_byte != u.begin() ) {
|
|
c = get_next_char( begin, end );
|
|
}
|
|
if ( i == 4 ) {
|
|
if ( is_dash(c) ) {
|
|
c = get_next_char( begin, end );
|
|
has_dashes = true;
|
|
}
|
|
}
|
|
if ( has_dashes ) {
|
|
if ( is_dash(c) ) {
|
|
c = get_next_char( begin, end );
|
|
}
|
|
}
|
|
|
|
*it_byte = get_value(c);
|
|
|
|
c = get_next_char( begin, end );
|
|
*it_byte <<= 4;
|
|
*it_byte |= get_value(c);
|
|
if ( *it_byte != 0U )
|
|
isEmpty = false;
|
|
}
|
|
|
|
// \ru Проверяем закрывающую скобку \en Check a closing parenthesis
|
|
if ( has_open_brace ) {
|
|
c = get_next_char( begin, end );
|
|
check_close_brace( c, open_brace_char );
|
|
}
|
|
|
|
u.isEmpty = isEmpty ? ts_positive : ts_negative;
|
|
return u;
|
|
}
|
|
|
|
private:
|
|
template <typename CharIterator>
|
|
typename std::iterator_traits<CharIterator>::value_type
|
|
get_next_char( CharIterator & begin, CharIterator end ) const {
|
|
if ( begin == end ) {
|
|
_ASSERT( false );
|
|
}
|
|
return *begin++;
|
|
}
|
|
|
|
unsigned char get_value( char c ) const {
|
|
static char const*const digits_begin = "0123456789abcdefABCDEF";
|
|
static char const*const digits_end = digits_begin + 22;
|
|
|
|
static unsigned char const values[] =
|
|
{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,10,11,12,13,14,15
|
|
, static_cast<unsigned char>(-1) };
|
|
|
|
char const * d = std::find( digits_begin, digits_end, c );
|
|
return values[d - digits_begin];
|
|
}
|
|
|
|
unsigned char get_value( wchar_t c ) const {
|
|
static wchar_t const*const digits_begin = L"0123456789abcdefABCDEF";
|
|
static wchar_t const*const digits_end = digits_begin + 22;
|
|
|
|
static unsigned char const values[] =
|
|
{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,10,11,12,13,14,15
|
|
, static_cast<unsigned char>(-1) };
|
|
|
|
wchar_t const * d = std::find( digits_begin, digits_end, c );
|
|
return values[d - digits_begin];
|
|
}
|
|
|
|
bool is_dash( char c ) const { return c == '-'; }
|
|
bool is_dash( wchar_t c ) const { return c == L'-'; }
|
|
|
|
// \ru Возвращаем открывающую скобку \en Return an opening parenthesis.
|
|
bool is_open_brace( char c ) const { return (c == '{'); }
|
|
bool is_open_brace( wchar_t c ) const { return (c == L'{'); }
|
|
|
|
bool check_close_brace( char c, char open_brace ) const {
|
|
if ( open_brace == '{' && c == '}' )
|
|
return true;
|
|
_ASSERT( false );
|
|
return false;
|
|
}
|
|
|
|
bool check_close_brace( wchar_t c, wchar_t open_brace ) const {
|
|
if ( open_brace == L'{' && c == L'}' )
|
|
return true;
|
|
_ASSERT( false );
|
|
return false;
|
|
}
|
|
};
|
|
|
|
|
|
struct hash8_generator
|
|
{
|
|
uint8 operator()( const MbUuid & trg ) const
|
|
{
|
|
static uint8 rand8[256] =
|
|
{
|
|
1, 14, 110, 25, 97, 174, 132, 119, 138, 170, 125, 118, 27, 233, 140, 51,
|
|
87, 197, 177, 107, 234, 169, 56, 68, 30, 7, 173, 73, 188, 40, 36, 65,
|
|
49, 213, 104, 190, 57, 211, 148, 223, 48, 115, 15, 2, 67, 186, 210, 28,
|
|
12, 181, 103, 70, 22, 58, 75, 78, 183, 167, 238, 157, 124, 147, 172, 144,
|
|
176, 161, 141, 86, 60, 66, 128, 83, 156, 241, 79, 46, 168, 198, 41, 254,
|
|
178, 85, 253, 237, 250, 154, 133, 88, 35, 206, 95, 116, 252, 192, 54, 221,
|
|
102, 218, 255, 240, 82, 106, 158, 201, 61, 3, 89, 9, 42, 155, 159, 93,
|
|
166, 80, 50, 34, 175, 195, 100, 99, 26, 150, 16, 145, 4, 33, 8, 189,
|
|
121, 64, 77, 72, 208, 245, 130, 122, 143, 55, 105, 134, 29, 164, 185, 194,
|
|
193, 239, 101, 242, 5, 171, 126, 11, 74, 59, 137, 228, 108, 191, 232, 139,
|
|
6, 24, 81, 20, 127, 17, 91, 92, 251, 151, 225, 207, 21, 98, 113, 112,
|
|
84, 226, 18, 214, 199, 187, 13, 32, 94, 220, 224, 212, 247, 204, 196, 43,
|
|
249, 236, 45, 244, 111, 182, 153, 136, 129, 90, 217, 202, 19, 165, 231, 71,
|
|
230, 142, 96, 227, 62, 179, 246, 114, 162, 53, 160, 215, 205, 180, 47, 109,
|
|
44, 38, 31, 149, 135, 0, 216, 52, 63, 23, 37, 69, 39, 117, 146, 184,
|
|
163, 200, 222, 235, 248, 243, 219, 10, 152, 131, 123, 229, 203, 76, 120, 209
|
|
};
|
|
|
|
uint8 h = 0;
|
|
MbUuid::const_iterator curr_iter = trg.cbegin(), end_iter = trg.cend();
|
|
while ( curr_iter != end_iter )
|
|
h = rand8[h ^ *curr_iter++];
|
|
return h;
|
|
}
|
|
};
|
|
|
|
|
|
#endif // _TOOL_UUID_H_
|