@ -19,6 +19,8 @@
# ifndef PG_WCHAR_H
# ifndef PG_WCHAR_H
# define PG_WCHAR_H
# define PG_WCHAR_H
# include "port/simd.h"
/*
/*
* The pg_wchar type
* The pg_wchar type
*/
*/
@ -704,25 +706,28 @@ extern WCHAR *pgwin32_message_to_UTF16(const char *str, int len, int *utf16len);
* Verify a chunk of bytes for valid ASCII .
* Verify a chunk of bytes for valid ASCII .
*
*
* Returns false if the input contains any zero bytes or bytes with the
* Returns false if the input contains any zero bytes or bytes with the
* high - bit set . Input len must be a multiple of 8 .
* high - bit set . Input len must be a multiple of the chunk size ( 8 or 16 ) .
*/
*/
static inline bool
static inline bool
is_valid_ascii ( const unsigned char * s , int len )
is_valid_ascii ( const unsigned char * s , int len )
{
{
const unsigned char * const s_end = s + len ;
const unsigned char * const s_end = s + len ;
uint64 chunk ,
Vector8 chunk ;
highbit_cum = UINT64CONST ( 0 ) ,
Vector8 highbit_cum = vector8_broadcast ( 0 ) ;
zero_cum = UINT64CONST ( 0x8080808080808080 ) ;
# ifdef USE_NO_SIMD
Vector8 zero_cum = vector8_broadcast ( 0x80 ) ;
# endif
Assert ( len % sizeof ( chunk ) = = 0 ) ;
Assert ( len % sizeof ( chunk ) = = 0 ) ;
while ( s < s_end )
while ( s < s_end )
{
{
memcpy ( & chunk , s , sizeof ( chunk ) ) ;
vector8_load ( & chunk , s ) ;
/* Capture any zero bytes in this chunk. */
# ifdef USE_NO_SIMD
/*
/*
* Capture any zero bytes in this chunk .
*
* First , add 0x7f to each byte . This sets the high bit in each byte ,
* First , add 0x7f to each byte . This sets the high bit in each byte ,
* unless it was a zero . If any resulting high bits are zero , the
* unless it was a zero . If any resulting high bits are zero , the
* corresponding high bits in the zero accumulator will be cleared .
* corresponding high bits in the zero accumulator will be cleared .
@ -733,21 +738,32 @@ is_valid_ascii(const unsigned char *s, int len)
* any input bytes did have the high bit set , it doesn ' t matter
* any input bytes did have the high bit set , it doesn ' t matter
* because we check for those separately .
* because we check for those separately .
*/
*/
zero_cum & = ( chunk + UINT64CONST ( 0x7f7f7f7f7f7f7f7f ) ) ;
zero_cum & = ( chunk + vector8_broadcast ( 0x7F ) ) ;
# else
/*
* Set all bits in each lane of the highbit accumulator where input
* bytes are zero .
*/
highbit_cum = vector8_or ( highbit_cum ,
vector8_eq ( chunk , vector8_broadcast ( 0 ) ) ) ;
# endif
/* Capture all set bits in this chunk. */
/* Capture all set bits in this chunk. */
highbit_cum | = chunk ;
highbit_cum = vector8_or ( highbit_cum , chunk ) ;
s + = sizeof ( chunk ) ;
s + = sizeof ( chunk ) ;
}
}
/* Check if any high bits in the high bit accumulator got set. */
/* Check if any high bits in the high bit accumulator got set. */
if ( highbit_cum & UINT64CONST ( 0x8080808080808080 ) )
if ( vector8_is_highbit_set ( highbit_cum ) )
return false ;
return false ;
# ifdef USE_NO_SIMD
/* Check if any high bits in the zero accumulator got cleared. */
/* Check if any high bits in the zero accumulator got cleared. */
if ( zero_cum ! = UINT64CONST ( 0x80808080808080 80 ) )
if ( zero_cum ! = vector8_broadcast ( 0x80 ) )
return false ;
return false ;
# endif
return true ;
return true ;
}
}